Comparing version 0.5.10 to 0.6.1
0.6.1 / 2014-03-24 | ||
================== | ||
* allow every and schedule to take array of job names | ||
0.6.0 / 2014-03-21 (NO BREAKING CHANGES) | ||
================== | ||
* convert to using setTimeout for precise job scheduling [closes #6] | ||
0.5.10/ 2014-03-20 | ||
@@ -3,0 +13,0 @@ ================== |
@@ -86,16 +86,48 @@ var Job = require('./job.js'), | ||
Agenda.prototype.every = function(interval, name, data) { | ||
var job; | ||
job = this.create(name, data); | ||
job.attrs.type = 'single'; | ||
job.repeatEvery(interval); | ||
job.save(); | ||
return job; | ||
Agenda.prototype.every = function(interval, names, data) { | ||
var self = this; | ||
if (typeof names === 'string') { | ||
return createJob(interval, names, data); | ||
} else if (names instanceof Array) { | ||
return createJobs(interval, names, data); | ||
} | ||
function createJob(interval, name, data) { | ||
var job; | ||
job = self.create(name, data); | ||
job.attrs.type = 'single'; | ||
job.repeatEvery(interval); | ||
job.save(); | ||
return job; | ||
} | ||
function createJobs(interval, names, data) { | ||
return names.map(function (name) { | ||
return createJob(interval, name, data); | ||
}); | ||
} | ||
}; | ||
Agenda.prototype.schedule = function(when, name, data) { | ||
var job = this.create(name, data); | ||
job.schedule(when); | ||
job.save(); | ||
return job; | ||
Agenda.prototype.schedule = function(when, names, data) { | ||
var self = this; | ||
if (typeof names === 'string') { | ||
return createJob(when, names, data); | ||
} else if (names instanceof Array) { | ||
return createJobs(when, names, data); | ||
} | ||
function createJob(when, name, data) { | ||
var job = self.create(name, data); | ||
job.schedule(when); | ||
job.save(); | ||
return job; | ||
} | ||
function createJobs(when, names, data) { | ||
return names.map(function (name) { | ||
return createJob(when, name, data); | ||
}); | ||
} | ||
}; | ||
@@ -111,3 +143,4 @@ | ||
Agenda.prototype.saveJob = function(job, cb) { | ||
var fn = cb; | ||
var fn = cb, | ||
self = this; | ||
@@ -141,6 +174,10 @@ var props = job.toJSON(), | ||
if(Array.isArray(res)) { | ||
job.attrs._id = res[0]._id; | ||
} else if(typeof res == 'object') { | ||
job.attrs._id = res._id; | ||
res = res[0]; | ||
} | ||
job.attrs._id = res._id; | ||
job.attrs.nextRunAt = res.nextRunAt; | ||
if(job.attrs.nextRunAt < self._nextScanAt) | ||
processJobs.call(self, job); | ||
} | ||
@@ -180,3 +217,3 @@ | ||
{ | ||
nextRunAt: {$lte: now}, | ||
nextRunAt: {$lte: this._nextScanAt}, | ||
$or: [ | ||
@@ -230,3 +267,3 @@ {lockedAt: null}, | ||
function processJobs() { | ||
function processJobs(extraJob) { | ||
var definitions = this._definitions, | ||
@@ -237,7 +274,20 @@ jobName, | ||
for (jobName in definitions) { | ||
jobQueueFilling(jobName); | ||
if(!extraJob) { | ||
for (jobName in definitions) { | ||
jobQueueFilling(jobName); | ||
} | ||
} else { | ||
// On the fly lock a job | ||
var now = new Date(); | ||
self._db.findAndModify({ _id: extraJob.attrs._id, lockedAt: null }, {}, { $set: { lockedAt: now } }, function(err, resp) { | ||
if(resp) { | ||
jobQueue.unshift(extraJob); | ||
jobProcessing(); | ||
} | ||
}); | ||
} | ||
function jobQueueFilling(name) { | ||
var now = new Date(); | ||
self._nextScanAt = new Date(now.valueOf() + self._processEvery), | ||
self._findAndLockNextJob(name, definitions[name], function (err, job) { | ||
@@ -261,2 +311,4 @@ if(err) { | ||
var now = new Date(); | ||
var job = jobQueue.pop(), | ||
@@ -266,12 +318,18 @@ name = job.attrs.name, | ||
if(jobDefinition.concurrency > jobDefinition.running && | ||
self._runningJobs < self._maxConcurrency) { | ||
if(job.attrs.nextRunAt < now) runOrRetry(); | ||
else setTimeout(runOrRetry, job.attrs.nextRunAt - now); | ||
self._runningJobs++; | ||
jobDefinition.running++; | ||
function runOrRetry() { | ||
if(jobDefinition.concurrency > jobDefinition.running && | ||
self._runningJobs < self._maxConcurrency) { | ||
job.run(processJobResult); | ||
jobProcessing(); | ||
} else { | ||
jobQueue.unshift(job); | ||
self._runningJobs++; | ||
jobDefinition.running++; | ||
job.run(processJobResult); | ||
jobProcessing(); | ||
} else { | ||
// Put on top to run ASAP | ||
jobQueue.push(job); | ||
} | ||
} | ||
@@ -278,0 +336,0 @@ } |
{ | ||
"name": "agenda", | ||
"version": "0.5.10", | ||
"version": "0.6.1", | ||
"description": "Light weight job scheduler for Node.js", | ||
@@ -42,4 +42,4 @@ "main": "index.js", | ||
"blanket": "~1.1.5", | ||
"q": "*" | ||
"q": "~1.0.0" | ||
} | ||
} |
@@ -124,5 +124,12 @@ # Agenda | ||
Specifies the frequency at which agenda will query the database looking for jobs | ||
that need to be processed. If your jobs are time sensitive, you will want to | ||
specify a low value. | ||
that need to be processed. Agenda internally uses `setTimeout` to guarantee that | ||
jobs run at (close to ~3ms) the right time. | ||
Decreasing the frequency will result in fewer database queries, but more jobs | ||
being stored in memory. | ||
Also worth noting is that if the job is queue is shutdown, any jobs stored in memory | ||
that haven't run will still be locked, meaning that you may have to wait for the | ||
lock to expire. | ||
```js | ||
@@ -248,2 +255,11 @@ agenda.processEvery('1 minute'); | ||
Optionally, `name` could be array of job names, which is convenient for scheduling | ||
different jobs for same `interval`. | ||
```js | ||
agenda.every('15 minutes', ['printAnalyticsReport', 'sendNotifications', 'updateUserRecords']); | ||
``` | ||
In this case, `every` returns array of `jobs`. | ||
### schedule(when, name, data) | ||
@@ -259,3 +275,2 @@ | ||
```js | ||
@@ -265,2 +280,10 @@ agenda.schedule('tomorrow at noon', 'printAnalyticsReport', {userCount: 100}); | ||
Optionally, `name` could be array of job names, similar to `every` method. | ||
```js | ||
agenda.schedule('tomorrow at noon', ['printAnalyticsReport', 'sendNotifications', 'updateUserRecords']); | ||
``` | ||
In this case, `schedule` returns array of `jobs`. | ||
### now(name, data) | ||
@@ -296,3 +319,3 @@ | ||
Lets you query all of the jobs in the agenda job's database. This is a full [mongoskin](https://github.com/kissjs/node-mongoskin) | ||
Lets you query all of the jobs in the agenda job's database. This is a full [mongoskin](https://github.com/kissjs/node-mongoskin) | ||
`find` query. See mongoskin's documentation for details. | ||
@@ -534,3 +557,3 @@ | ||
console.log('start job server: ' + cluster.worker.id); | ||
require('./app/job-worker');//initialize the agenda here | ||
require('./app/job-worker');//initialize the agenda here | ||
} | ||
@@ -537,0 +560,0 @@ } |
@@ -134,2 +134,7 @@ var mongoCfg = 'localhost:27017/agenda-test', | ||
}); | ||
describe('with array of names specified', function () { | ||
it('returns array of jobs', function () { | ||
expect(jobs.every('5 minutes', ['send email', 'some job'])).to.be.an('array'); | ||
}); | ||
}); | ||
}); | ||
@@ -147,2 +152,7 @@ | ||
}); | ||
describe('with array of names specified', function () { | ||
it('returns array of jobs', function () { | ||
expect(jobs.schedule('5 minutes', ['send email', 'some job'])).to.be.an('array'); | ||
}); | ||
}); | ||
}); | ||
@@ -149,0 +159,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
48313
901
596