Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/evanshortiss/node-cron-master
Easily manage and structure your "node-cron" CronJobs.
https://github.com/evanshortiss/node-cron-master
Last synced: 21 days ago
JSON representation
Easily manage and structure your "node-cron" CronJobs.
- Host: GitHub
- URL: https://github.com/evanshortiss/node-cron-master
- Owner: evanshortiss
- License: mit
- Created: 2015-10-14T21:29:36.000Z (about 9 years ago)
- Default Branch: master
- Last Pushed: 2022-04-07T16:06:25.000Z (over 2 years ago)
- Last Synced: 2024-09-19T05:37:54.568Z (about 2 months ago)
- Language: JavaScript
- Homepage:
- Size: 31.3 KB
- Stars: 1
- Watchers: 2
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
README
cron-master
===========[![build-status](https://travis-ci.org/evanshortiss/node-cron-master.svg?branch=master)
](https://travis-ci.org/evanshortiss/node-cron-master)[![npm version](https://badge.fury.io/js/cron-master.svg)
](https://badge.fury.io/js/cron-master.svg)[![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)
](https://standardjs.com)[![!Dependency Scan](https://snyk.io/test/github/evanshortiss/node-cron-master/badge.svg)
](https://snyk.io/org/evanshortiss/project/982f8d62-ce8e-4620-a1bf-b270166f7bac)[![TypeScript](https://badges.frapsoft.com/typescript/version/typescript-next.svg?v=101)](https://github.com/ellerbrock/typescript-badges/)cron-master provides a standardised way to manage your Node.js CronJobs created
using the cron module.Typically in projects we'll see instances of _CronJob_ from the fantastic `cron`
module scattered throughout the codebase meaning they're hard to find and not
managed in a consistent manner. cron-master encourages the pattern of storing
all jobs in a single location, and ensures they all follow the same pattern. It
also adds events to your _CronJob_ instances so you can add generic hooks for
logging, detecting errors, and preventing overlapping calls that can cause
unpredictable results.For example, if you have a job that runs every 5 minutes, did you remember to
ensure that next time it runs the previous run has completed!? cron-master
removes the need to check for that case, it simply won't let the same job run
again until the currently running call has completed.## Features
* Prevents a the same CronJob running more than once concurrently.
* Provides a structured way to create a manage jobs.
* Enables jobs to emit and receive events, also provides useful default events.
* Automatically computes time taken by each CronJob to complete.
* Provides an error and/or result from each job via an event and/or callback.## Install
Seemples!
```
npm install cron-master --save
```## API
### module.getInstance()
Factory function that returns manager instances.```js
const cmaster = require('cron-master');// This is our instance
const instance = cmaster.getInstance()
```### instance.loadJobs(absolutePath, callback)
Loads all jobs contained in the specified folder, and place them under the
managment of cron-master. Each file in the folder must have module.exports set
to an instance of CronMasterJob.As of version 0.2.0 the jobs are not cached. This means if you call load jobs
a second time with the same jobs, a new instance of the file containing the job
will be loaded. This means the _require.cache_ for the specifc cron files your
loading is deleted to prevent conflictsThe callback should be of the format _function(err, jobs)_. _jobs_ will be an
Array of the managed jobs that were loaded.```javascript
const path = require('path')
const cmaster = require('cron-master');
const manager = cmaster()instance.loadJobs(path.join(__dirname, '../', 'my-jobs'), function (err, jobs) {
if (err) {
console.error('Failed to load jobs!');
} else {
console.log('Loaded %d jobs!', jobs.length);
}
});
```#### instance.hasRunningJobs()
Returns a boolean indicating if any jobs are currently running.#### instance.getJobs()
Get an Array containing all currently loaded jobs.#### instance.getRunningJobs()
Get an Array containing all currently running jobs.#### instance.startJobs(callback)
Starts all jobs that are being managed so that they will be run at the time
specified by their cron tab. Internally this will call the cron module _start_
function for each job.#### instance.stopJobs(callback)
Stops all jobs being managed so they will no longer execute at the time
specified by their cron tab. If any jobs are currently in the middle of a tick
callback won't fire until they're all complete. Internally this will call the
cron module _stop_ function for each job. You can short circuit your job
function to stop early by by using the STOP_REQUESTED event, examples below.### module.EVENTS
A map of the event names, helps avoid spelling errors etc. Events:* TICK_STARTED - 'tick-started',
* START_REQUESTED - 'start-requested',
* TICK_COMPLETE - 'tick-complete',
* STOP_REQUESTED - 'stop-requested',
* STOPPED - 'stopped',
* TIME_WARNING - 'time-warning',
* OVERLAPPING_CALL - 'overlapping-call'Usage examples are included below.
### module.CronMasterJob
This is a replacement for _cron.CronJob_ (the `cron` module from npm) that you
usually use. It requires parameters to be passed in an Object.The function you usually pass as the _onTick_ parameter the cron module doesn't
take a callback, but when using cron-master you must accept a callback into
your cron _onTick_ function as shown below.Each job exposes the following functions for direct use if required:
#### instance.start([callback])
Starts the job so that it will run at the specified time(s).#### instance.forceRun([callback])
Force the job to run immediately even if already running.#### instance.run([callback])
Run the job if it is not currently in progress.#### instance.stop([callback])
Stop the job so that it will not run at the specified time(s).Here's a trivial example of creating a CronMasterJob:
```javascript
var CronMasterJob = require('cron-master').CronMasterJob;
module.exports = new CronMasterJob({
// Optional. Used to determine when to trigger the 'time-warning'. Fires after
// the provided number of milliseconds (e.g 2 minutes in the case below) has
// passed if the job has not called the done callback
timeThreshold: 2 * 60 * 1000,// Optional. Can be used to add useful meta data for a job
meta: {
name: 'Test Job'
},// Just the usual params that you pass to the "cron" module!
cronParams: {
cronTime: '* * * * * *',
onTick: function (job, done) {
console.log('Running job!');
done(null, 'ok');
}
}});
```## Examples
### Basic Job
```javascript
var CronMasterJob = require('cron-master').CronMasterJob;
module.exports = new CronMasterJob({
// The usual params that you pass to the "cron" module go here
cronParams: {
cronTime: '* * * * * *',
onTick: function (job, done) {
console.log('running job');
done(null, 'result');
}
}
});```
### Adding Events to Jobs
```javascript
var path = require('path')
, cmaster = require('cron-master');cmaster.loadJobs(path.join(__dirname, '../', 'my-jobs'), function (err, jobs) {
if (err) {
console.error('Failed to load jobs!');
} else {
jobs.forEach(function (job) {
// Using event map for name.
// Log output when the job is about to run.
job.on(cmaster.EVENTS.TICK_STARTED, function () {
console.log('Job tick starting!');
});// Using String for event name.
// Log output when the job has complete.
job.on('tick-complete', function (err, res, time) {
console.log('Job tick complete in %d!', time);
if (err) {
console.error('Error running job %s: %s', job.meta.name, err);
} else {
console.log('Job complete. Result: %s', res);
}
});job.on(events.TIME_WARNING, function () {
console.log('Job has %s exceeded expected run time!', job.meta.name);
});job.on('overlapping-call', function () {
console.log(
'Job %s attempting to run before previous tick is complete!',
job.meta.name
);
});
});
}
});
```### Advanved Job with Short Circuit
The job below runs every 2 minutes. Interestingly however, it binds a one time
event listener to see if the job was requested to stop. If so it will prevent
further execution and simply skip the business logic.```javascript
const CronMasterJob = require('cron-master').CronMasterJob
const async = require('async')
const db = require('lib/db-wrapper')/**
* Function to call for this cron job.
* @param {CronMaster} job Reference to the job itself, use for events.
* @param {Function} done Used to signal the job is finished.
*/
function cronFn (job, done) {
var stopped = false;// Let's use the job events to allow this job to be stopped mid process!
job.once('stop-requested', stopListener);function stopListener () {
stopped = true;
}function letterProcessor (letter, next) {
if (!stopped) {
// Do nothing, just skip since a stop was requested
next();
} else {
db.insert(letter, next);
}
}async.eachSeries(['a', 'b', 'c'], letterProcessor, function (err) {
// Remove event bindings to prevent memory leaks!
job.removeListener('stop-requested', stopListener);// Pass the result to the CronMasterJob callback
done(err);
});
}module.exports = new CronMasterJob({
// Optional. Used to determine when to trigger the 'time-warning'. Fires after
// the provided number of milliseconds (e.g 2 minutes in the case below) has
// passed if the job has not called the done callback
timeThreshold: (2 * 60 * 1000),// Just the usual params that you pass to the "cron" module!
cronParams: {
cronTime: '00 */2 * * * *',
onTick: cronFn
}});
```## Changelog
### 1.0.1
* Remove `EVENTS` from typings
* Fix return type for `loadJobs` in typings
* Fix `CronMasterJobOptions` to accept `meta` and `cronParams`### 1.0.0
* Changed public interface
* Added TypeScript typings
* Updated tests to use Jest
* Added coverage
* Added Synk
* Added StandardJS formatting### 0.3.0
* Renamed the _forceRun_ function to _run_ to reflect it's true behaviour
* Added _run_ function that will only run a job if it is not already running### 0.2.0
* Delete require cache for each job loaded
* Add function _hasRunningJobs()_
* Add function _getJobs()_
* Add function _getRunningJobs()_
* Improve test cases### 0.1.0
* Initial release