Socket
Socket
Sign inDemoInstall

agenda

Package Overview
Dependencies
17
Maintainers
5
Versions
88
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 2.0.2 to 2.1.0

12

History.md

@@ -6,2 +6,12 @@ Next

2.1.0 / 2019-09-09
==================
* Support async functions in job processing ([#653](https://github.com/agenda/agenda/pull/653)) (thanks @princjef!)
* Allow sorting and limiting jobs when searching ((#665)[https://github.com/agenda/agenda/pull/665]) (thank you @edwin-jones)
* Update MongoClient connection settings with `useNewUrlParser: true` to remove the deprecation warning. ([#806](https://github.com/agenda/agenda/pull/806)) (thanks @dpawson905!)
* Allow valid date strings when scheduling ([#808](https://github.com/agenda/agenda/pull/808)) (Thanks @wingsbob!)
* Update dependencies ([#820](https://github.com/agenda/agenda/pull/820))
* Update documentation (kudos @dandv, @pedruino and many others!)
* Fix linting errors ([#847](https://github.com/agenda/agenda/pull/847)) (thanks @dmbarreiro!)
2.0.2 / 2018-09-15

@@ -11,3 +21,3 @@ ==================

https://github.com/agenda/agenda/pull/674)
2.0.1 / 2018-08-30

@@ -14,0 +24,0 @@ ==================

9

lib/agenda/cancel.js

@@ -12,11 +12,12 @@ 'use strict';

*/
module.exports = function(query) {
module.exports = async function(query) {
debug('attempting to cancel all Agenda jobs', query);
return this._collection.deleteMany(query).then(({result}) => {
try {
const {result} = await this._collection.deleteMany(query);
debug('%s jobs cancelled', result.n);
return result.n;
}).catch(err => {
} catch (err) {
debug('error trying to delete jobs from MongoDB');
throw err;
});
}
};

@@ -29,3 +29,3 @@ 'use strict';

collection = collection || 'agendaJobs';
options = Object.assign({autoReconnect: true, reconnectTries: Number.MAX_SAFE_INTEGER, reconnectInterval: this._processEvery}, options);
options = Object.assign({autoReconnect: true, reconnectTries: Number.MAX_SAFE_INTEGER, reconnectInterval: this._processEvery, useNewUrlParser: true}, options);
MongoClient.connect(url, options, (error, client) => {

@@ -32,0 +32,0 @@ if (error) {

@@ -8,6 +8,6 @@ 'use strict';

* @function
* @param {Number} interval run every X interval
* @param {*} names String or strings of jobs to schedule
* @param {Object} data data to run for job
* @param {Object} options options to run job for
* @param {String|Number} interval - run every X interval
* @param {String|Array<String>} names - String or strings of jobs to schedule
* @param {Object} [data] - data to run for job
* @param {Object} [options] - options to run job for
* @returns {Promise} Job/s created. Resolves when schedule fails or passes

@@ -14,0 +14,0 @@ */

'use strict';
/**
* Given a mongo connection url will check if it contains the mongo
* @param url
* @returns {boolean}
* @param {string} url URL to be tested
* @returns {boolean} whether or not the url is a valid mongo URL
*/

@@ -7,0 +7,0 @@ module.exports = function(url) {

@@ -9,8 +9,14 @@ 'use strict';

* @param {Object} query object for MongoDB
* @param {Object} sort object for MongoDB
* @param {Number} limit number of documents to return from MongoDB
* @returns {Promise} resolves when fails or passes
*/
module.exports = async function(query) {
const result = await this._collection.find(query).toArray();
module.exports = async function(query = {}, sort = {}, limit = 0) {
const result = await this._collection
.find(query)
.sort(sort)
.limit(limit)
.toArray();
return result.map(job => createJob(this, job));
};

@@ -11,3 +11,2 @@ 'use strict';

* @param {Object} data data to pass to job
* @param {Function} cb called when job scheduling fails or passes
* @returns {Job} new job instance created

@@ -14,0 +13,0 @@ */

@@ -9,3 +9,3 @@ 'use strict';

* @function
* @param {Number} time time to process
* @param {Number|String} time - time to process, expressed in human interval
* @returns {exports} agenda instance

@@ -12,0 +12,0 @@ */

@@ -8,3 +8,3 @@ 'use strict';

* the job immediately or to let the processJobs() interval pick it up later
* @param {Error} err error passed in via MongoDB call as to whether modify call failed or passed
* @param {Job} job job instance
* @param {*} result the data returned from the findOneAndUpdate() call or insertOne() call

@@ -11,0 +11,0 @@ * @access private

@@ -10,3 +10,3 @@ 'use strict';

* @function
* @returns {Promise}
* @returns {Promise} resolves if db set beforehand, returns undefined otherwise
*/

@@ -13,0 +13,0 @@ module.exports = async function() {

@@ -21,3 +21,10 @@ 'use strict';

let finished = false;
const jobCallback = async err => {
// We don't want to complete the job multiple times
if (finished) {
return;
}
finished = true;
if (err) {

@@ -64,6 +71,6 @@ self.fail(err);

debug('[%s:%s] process function being called', self.attrs.name, self.attrs._id);
definition.fn(self, jobCallback);
await definition.fn(self, jobCallback);
} else {
debug('[%s:%s] process function being called', self.attrs.name, self.attrs._id);
definition.fn(self);
await definition.fn(self);
await jobCallback();

@@ -70,0 +77,0 @@ }

@@ -12,4 +12,7 @@ 'use strict';

module.exports = function(time) {
this.attrs.nextRunAt = (time instanceof Date) ? time : date(time);
const d = new Date(time);
this.attrs.nextRunAt = Number.isNaN(d.getTime()) ? date(time) : d;
return this;
};

@@ -265,3 +265,3 @@ 'use strict';

*/
function runOrRetry() {
async function runOrRetry() {
if (self._processInterval) {

@@ -289,5 +289,6 @@ if (jobDefinition.concurrency > jobDefinition.running && self._runningJobs.length < self._maxConcurrency) {

debug('[%s:%s] processing job', job.attrs.name, job.attrs._id);
job.run()
.catch(err => [err, job])
.then(job => processJobResult(...Array.isArray(job) ? job : [null, job]));
.then(job => processJobResult(...Array.isArray(job) ? job : [null, job])); // eslint-disable-line promise/prefer-await-to-then

@@ -294,0 +295,0 @@ // Re-run the loop to check for more jobs to process (locally)

{
"name": "agenda",
"version": "2.0.2",
"version": "2.1.0",
"description": "Light weight job scheduler for Node.js",

@@ -43,21 +43,21 @@ "main": "index.js",

"dependencies": {
"cron": "~1.3.0",
"date.js": "~0.3.2",
"debug": "~3.1.0",
"human-interval": "~0.1.3",
"moment-timezone": "~0.5.0",
"mongodb": "~3.1"
"cron": "~1.7.2",
"date.js": "~0.3.3",
"debug": "~4.1.1",
"human-interval": "~0.1.6",
"moment-timezone": "~0.5.26",
"mongodb": "~3.2.7"
},
"devDependencies": {
"blanket": "1.2.3",
"coveralls": "3.0.2",
"delay": "3.0.0",
"coveralls": "3.0.6",
"delay": "4.3.0",
"eslint": "4.9.0",
"expect.js": "0.3.1",
"jsdoc": "3.5.5",
"jsdoc": "3.6.3",
"jsdoc-template": "https://github.com/braintree/jsdoc-template",
"mocha": "5.2.0",
"mocha": "6.1.4",
"mocha-lcov-reporter": "1.3.0",
"q": "1.5.0",
"sinon": "6.1.4",
"q": "1.5.1",
"sinon": "7.3.2",
"xo": "0.21.1"

@@ -64,0 +64,0 @@ },

@@ -22,8 +22,8 @@ <p align="center">

- Mongo backed persistence layer.
- Promises based API
- Scheduling with configurable priority, concurrency, and repeating
- Promises based API.
- Scheduling with configurable priority, concurrency, and repeating.
- Scheduling via cron or human readable syntax.
- Event backed job queue that you can hook into.
- [Agendash](https://github.com/agenda/agendash): optional standalone web-interface
- [Agenda-rest](https://github.com/agenda/agenda-rest): optional standalone REST API
- [Agendash](https://github.com/agenda/agendash): optional standalone web-interface.
- [Agenda-rest](https://github.com/agenda/agenda-rest): optional standalone REST API.

@@ -37,16 +37,17 @@ ### Feature Comparison

| Feature | Bull | Kue | Bee | Agenda |
| :------------- |:-------------:|:-----:|:---:|:------:|
| Backend | redis | redis |redis| mongo |
| Priorities | ✓ | ✓ | | ✓ |
| Concurrency | ✓ | ✓ | ✓ | ✓ |
| Delayed jobs | ✓ | ✓ | | ✓ |
| Global events | ✓ | ✓ | | |
| Rate Limiter | ✓ | | | |
| Pause/Resume | ✓ | ✓ | | |
| Sandboxed worker| ✓ | | | |
| Repeatable jobs | ✓ | | | ✓ |
| Atomic ops | ✓ | | ✓ | |
| Persistence | ✓ | ✓ | ✓ | ✓ |
| UI | ✓ | ✓ | | ✓ |
| Feature | Bull | Bee | Agenda |
| :------------- |:-------------:|:---:|:------:|
| Backend | redis |redis| mongo |
| Priorities | ✓ | | ✓ |
| Concurrency | ✓ | ✓ | ✓ |
| Delayed jobs | ✓ | | ✓ |
| Global events | ✓ | | |
| Rate Limiter | ✓ | | |
| Pause/Resume | ✓ | | |
| Sandboxed worker| ✓ | | |
| Repeatable jobs | ✓ | | ✓ |
| Atomic ops | ✓ | ✓ | |
| Persistence | ✓ | ✓ | ✓ |
| UI | ✓ | | ✓ |
| REST API | | | ✓ |
| Optimized for | Jobs / Messages | Jobs | Messages | Jobs |

@@ -81,4 +82,4 @@

agenda.define('delete old users', (job, done) => {
User.remove({lastLogIn: {$lt: twoDaysAgo}}, done);
agenda.define('delete old users', async job => {
await User.remove({lastLogIn: {$lt: twoDaysAgo}});
});

@@ -97,5 +98,5 @@

```js
agenda.define('send email report', {priority: 'high', concurrency: 10}, (job, done) => {
agenda.define('send email report', {priority: 'high', concurrency: 10}, async job => {
const {to} = job.attrs.data;
emailClient.send({
await emailClient.send({
to,

@@ -105,3 +106,3 @@ from: 'example@example.com',

body: '...'
}, done);
});
});

@@ -188,42 +189,14 @@

### mongo(mongoClientInstance)
### mongo(dbInstance)
Use an existing mongodb-native MongoClient instance. This can help consolidate connections to a
database. You can instead use `.database` to have agenda handle connecting for
you.
Use an existing mongodb-native MongoClient/Db instance. This can help consolidate connections to a
database. You can instead use `.database` to have agenda handle connecting for you.
Please note that this must be a *collection*. Also, you will want to run the following
afterwards to ensure the database has the proper indexes:
You can also specify it during instantiation:
```js
(async () => {
await agenda._ready;
try {
agenda._collection.createIndex({
disabled: 1,
lockedAt: 1,
name: 1,
nextRunAt: 1,
priority: -1
}, {
name: 'findAndLockNextJobIndex'
});
} catch (err) {
console.log('Failed to create Agenda index!');
console.error(err);
throw err;
}
console.log('Agenda index created.');
})();
const agenda = new Agenda({mongo: mongoClientInstance.db('agenda-test')});
```
Note that MongoClient.connect() returns a mongoClientInstance since [node-mongodb-native 3.0.0](https://github.com/mongodb/node-mongodb-native/blob/master/CHANGES_3.0.0.md), while it used to return a dbInstance that could then be directly passed to agenda.
You can also specify it during instantiation.
```js
const agenda = new Agenda({mongo: mongoClientInstance});
```
### name(name)

@@ -259,3 +232,3 @@

that haven't run will still be locked, meaning that you may have to wait for the
lock to expire.
lock to expire. By default it is `'5 seconds'`.

@@ -336,4 +309,5 @@ ```js

A job will unlock if it is finished (ie. `done` is called) before the `lockLifetime`.
The lock is useful if the job crashes or times out.
A job will unlock if it is finished (ie. the returned Promise resolves/rejects
or `done` is specified in the params and `done()` is called) before the
`lockLifetime`. The lock is useful if the job crashes or times out.

@@ -376,5 +350,7 @@ ```js

Defines a job with the name of `jobName`. When a job of `jobName` gets run, it
will be passed to `fn(job, done)`. To maintain asynchronous behavior, you must
call `done()` when you are processing the job. If your function is synchronous,
you may omit `done` from the signature.
will be passed to `fn(job, done)`. To maintain asynchronous behavior, you may
either provide a Promise-returning function in `fn` *or* provide `done` as a
second parameter to `fn`. If `done` is specified in the function signature, you
must call `done()` when you are processing the job. If your function is
synchronous or returns a Promise, you may omit `done` from the signature.

@@ -387,3 +363,3 @@ `options` is an optional argument which can overwrite the defaults. It can take

- `lockLifetime`: `number` interval in ms of how long the job stays locked for (see [multiple job processors](#multiple-job-processors) for more info).
A job will automatically unlock if `done()` is called.
A job will automatically unlock once a returned promise resolves/rejects (or if `done` is specified in the signature and `done()` is called).
- `priority`: `(lowest|low|normal|high|highest|number)` specifies the priority

@@ -406,2 +382,11 @@ of the job. Higher priority jobs will run first. See the priority mapping

```js
agenda.define('some long running job', async job => {
const data = await doSomelengthyTask();
await formatThatData(data);
await sendThatData(data);
});
```
Async Job (using `done`):
```js
agenda.define('some long running job', (job, done) => {

@@ -424,5 +409,8 @@ doSomelengthyTask(data => {

`define()` acts like an assignment: if `define(jobName, ...)` is called multiple times (e.g. every time your script starts), the definition in the last call will overwrite the previous one. Thus, if you `define` the `jobName` only once in your code, it's safe for that call to execute multiple times.
## Creating Jobs
### every(interval, name, [data], [options], [cb])
### every(interval, name, [data], [options])

@@ -440,4 +428,4 @@ Runs job `name` at the given `interval`. Optionally, data and options can be passed in.

`options` is an optional argument that will be passed to `job.repeatEvery`. In order to use
this argument, `data` must also be specified.
`options` is an optional argument that will be passed to [`job.repeatEvery`](#repeateveryinterval-options).
In order to use this argument, `data` must also be specified.

@@ -451,8 +439,6 @@ `cb` is an optional callback function which will be called when the job has been

```js
agenda.define('printAnalyticsReport', (job, done) => {
User.doSomethingReallyIntensive((err, users) => {
processUserData();
console.log('I print a report!');
done();
});
agenda.define('printAnalyticsReport', async job => {
const users = await User.doSomethingReallyIntensive();
processUserData(users);
console.log('I print a report!');
});

@@ -472,3 +458,3 @@

### schedule(when, name, [data], [cb])
### schedule(when, name, [data])

@@ -490,3 +476,3 @@ Schedules a job to run `name` once at a given time. `when` can be a `Date` or a

Optionally, `name` could be array of job names, similar to `every` method.
Optionally, `name` could be array of job names, similar to the `every` method.

@@ -499,3 +485,3 @@ ```js

### now(name, [data], [cb])
### now(name, [data])

@@ -507,5 +493,2 @@ Schedules a job to run `name` once immediately.

`cb` is an optional callback function which will be called when the job has been
persisted in the database.
Returns the `job`.

@@ -524,5 +507,4 @@

const job = agenda.create('printAnalyticsReport', {userCount: 100});
job.save(err => {
console.log('Job successfully saved');
});
await job.save();
console.log('Job successfully saved');
```

@@ -533,9 +515,8 @@

### jobs(mongodb-native query)
### jobs(mongodb-native query, mongodb-native sort, mongodb-native limit)
Lets you query all of the jobs in the agenda job's database. This is a full [mongodb-native](https://github.com/mongodb/node-mongodb-native)
`find` query. See mongodb-native's documentation for details.
Lets you query (then sort and limit the result) all of the jobs in the agenda job's database. These are full [mongodb-native](https://github.com/mongodb/node-mongodb-native) `find`, `sort` and `limit` commands. See mongodb-native's documentation for details.
```js
const jobs = await agenda.jobs({name: 'printAnalyticsReport'});
const jobs = await agenda.jobs({name: 'printAnalyticsReport'}, {data:-1}, 3);
// Work with jobs (see below)

@@ -576,4 +557,4 @@ ```

Starts the job queue processing, checking `processEvery` time to see if there
are new jobs.
Starts the job queue processing, checking [`processEvery`](#processeveryinterval) time to see if there
are new jobs. Must be called *after* `processEvery`, and *before* any job scheduling (e.g. `every`).

@@ -621,3 +602,4 @@ ### stop

When a job is finished (ie. `done` is called), it will automatically unlock.
When a job is finished (i.e. the returned promise resolves/rejects or `done` is
specified in the signature and `done()` is called), it will automatically unlock.

@@ -627,3 +609,3 @@ ## Manually working with a job

A job instance has many instance methods. All mutating methods must be followed
with a call to `job.save()` in order to persist the changes to the database.
with a call to `await job.save()` in order to persist the changes to the database.

@@ -645,3 +627,3 @@

job.repeatEvery('10 minutes');
job.save();
await job.save();
```

@@ -653,3 +635,3 @@

});
job.save();
await job.save();
```

@@ -661,3 +643,3 @@

});
job.save();
await job.save();
```

@@ -671,3 +653,3 @@

job.repeatAt('3:30pm');
job.save();
await job.save();
```

@@ -681,3 +663,3 @@

job.schedule('tomorrow at 6pm');
job.save();
await job.save();
```

@@ -692,3 +674,3 @@

job.priority('low');
job.save();
await job.save();
```

@@ -703,15 +685,14 @@

- `insertOnly`: `boolean` will prevent any properties from persisting if job already exists. Defaults to false.
- `insertOnly`: `boolean` will prevent any properties from persisting if the job already exists. Defaults to false.
```js
job.unique({'data.type': 'active', 'data.userId': '123', nextRunAt(date)});
job.save();
await job.save();
```
*IMPORTANT:* To avoid high CPU usage by MongoDB, Make sure to create an index on the used fields, like: `data.type` and `data.userId` for the example above.
*IMPORTANT:* To avoid high CPU usage by MongoDB, make sure to create an index on the used fields, like `data.type` and `data.userId` for the example above.
### fail(reason)
Sets `job.attrs.failedAt` to `now`, and sets `job.attrs.failReason`
to `reason`.
Sets `job.attrs.failedAt` to `now`, and sets `job.attrs.failReason` to `reason`.

@@ -722,6 +703,6 @@ Optionally, `reason` can be an error, in which case `job.attrs.failReason` will

```js
job.fail('insuficient disk space');
job.fail('insufficient disk space');
// or
job.fail(new Error('insufficient disk space'));
job.save();
await job.save();
```

@@ -740,23 +721,25 @@

### save(callback)
### save()
Saves the `job.attrs` into the database.
Saves the `job.attrs` into the database. Returns a Promise resolving to a Job instance, or rejecting on error.
```js
job.save(err => {
if (!err) {
console.log('Successfully saved job to collection');
}
});
try {
await job.save();
cosole.log('Successfully saved job to collection');
} catch (e) {
console.error('Error saving job to collection');
}
```
### remove(callback)
### remove()
Removes the `job` from the database.
Removes the `job` from the database. Returns a Promise resolving to the number of jobs removed, or rejecting on error.
```js
job.remove(err => {
if (!err) {
console.log('Successfully removed job from collection');
}
try {
await job.remove();
console.log('Successfully removed job from collection');
} catch (e) {
console.error('Error removing job from collection');
});

@@ -780,10 +763,8 @@ ```

```js
agenda.define('super long job', (job, done) => {
(async () => {
await doSomeLongTask();
await job.touch();
await doAnotherLongTask();
await job.touch();
await finishOurLongTasks();
})().then(done, done);
agenda.define('super long job', async job => {
await doSomeLongTask();
await job.touch();
await doAnotherLongTask();
await job.touch();
await finishOurLongTasks();
});

@@ -828,3 +809,3 @@ ```

agenda.on('fail:send email', (err, job) => {
console.log('Job failed with error: ${err.message}');
console.log(`Job failed with error: ${err.message}`);
});

@@ -883,3 +864,3 @@ ```

### Spawning / forking processes.
### Spawning / forking processes

@@ -993,12 +974,8 @@ Ultimately Agenda can work from a single job queue across multiple machines, node processes, or forks. If you are interested in having more than one worker, [Bars3s](http://github.com/bars3s) has written up a fantastic example of how one might do it:

module.exports = function(agenda) {
agenda.define('registration email', (job, done) => {
User.get(job.attrs.data.userId, (err, user) => {
if (err) {
return done(err);
}
email(user.email(), 'Thanks for registering', 'Thanks for registering ' + user.name(), done);
});
agenda.define('registration email', async job => {
const user = await User.get(job.attrs.data.userId);
await email(user.email(), 'Thanks for registering', 'Thanks for registering ' + user.name());
});
agenda.define('reset password', (job, done) => {
agenda.define('reset password', async job => {
// Etc

@@ -1005,0 +982,0 @@ });

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc