npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

egg-schedule

v4.0.1

Published

schedule plugin for egg, support corn job.

Downloads

90,373

Readme

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