agenda
Version:
Light weight job scheduler for Node.js
85 lines (78 loc) • 2.93 kB
JavaScript
const debug = require('debug')('agenda:_findAndLockNextJob');
const utils = require('../utils');
const createJob = utils.createJob;
/**
* Find and lock jobs
* @param {String} jobName name of job to try to lock
* @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}
*/
module.exports = function(jobName, definition, cb) {
const self = this;
const now = new Date();
const lockDeadline = new Date(Date.now().valueOf() - definition.lockLifetime);
debug('_findAndLockNextJob(%s, [Function], cb)', jobName);
// Don't try and access MongoDB if we've lost connection to it.
// Trying to resolve crash on Dev PC when it resumes from sleep. NOTE: Does this still happen?
const s = this._mdb.s || this._mdb.db.s;
if (s.topology.connections().length === 0) {
if (s.topology.autoReconnect && !s.topology.isDestroyed()) {
// Continue processing but notify that Agenda has lost the connection
debug('Missing MongoDB connection, not attempting to find and lock a job');
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'));
}
} else {
/**
* Query used to find job to run
* @type {{$or: [*]}}
*/
const JOB_PROCESS_WHERE_QUERY = {
$or: [{
name: jobName,
lockedAt: null,
nextRunAt: {$lte: this._nextScanAt},
disabled: {$ne: true}
}, {
name: jobName,
lockedAt: {$exists: false},
nextRunAt: {$lte: this._nextScanAt},
disabled: {$ne: true}
}, {
name: jobName,
lockedAt: {$lte: lockDeadline},
disabled: {$ne: true}
}]
};
/**
* 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}}
*/
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);
}
if (err) {
debug('error occurred when running query to find and lock job');
}
cb(err, job);
});
}
};
;