Skip to content
Browse files

Merge pull request #40 from calmh/fix-long-sleep

Correctly handle long sleep times
  • Loading branch information...
2 parents 6cf764b + cca07d9 commit 7c7506e498c245987d97a1260363226cad5abfa5 @ncb000gt committed Jul 4, 2012
Showing with 59 additions and 6 deletions.
  1. +45 −6 lib/cron.js
  2. +14 −0 tests/test-cron.js
View
51 lib/cron.js
@@ -276,19 +276,58 @@ CronJob.prototype = {
*/
start: function() {
if(this.running) return;
+
+ var MAXDELAY = 2147483647; // The maximum number of milliseconds setTimeout will wait.
+ var self = this;
var timeout = this.cronTime.getTimeout();
+ var remaining = 0;
+
if (this.cronTime.realDate) this.runOnce = true;
+ // The callback wrapper checks if it needs to sleep another period or not
+ // and does the real callback logic when it's time.
+
+ function callbackWrapper() {
+
+ // If there is sleep time remaining, calculate how long and go to sleep
+ // again. This processing might make us miss the deadline by a few ms
+ // times the number of sleep sessions. Given a MAXDELAY of almost a
+ // month, this should be no issue.
+
+ if (remaining) {
+ if (remaining > MAXDELAY) {
+ remaining -= MAXDELAY;
+ timeout = MAXDELAY;
+ } else {
+ timeout = remaining;
+ remaining = 0;
+ }
+
+ self._timeout = setTimeout(callbackWrapper, timeout);
+ } else {
+
+ // We have arrived at the correct point in time.
+
+ self.running = false;
+
+ //start before calling back so the callbacks have the ability to stop the cron job
+ if (!(self.runOnce)) self.start();
+
+ self._callback();
+ }
+ }
+
if (timeout >= 0) {
this.running = true;
- this._timeout = setTimeout(function(self) {
- self.running = false;
- //start before calling back so the callbacks have the ability to stop the cron job
- if (!(self.runOnce)) self.start();
+ // Don't try to sleep more than MAXDELAY ms at a time.
+
+ if (timeout > MAXDELAY) {
+ remaining = timeout - MAXDELAY;
+ timeout = MAXDELAY;
+ }
- self._callback();
- }, timeout, this);
+ this._timeout = setTimeout(callbackWrapper, timeout);
} else {
this.stop();
}
View
14 tests/test-cron.js
@@ -293,5 +293,19 @@ module.exports = testCase({
assert.equal(count, 1);
assert.done();
}, 5250);
+ },
+ 'test long wait should not fire immediately': function(assert) {
+ assert.expect(1);
+ var count = 0;
+ var d = new Date().getTime() + 31 * 86400 * 1000;
+ var job = cron.job(new Date(d), function() {
+ assert.ok(false);
+ });
+ job.start();
+ setTimeout(function() {
+ job.stop();
+ assert.ok(true);
+ assert.done();
+ }, 250);
}
});

0 comments on commit 7c7506e

Please sign in to comment.
Something went wrong with that request. Please try again.