-
Notifications
You must be signed in to change notification settings - Fork 639
lastDate()/lastExecution does not reflect the last execution of the registered callback(s) #1048
Description
Description
As originally described in the issue #710 the method lastDate() and therefore lastExecution indicate the moment when the last time was checked, if the next execution can be triggered and not when.
In the following section we are able to see that the lastExecution property will be set to the current Date before fireOnTick was even called.
Lines 336 to 344 in d6f7c4a
| // we have arrived at the correct point in time. | |
| this.lastExecution = new Date(); | |
| this._isActive = false; | |
| // start before calling back so the callbacks have the ability to stop the cron job | |
| if (!this.runOnce) this.start(); | |
| void this.fireOnTick(); |
I think this is a bug as the variable name, lastExecution, and method description lastDate: Provides the last execution date. indicate information about the last execution rather the last tick as it's otherwise indicated by the methods
nextDate: Indicates the subsequent date that will activate anonTick.
nextDates(count): Supplies an array of upcoming dates that will initiate an onTick.
I think currently we are seeing more likely the information about the lastTick or lastStart if you will.
Expected Behavior
lastDate() and lastExecution actually represent the moment when the callback(s) where invoked.
Actual Behavior
lastDate() and lastExecution represent the moment of the last check if the callback(s) can be invoked and will be updated on each iteration even without invoking any callback.
Possible Fix
Set lastExecution after setting _isCallbackRunning = true at:
Line 248 in d6f7c4a
| this._isCallbackRunning = true; |
Drop setting lastExecution at:
Line 130 in d6f7c4a
this.lastExecution = new Date(); Line 337 in d6f7c4a
this.lastExecution = new Date(); Line 367 in d6f7c4a
this.lastExecution = new Date();
Steps to Reproduce
import { CronJob } from 'cron';
console.log('=== Issue: lastExecution changes while callback is running ===\n');
console.log('Cron: every 5 seconds');
console.log('Callback: takes 60 seconds');
console.log('waitForCompletion: true (should prevent overlapping executions)\n');
let callbackStartTime: Date | null = null;
const callback = async () => {
callbackStartTime = new Date();
console.log(`🔵 Callback STARTED at: ${callbackStartTime.toISOString()}\n`);
await new Promise((resolve) => setTimeout(resolve, 60000)); // 60 seconds
console.log(`🟢 Callback COMPLETED at: ${new Date().toISOString()}\n`);
callbackStartTime = null;
};
const job = new CronJob('*/5 * * * * *', callback, null, true, null, null, false, null, false, true);
// Monitor every 2 seconds
setInterval(() => {
const now = new Date();
const actual = job.lastExecution;
const isRunning = job.isCallbackRunning;
if (!actual) return;
console.log(`[${now.toISOString()}]`);
console.log(` isCallbackRunning: ${isRunning}`);
console.log(` ACTUAL lastExecution: ${actual.toISOString()}`);
if (callbackStartTime) {
console.log(` EXPECTED lastExecution: ${callbackStartTime.toISOString()}`);
const diff = actual.getTime() - callbackStartTime.getTime();
if (Math.abs(diff) > 100) {
console.log(` ❌ DIFFERENCE: ${diff}ms`);
console.log(' ❌ lastExecution changed while callback is STILL RUNNING!');
} else {
console.log(' ✅ lastExecution matches callback start time');
}
}
console.log('');
}, 2000);
setTimeout(() => {
job.stop();
console.log('\n=== Summary ===');
console.log('Problem: lastExecution updates every 5s even though callback is still running');
console.log('Expected: lastExecution should stay constant until callback completes');
console.log('Solution: Set lastExecution in fireOnTick() after isCallbackRunning = true');
process.exit(0);
}, 65000);Context
We want to monitor our cron's and know if they maybe take longer as they should or they are not invoked anymore besides that the callback is not running.
At least for us it's no solution to work with the threshold and timeout to execute the callback(s) even if its still running.
Your Environment
cronversion: 4.4.0- NodeJS version: 25.7.0
- Operating System and version: Debian 13
- TypeScript version (if applicable): 5.9.3
- Link to your project (if applicable): not possible to provide, sorry