Coder Social home page Coder Social logo

egg-schedule's Introduction

egg-schedule

NPM version Node.js CI Test coverage Known Vulnerabilities npm download

A schedule plugin for egg, has been built-in plugin for egg enabled by default.

It's fully extendable for a developer and provides a simple built-in TimerStrategy.

Usage

Just add your job file to {app_root}/app/schedule.

// {app_root}/app/schedule/cleandb.js
const Subscription = require('egg').Subscription;

class CleanDB extends Subscription {
  /**
   * @property {Object} schedule
   *  - {String} type - schedule type, `worker` or `all` or your custom types.
   *  - {String} [cron] - cron expression, see [below](#cron-style-scheduling)
   *  - {Object} [cronOptions] - cron options, see [cron-parser#options](https://github.com/harrisiirak/cron-parser#options)
   *  - {String | Number} [interval] - interval expression in millisecond or express explicitly like '1h'. see [below](#interval-style-scheduling)
   *  - {Boolean} [immediate] - To run a scheduler at startup
   *  - {Boolean} [disable] - whether to disable a scheduler, usually use in dynamic schedule
   *  - {Array} [env] - only enable scheduler when match env list
   */
  static get schedule() {
    return {
      type: 'worker',
      cron: '0 0 3 * * *',
      // interval: '1h',
      // immediate: true,
    };
  }

  async subscribe() {
    await this.ctx.service.db.cleandb();
  }
}

module.exports = CleanDB;

You can also use function simply like:

exports.schedule = {
  type: 'worker',
  cron: '0 0 3 * * *',
  // interval: '1h',
  // immediate: true,
};

exports.task = async function (ctx) {
  await ctx.service.db.cleandb();
};

Overview

egg-schedule supports both cron-based scheduling and interval-based scheduling.

Schedule decision is being made by agent process. agent triggers a task and sends a message to worker process. Then, one or all worker process(es) execute the task based on schedule type.

To setup a schedule task, simply create a job file in {app_root}/app/schedule. A file contains one job and exports schedule and task properties.

The rule of thumbs is one job per file.

Task

Task is a class which will be instantiated with every schedule, and a subscribe method will be invoked.

You can get anonymous context with this.ctx.

  • ctx.method: SCHEDULE
  • ctx.path: /__schedule?path=${schedulePath}&${schedule}.

To create a task, subscribe can be a generator function or async function. For example:

// A simple logger example
const Subscription = require('egg').Subscription;
class LoggerExample extends Subscription {
  async subscribe() {
    this.ctx.logger.info('Info about your task');
  }
}
// A real world example: wipe out your database.
// Use it with caution. :)
const Subscription = require('egg').Subscription;
class CleanDB extends Subscription {
  async subscribe() {
    await this.ctx.service.db.cleandb();
  }
}

Scheduling

schedule is an object that contains one required property, type, and optional properties, { cron, cronOptions, interval, immediate, disable, env }.

Cron-style Scheduling

Use cron-parser.

Note: cron-parser support second as optional that is not supported by linux crontab.

@hourly / @daily / @weekly / @monthly / @yearly is also supported.

*    *    *    *    *    *
┬    ┬    ┬    ┬    ┬    ┬
│    │    │    │    │    |
│    │    │    │    │    └ day of week (0 - 7) (0 or 7 is Sun)
│    │    │    │    └───── month (1 - 12)
│    │    │    └────────── day of month (1 - 31)
│    │    └─────────────── hour (0 - 23)
│    └──────────────────── minute (0 - 59)
└───────────────────────── second (0 - 59, optional)

Example:

// To execute task every 3 hours
exports.schedule = {
  type: 'worker',
  cron: '0 0 */3 * * *',
  cronOptions: {
    // tz: 'Europe/Athens',
  }
};

Interval-style Scheduling

To use setInterval, and support ms conversion style

Example:

// To execute task every 3 hours
exports.schedule = {
  type: 'worker',
  interval: '3h',
};

Notice: Egg built-in TimerStrategy will schedule each execution at a fix rate, regardless of its execution time. So you have to make sure that your actual execution time of your task/subscribe must be smaller than your delay time.

Schedule Type

Build-in support is:

  • worker: will be executed in one random worker when a schedule runs.
  • all: will be executed in all workers when a schedule runs.

Custom schedule:

To create a custom schedule, simply extend agent.ScheduleStrategy and register it by agent.schedule.use(type, clz). You can schedule the task to be executed by one random worker or all workers with the built-in method this.sendOne(...args) or this.sendAll(...args) which support params, it will pass to subscribe(...args) or task(ctx, ...args).

// {app_root}/agent.js
module.exports = function(agent) {
  class CustomStrategy extends agent.ScheduleStrategy {
    start() {
      // such as mq / redis subscribe
      agent.notify.subscribe('remote_task', data => {
        this.sendOne(data);
      });
    }
  }
  agent.schedule.use('custom', CustomStrategy);
};

Then you could use it to defined your job:

// {app_root}/app/schedule/other.js
const Subscription = require('egg').Subscription;
class ClusterTask extends Subscription {
  static get schedule() {
    return {
      type: 'custom',
    };
  }
  async subscribe(data) {
    console.log('got custom data:', data);
    await this.ctx.service.someTask.run();
  }
}
module.exports = ClusterTask;

Dynamic schedule

// {app_root}/app/schedule/sync.js
module.exports = app => {
  class SyncTask extends app.Subscription {
    static get schedule() {
      return {
        interval: 10000,
        type: 'worker',
        // only start task when hostname match
        disable: require('os').hostname() !== app.config.sync.hostname,
        // only start task at prod mode
        env: [ 'prod' ],
      };
    }
    async subscribe() {
      await this.ctx.sync();
    }
  }
  return SyncTask;
}

Configuration

Logging

See ${appInfo.root}/logs/{app_name}/egg-schedule.log which provided by config.customLogger.scheduleLogger.

// config/config.default.js
config.customLogger = {
  scheduleLogger: {
    // consoleLevel: 'NONE',
    // file: path.join(appInfo.root, 'logs', appInfo.name, 'egg-schedule.log'),
  },
};

Customize directory

If you want to add additional schedule directories, you can use this config.

// config/config.default.js
config.schedule = {
  directory: [
    path.join(__dirname, '../app/otherSchedule'),
  ],
};

Testing

app.runSchedule(scheduleName) is provided by egg-schedule plugin only for test purpose.

Example:

it('test a schedule task', async function () {
  // get app instance
  await app.runSchedule('clean_cache');
});

Questions & Suggestions

Please open an issue here.

License

MIT

egg-schedule's People

Contributors

atian25 avatar cwtuan avatar dead-horse avatar fengmk2 avatar jedmeng avatar killagu avatar luomusha avatar ngot avatar popomore avatar samwu4166 avatar vyasriday avatar zhennann avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.