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`.
...