jaclarke/cronosjs

Question about OS time changes

Closed this issue · 3 comments

Hi again.

I have a question regarding what happens to Cron and date sequences when the os time changes. Does cronosjs handle this? If not, would you consider it?

I ask as recently, on a node-red forum thread here an issue was found on a different Cron library on raspberry pi where the application started before the clock was updated (pi does not have a RTC)

I am hoping your library handles os time changes so users have a solution.

Off the top of my head, if you store the current now OS time and periodically check for time changes, then any change above or below a programmable option, you internally update the schedules. This feature could be disabled by default for compatibility.

Is this is something you might look to handle?

Please let me know.

If not, I believe in my application I could handle it (less gracefully) by recreating every schedule the user entered but it will be a dirty hack ;)

Currently the library doesn't have any special handling for OS time changes. It just calculates how many seconds to the next cron execution time from the current time reported by the OS, and then uses setTimeout to wait until then. If the OS time changes during that timeout it will trigger at the wrong time.

As far as I know, there's no specific api for listening for OS time changes in JS (or node), so as you said you're left with just polling for changes to the time (or maybe in node creating a native module to access system api's eg. https://stackoverflow.com/questions/2251635/how-to-detect-change-of-system-time-in-linux), though this seems a bit out of scope for this library.

My proposed solution would be to add an api to cronosjs to allow you to refresh the internal timer (so you don't have to re-create all the schedules), leaving you free to use whatever method works best for your application to detect OS time changes.

For example, something like:

import { refreshSchedulerTimer } from 'cronosjs'

const pollInterval = 10 * 60000
const skewThreshold = 1000

let lastTimestamp = Date.now()
function checkClockChange() {
  const clockSkew = Date.now() - lastTimestamp - pollInterval
  if (Math.abs(clockSkew) > skewThreshold) {
    refreshSchedulerTimer()
  }
  lastTimestamp = Date.now()
  setTimeout(checkClockChange, pollInterval)
}
setTimeout(checkClockChange, pollInterval)

For now, I have handled this internally - recreating schedules on time change.
Please close this issue if you wish.

Thanks as always.
Steve.

Ok, the refreshSchedulerTimer() function mentioned above has now also been implemented in 1.7.0.