agenda
Advanced tools
Comparing version 2.3.0 to 3.0.0
@@ -6,2 +6,15 @@ Next | ||
3.0.0 / 2020-02-13 | ||
================== | ||
* Support MongoDB's Unified Topology Design ([#921](https://github.com/agenda/agenda/pull/921)) (Thanks @viktorzavadil!) | ||
* Fix: check that the new nextRunAt is different that the previous nextRunAt ([#863](https://github.com/agenda/agenda/pull/863)) (Thanks @RaphaelRheault!) | ||
* Update dependencies. Most notably MongoDB driver 3.4 → 3.5 ([#899](https://github.com/agenda/agenda/pull/899), [#900](https://github.com/agenda/agenda/pull/900), [#903](https://github.com/agenda/agenda/pull/903), [#906](https://github.com/agenda/agenda/pull/906), [#908](https://github.com/agenda/agenda/pull/908), [#910](https://github.com/agenda/agenda/pull/910), [#912](https://github.com/agenda/agenda/pull/912), [#913](https://github.com/agenda/agenda/pull/913), [#920](https://github.com/agenda/agenda/pull/920), [#922](https://github.com/agenda/agenda/pull/922)) | ||
* Documentation updates, thanks @MichielDeMey and @Sunghee2. ([#923](https://github.com/agenda/agenda/pull/923) & [#907](https://github.com/agenda/agenda/pull/907)) | ||
BREAKING | ||
-------- | ||
* Stop testing for Node.js 8. This might still work but we're no longer actively testing for it. ([#925](https://github.com/agenda/agenda/pull/925)) | ||
2.3.0 / 2019-12-16 | ||
@@ -8,0 +21,0 @@ ================== |
@@ -11,12 +11,11 @@ 'use strict'; | ||
* @param {Object} definition definition used to tell how job is run | ||
* @param {Function} cb called when job lock fails or passes | ||
* @access protected | ||
* @caller jobQueueFilling() only | ||
* @returns {undefined} | ||
* @returns Promise | ||
*/ | ||
module.exports = function(jobName, definition, cb) { | ||
module.exports = async function(jobName, definition) { | ||
const self = this; | ||
const now = new Date(); | ||
const lockDeadline = new Date(Date.now().valueOf() - definition.lockLifetime); | ||
debug('_findAndLockNextJob(%s, [Function], cb)', jobName); | ||
debug('_findAndLockNextJob(%s, [Function])', jobName); | ||
@@ -26,3 +25,3 @@ // Don't try and access MongoDB if we've lost connection to it. | ||
const s = this._mdb.s || this._mdb.db.s; | ||
if (s.topology.connections().length === 0) { | ||
if (s.topology.connections && s.topology.connections().length === 0 && !this._mongoUseUnifiedTopology) { | ||
if (s.topology.autoReconnect && !s.topology.isDestroyed()) { | ||
@@ -32,7 +31,6 @@ // Continue processing but notify that Agenda has lost the connection | ||
self.emit('error', new Error('Lost MongoDB connection')); | ||
cb(); | ||
} else { | ||
// No longer recoverable | ||
debug('topology.autoReconnect: %s, topology.isDestroyed(): %s', s.topology.autoReconnect, s.topology.isDestroyed()); | ||
cb(new Error('MongoDB connection is not recoverable, application restart required')); | ||
throw new Error('MongoDB connection is not recoverable, application restart required'); | ||
} | ||
@@ -59,28 +57,24 @@ } else { | ||
/** | ||
* Query used to set a job as locked | ||
* @type {{$set: {lockedAt: Date}}} | ||
*/ | ||
* Query used to set a job as locked | ||
* @type {{$set: {lockedAt: Date}}} | ||
*/ | ||
const JOB_PROCESS_SET_QUERY = {$set: {lockedAt: now}}; | ||
/** | ||
* Query used to affect what gets returned | ||
* @type {{returnOriginal: boolean, sort: object}} | ||
*/ | ||
* Query used to affect what gets returned | ||
* @type {{returnOriginal: boolean, sort: object}} | ||
*/ | ||
const JOB_RETURN_QUERY = {returnOriginal: false, sort: this._sort}; | ||
// Find ONE and ONLY ONE job and set the 'lockedAt' time so that job begins to be processed | ||
this._collection.findOneAndUpdate(JOB_PROCESS_WHERE_QUERY, JOB_PROCESS_SET_QUERY, JOB_RETURN_QUERY, (err, result) => { | ||
let job; | ||
if (!err && result.value) { | ||
debug('found a job available to lock, creating a new job on Agenda with id [%s]', result.value._id); | ||
job = createJob(self, result.value); | ||
} | ||
const result = await this._collection.findOneAndUpdate(JOB_PROCESS_WHERE_QUERY, JOB_PROCESS_SET_QUERY, JOB_RETURN_QUERY); | ||
if (err) { | ||
debug('error occurred when running query to find and lock job'); | ||
} | ||
let job; | ||
if (result.value) { | ||
debug('found a job available to lock, creating a new job on Agenda with id [%s]', result.value._id); | ||
job = createJob(self, result.value); | ||
} | ||
cb(err, job); | ||
}); | ||
return job; | ||
} | ||
}; |
@@ -54,2 +54,5 @@ const {EventEmitter} = require('events'); | ||
this.mongo(config.mongo, config.db ? config.db.collection : undefined, cb); | ||
if (config.mongo.s && config.mongo.topology && config.mongo.topology.s) { | ||
this._mongoUseUnifiedTopology = Boolean(config.mongo.topology.s.options.useUnifiedTopology); | ||
} | ||
} else if (config.db) { | ||
@@ -56,0 +59,0 @@ this.database(config.db.address, config.db.collection, config.db.options, cb); |
@@ -18,2 +18,3 @@ 'use strict'; | ||
const {repeatAt} = this.attrs; | ||
const previousNextRunAt = this.attrs.nextRunAt || new Date(); | ||
this.attrs.nextRunAt = undefined; | ||
@@ -41,3 +42,3 @@ | ||
let nextDate = cronTime._getNextDateFrom(lastRun); | ||
if (nextDate.valueOf() === lastRun.valueOf()) { | ||
if (nextDate.valueOf() === lastRun.valueOf() || nextDate.valueOf() <= previousNextRunAt.valueOf()) { | ||
// Handle cronTime giving back the same date for the next run time | ||
@@ -44,0 +45,0 @@ nextDate = cronTime._getNextDateFrom(dateForTimezone(new Date(lastRun.valueOf() + 1000))); |
@@ -86,3 +86,3 @@ 'use strict'; | ||
*/ | ||
function lockOnTheFly() { | ||
async function lockOnTheFly() { | ||
// Already running this? Return | ||
@@ -131,23 +131,18 @@ if (self._isLockingOnTheFly) { | ||
// Lock the job in MongoDB! | ||
self._collection.findOneAndUpdate(criteria, update, options, (err, resp) => { | ||
if (err) { | ||
throw err; | ||
} | ||
const resp = await self._collection.findOneAndUpdate(criteria, update, options); | ||
// Did the "job" get locked? Create a job object and run | ||
if (resp.value) { | ||
const job = createJob(self, resp.value); | ||
debug('found job [%s] that can be locked on the fly', job.attrs.name); | ||
self._lockedJobs.push(job); | ||
definitions[job.attrs.name].locked++; | ||
enqueueJobs(job); | ||
jobProcessing(); | ||
} | ||
if (resp.value) { | ||
const job = createJob(self, resp.value); | ||
debug('found job [%s] that can be locked on the fly', job.attrs.name); | ||
self._lockedJobs.push(job); | ||
definitions[job.attrs.name].locked++; | ||
enqueueJobs(job); | ||
jobProcessing(); | ||
} | ||
// Mark lock on fly is done for now | ||
self._isLockingOnTheFly = false; | ||
// Mark lock on fly is done for now | ||
self._isLockingOnTheFly = false; | ||
// Re-run in case anything is in the queue | ||
lockOnTheFly(); | ||
}); | ||
// Re-run in case anything is in the queue | ||
await lockOnTheFly(); | ||
} | ||
@@ -160,3 +155,3 @@ | ||
*/ | ||
function jobQueueFilling(name) { | ||
async function jobQueueFilling(name) { | ||
// Don't lock because of a limit we have set (lockLimit, etc) | ||
@@ -173,8 +168,4 @@ if (!shouldLock(name)) { | ||
// For this job name, find the next job to run and lock it! | ||
self._findAndLockNextJob(name, definitions[name], (err, job) => { | ||
if (err) { | ||
debug('[%s] job lock failed while filling queue', name); | ||
throw err; | ||
} | ||
try { | ||
const job = await self._findAndLockNextJob(name, definitions[name]); | ||
// Still have the job? | ||
@@ -190,6 +181,8 @@ // 1. Add it to lock list | ||
enqueueJobs(job); | ||
jobQueueFilling(name); | ||
await jobQueueFilling(name); | ||
jobProcessing(); | ||
} | ||
}); | ||
} catch (error) { | ||
debug('[%s] job lock failed while filling queue', name, error); | ||
} | ||
} | ||
@@ -196,0 +189,0 @@ |
{ | ||
"name": "agenda", | ||
"version": "2.3.0", | ||
"version": "3.0.0", | ||
"description": "Light weight job scheduler for Node.js", | ||
@@ -10,3 +10,3 @@ "main": "index.js", | ||
"engines": { | ||
"node": ">=8.0.0" | ||
"node": ">=10.0.0" | ||
}, | ||
@@ -46,3 +46,3 @@ "scripts": { | ||
"dependencies": { | ||
"cron": "~1.7.2", | ||
"cron": "~1.8.0", | ||
"date.js": "~0.3.3", | ||
@@ -52,3 +52,3 @@ "debug": "~4.1.1", | ||
"moment-timezone": "~0.5.27", | ||
"mongodb": "~3.4.0" | ||
"mongodb": "~3.5.0" | ||
}, | ||
@@ -60,16 +60,16 @@ "devDependencies": { | ||
"eslint-config-xo": "0.27.2", | ||
"eslint-plugin-ava": "9.0.0", | ||
"eslint-plugin-ava": "10.0.1", | ||
"eslint-plugin-eslint-comments": "3.1.2", | ||
"eslint-plugin-import": "2.19.1", | ||
"eslint-plugin-node": "10.0.0", | ||
"eslint-plugin-unicorn": "14.0.1", | ||
"eslint": "6.7.2", | ||
"eslint-plugin-import": "2.20.1", | ||
"eslint-plugin-node": "11.0.0", | ||
"eslint-plugin-unicorn": "16.1.1", | ||
"eslint": "6.8.0", | ||
"expect.js": "0.3.1", | ||
"jsdoc": "3.6.3", | ||
"jsdoc-template": "https://github.com/braintree/jsdoc-template", | ||
"mocha": "6.2.2", | ||
"mocha": "7.0.1", | ||
"mocha-lcov-reporter": "1.3.0", | ||
"q": "1.5.1", | ||
"sinon": "7.5.0", | ||
"xo": "0.25.3" | ||
"sinon": "8.1.1", | ||
"xo": "0.26.0" | ||
}, | ||
@@ -76,0 +76,0 @@ "xo": { |
@@ -52,3 +52,3 @@ <p align="center"> | ||
| REST API | | | ✓ | | ||
| Optimized for | Jobs / Messages | Jobs | Messages | Jobs | | ||
| Optimized for | Jobs / Messages | Messages | Jobs | | ||
@@ -954,3 +954,3 @@ _Kudos for making the comparison chart goes to [Bull](https://www.npmjs.com/package/bull#feature-comparison) maintainers._ | ||
jobTypes.forEach(type => { | ||
require('./lib/jobs/' + type)(agenda); | ||
require('./jobs/' + type)(agenda); | ||
}); | ||
@@ -957,0 +957,0 @@ |
110792
1580
+ Addedbl@2.2.1(transitive)
+ Addedcore-util-is@1.0.3(transitive)
+ Addedcron@1.8.3(transitive)
+ Addeddenque@1.5.1(transitive)
+ Addedinherits@2.0.4(transitive)
+ Addedisarray@1.0.0(transitive)
+ Addedluxon@1.28.1(transitive)
+ Addedmongodb@3.5.11(transitive)
+ Addedprocess-nextick-args@2.0.1(transitive)
+ Addedreadable-stream@2.3.8(transitive)
+ Addedsafe-buffer@5.1.2(transitive)
+ Addedstring_decoder@1.1.1(transitive)
+ Addedutil-deprecate@1.0.2(transitive)
- Removedcron@1.7.2(transitive)
- Removedmongodb@3.4.1(transitive)
Updatedcron@~1.8.0
Updatedmongodb@~3.5.0