From e928c8c103d8f590cdabafbc47f24eab1e9314a9 Mon Sep 17 00:00:00 2001 From: Nick Campbell Date: Tue, 26 May 2020 22:51:12 -0400 Subject: [PATCH] GH-467 GH-478 GH-469 GH-470 GH-497 GH-498 - Allow soft warning when a hard error isn't required. Signed-off-by: Nick Campbell --- README.md | 5 +++++ lib/job.js | 6 ++++-- lib/time.js | 18 ++++++++++++------ 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index c099ed7f..059a9194 100644 --- a/README.md +++ b/README.md @@ -158,6 +158,11 @@ Parameter Based loop. For more information take a look at [timers#timers_timeout_unref](https://nodejs.org/api/timers.html#timers_timeout_unref) from the NodeJS docs. + - `softTimeout` - [OPTIONAL] - This module needs to determine the time at which to run. + However, there have been cases when an infinite loop can occur in this determination. + When `true`, the module will display a warning if the time has slipped by more than 5 + seconds trying to determine the next time to trigger the onTick. When `false`, this + will throw an exception stopping the execution. - `start` - Runs your job. - `stop` - Stops your job. - `setTime` - Stops and changes the time for the `CronJob`. Param must be a `CronTime`. diff --git a/lib/job.js b/lib/job.js index eb022628..0caa1cc8 100644 --- a/lib/job.js +++ b/lib/job.js @@ -33,7 +33,8 @@ function CronJob(CronTime, spawn) { context, runOnInit, utcOffset, - unrefTimeout + unrefTimeout, + softTimeout ) { var _cronTime = cronTime; var argCount = 0; @@ -54,12 +55,13 @@ function CronJob(CronTime, spawn) { _cronTime = cronTime.cronTime; utcOffset = cronTime.utcOffset; unrefTimeout = cronTime.unrefTimeout; + softTimeout = cronTime.softTimeout || true; // default to "opt in" soft timeout warning rather than throwing an exception if dwthe detecting a new time slips slightly. this can mean that an "infinite loop" is possible when trying to determine a new date } this.context = context || this; this._callbacks = []; this.onComplete = fnWrap(onComplete); - this.cronTime = new CronTime(_cronTime, timeZone, utcOffset); + this.cronTime = new CronTime(_cronTime, timeZone, utcOffset, softTimeout); this.unrefTimeout = unrefTimeout; addCallback.call(this, fnWrap(onTick)); diff --git a/lib/time.js b/lib/time.js index e09af4b0..38309a5b 100644 --- a/lib/time.js +++ b/lib/time.js @@ -66,8 +66,9 @@ const RE_WILDCARDS = /\*/g; const RE_RANGE = /^(\d+)(?:-(\d+))?(?:\/(\d+))?$/g; function CronTime(luxon) { - function CT(source, zone, utcOffset) { + function CT(source, zone, utcOffset, softTimeout) { this.source = source; + this.softTimeout = softTimeout; if (zone) { const dt = luxon.DateTime.fromObject({ zone: zone }); @@ -265,13 +266,18 @@ function CronTime(luxon) { // hard stop if the current date is after the expected execution if (Date.now() > timeout) { - throw new Error( - `Something went wrong. cron reached maximum iterations. + var msg = `Something went wrong. cron reached maximum iterations. Please open an issue (https://github.com/kelektiv/node-cron/issues/new) and provide the following string Time Zone: ${zone || '""'} - Cron String: ${this} - UTC offset: ${date.format( - 'Z' - )} - current Date: ${luxon.DateTime.local().toString()}` - ); + 'Z' + )} - current Date: ${luxon.DateTime.local().toString()}`; + + if (this.softTimeout) { + // a soft timeout here could allow for an infinite loop. to prevent this, set the soft timeout to true + console.warn(msg); + } else { + throw new Error(msg); + } } if (