UNPKG

agenda

Version:

Light weight job scheduler for Node.js

85 lines (78 loc) 2.93 kB
'use strict'; 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); }); } };