function Job(args) { args = args || {}; // Remove special args this.agenda = args.agenda; delete args.agenda; // Process args args.priority = parsePriority(args.priority) || 0; // Set attrs to args var attrs = {}; for (var key in args) { if (args.hasOwnProperty(key)) { attrs[key] = args[key]; } } // Set defaults if undefined attrs.nextRunAt = attrs.nextRunAt || new Date(); attrs.type = attrs.type || 'once'; this.attrs = attrs; }
n/a
function EventEmitter() { EventEmitter.init.call(this); }
n/a
function Job(args) { args = args || {}; // Remove special args this.agenda = args.agenda; delete args.agenda; // Process args args.priority = parsePriority(args.priority) || 0; // Set attrs to args var attrs = {}; for (var key in args) { if (args.hasOwnProperty(key)) { attrs[key] = args[key]; } } // Set defaults if undefined attrs.nextRunAt = attrs.nextRunAt || new Date(); attrs.type = attrs.type || 'once'; this.attrs = attrs; }
n/a
computeNextRunAt = function () { var interval = this.attrs.repeatInterval; var timezone = this.attrs.repeatTimezone; var repeatAt = this.attrs.repeatAt; this.attrs.nextRunAt = undefined; if (interval) { computeFromInterval.call(this); } else if (repeatAt) { computeFromRepeatAt.call(this); } return this; function dateForTimezone (d) { d = moment(d); if(timezone) d.tz(timezone); return d; } function computeFromInterval() { var lastRun = this.attrs.lastRunAt || new Date(); lastRun = dateForTimezone(lastRun); try { var cronTime = new CronTime(interval); var nextDate = cronTime._getNextDateFrom(lastRun); if (nextDate.valueOf() == lastRun.valueOf()) { // Handle cronTime giving back the same date for the next run time nextDate = cronTime._getNextDateFrom(dateForTimezone(new Date(lastRun.valueOf() + 1000))); } this.attrs.nextRunAt = nextDate; } catch (e) { // Nope, humanInterval then! try { if (!this.attrs.lastRunAt && humanInterval(interval)) { this.attrs.nextRunAt = lastRun.valueOf(); } else { this.attrs.nextRunAt = lastRun.valueOf() + humanInterval(interval); } } catch (e) {} } finally { if (isNaN(this.attrs.nextRunAt)) { this.attrs.nextRunAt = undefined; this.fail('failed to calculate nextRunAt due to invalid repeat interval'); } } } function computeFromRepeatAt() { var lastRun = this.attrs.lastRunAt || new Date(); var nextDate = date(repeatAt).valueOf(); var offset = Date.now(); // if you do not specify offset date for below test it will fail for ms if (offset === date(repeatAt,offset).valueOf()) { this.attrs.nextRunAt = undefined; this.fail('failed to calculate repeatAt time due to invalid format'); } else if (nextDate.valueOf() == lastRun.valueOf()) { this.attrs.nextRunAt = date('tomorrow at ', repeatAt); } else { this.attrs.nextRunAt = date(repeatAt); } } }
...
var self = this,
agenda = self.agenda,
definition = agenda._definitions[self.attrs.name];
var setImmediate = setImmediate || process.nextTick;
setImmediate(function() {
self.attrs.lastRunAt = new Date();
self.computeNextRunAt();
self.save(function() {
var jobCallback = function(err) {
if (err) {
self.fail(err);
}
self.attrs.lastFinishedAt = new Date();
...
disable = function () { this.attrs.disabled = true; return this; }
n/a
enable = function () { this.attrs.disabled = false; return this; }
n/a
fail = function (reason) { if(reason instanceof Error) { reason = reason.message; } this.attrs.failReason = reason; this.attrs.failCount = (this.attrs.failCount || 0) + 1; this.attrs.failedAt = new Date(); return this; }
...
Sets `job.attrs.failedAt` to `now`, and sets `job.attrs.failReason`
to `reason`.
Optionally, `reason` can be an error, in which case `job.attrs.failReason` will
be set to `error.message`
```js
job.fail('insuficient disk space');
// or
job.fail(new Error('insufficient disk space'));
job.save();
```
### run(callback)
...
isRunning = function () { if (!this.attrs.lastRunAt) return false; if (!this.attrs.lastFinishedAt) return true; if (this.attrs.lockedAt && this.attrs.lastRunAt.getTime() > this.attrs.lastFinishedAt.getTime()) { return true; } return false; }
n/a
priority = function (priority) { this.attrs.priority = parsePriority(priority); return this; }
...
### priority(priority)
Specifies the `priority` weighting of the job. Can be a number or a string from
the above priority table.
```js
job.priority('low');
job.save();
```
### unique(properties, [options])
Ensure that only one instance of this job exists with the specified properties
...
remove = function (cb) {
// refactored NF 21/04/2015
this.agenda.cancel( {_id: this.attrs._id}, cb );
/*
var self = this;
this.agenda._db.remove({_id: this.attrs._id}, function(err, count) {
if(err) {
return cb(err);
}
cb(err, count);
});
*/
}
...
// or pass additional connection options:
// var agenda = new Agenda({db: {address: mongoConnectionString, collection: "jobCollectionName", options: {server:{auto_reconnect
:true}}}});
// or pass in an existing mongodb-native MongoClient instance
// var agenda = new Agenda({mongo: myMongoClient});
agenda.define('delete old users', function(job, done) {
User.remove({lastLogIn: { $lt: twoDaysAgo }}, done);
});
agenda.on('ready', function() {
agenda.every('3 minutes', 'delete old users');
// Alternatively, you could also do:
agenda.every('*/3 * * * *', 'delete old users');
...
repeatAt = function (time) { this.attrs.repeatAt = time; return this; }
...
```
### repeatAt(time)
Specifies a `time` when the job should repeat. [Possible values](https://github.com/matthewmueller/date#examples)
```js
job.repeatAt('3:30pm');
job.save();
```
### schedule(time)
Specifies the next `time` at which the job should run.
...
repeatEvery = function (interval, options) { options = options || {}; this.attrs.repeatInterval = interval; this.attrs.repeatTimezone = options.timezone ? options.timezone : null; return this; }
...
agenda.start();
});
```
```js
agenda.on('ready', function() {
var weeklyReport = agenda.create('send email report', {to: 'another-guy@example.com'})
weeklyReport.repeatEvery('1 week').save();
agenda.start();
});
```
# Full documentation
Agenda's basic control structure is an instance of an agenda. Agenda's are
...
run = function (cb) { var self = this, agenda = self.agenda, definition = agenda._definitions[self.attrs.name]; var setImmediate = setImmediate || process.nextTick; setImmediate(function() { self.attrs.lastRunAt = new Date(); self.computeNextRunAt(); self.save(function() { var jobCallback = function(err) { if (err) { self.fail(err); } self.attrs.lastFinishedAt = new Date(); self.attrs.lockedAt = null; self.save(function(saveErr, job) { cb && cb(err || saveErr, job); if (err) { agenda.emit('fail', err, self); agenda.emit('fail:' + self.attrs.name, err, self); } else { agenda.emit('success', self); agenda.emit('success:' + self.attrs.name, self); } agenda.emit('complete', self); agenda.emit('complete:' + self.attrs.name, self); }); }; try { agenda.emit('start', self); agenda.emit('start:' + self.attrs.name, self); if (!definition) { throw new Error('Undefined job'); } if (definition.fn.length === 2) { definition.fn(self, jobCallback); } else { definition.fn(self); jobCallback(); } } catch (e) { jobCallback(e); } }); }); }
...
### run(callback)
Runs the given `job` and calls `callback(err, job)` upon completion. Normally
you never need to call this manually.
```js
job.run(function(err, job) {
console.log("I don't know why you would need to do this...");
});
```
### save(callback)
Saves the `job.attrs` into the database.
...
save = function (cb) { this.agenda.saveJob(this, cb); return this; }
...
agenda.start();
});
```
```js
agenda.on('ready', function() {
var weeklyReport = agenda.create('send email report', {to: 'another-guy@example.com'})
weeklyReport.repeatEvery('1 week').save();
agenda.start();
});
```
# Full documentation
Agenda's basic control structure is an instance of an agenda. Agenda's are
...
schedule = function (time) { this._scheduled = true; this.attrs.nextRunAt = (time instanceof Date) ? time : date(time); return this; }
...
from: 'example@example.com',
subject: 'Email Report',
body: '...'
}, done);
});
agenda.on('ready', function() {
agenda.schedule('in 20 minutes', 'send email report', {to: '
admin@example.com'});
agenda.start();
});
```
```js
agenda.on('ready', function() {
var weeklyReport = agenda.create('send email report', {to: 'another-guy@example.com'})
...
toJSON = function () { // create a persistable Mongo object -RR var self = this, attrs = self.attrs || {}; var result = {}; for (var prop in attrs) { if (attrs.hasOwnProperty(prop)) { result[prop] = attrs[prop]; } } var dates = ['lastRunAt', 'lastFinishedAt', 'nextRunAt', 'failedAt', 'lockedAt']; dates.forEach(function(d) { if (result[d]) { result[d] = new Date(result[d]); } }); return result; }
n/a
touch = function (cb) { this.attrs.lockedAt = new Date(); this.save(cb); }
...
Resets the lock on the job. Useful to indicate that the job hasn't timed out
when you have very long running jobs.
```js
agenda.define('super long job', function(job, done) {
doSomeLongTask(function() {
job.touch(function() {
doAnotherLongTask(function() {
job.touch(function() {
finishOurLongTasks(done);
});
});
});
});
...
unique = function (unique, opts) { this.attrs.unique = unique; this.attrs.uniqueOpts = opts; return this; }
...
`options` is an optional argument which can overwrite the defaults. It can take
the following:
- `insertOnly`: `boolean` will prevent any properties from persisting if job already exists. Defaults to false.
```js
job.unique({'data.type': 'active', 'data.userId': '
;123', nextRunAt(date)});
job.save();
```
### fail(reason)
Sets `job.attrs.failedAt` to `now`, and sets `job.attrs.failReason`
to `reason`.
...