Search code examples
javascriptnode.jstimer

Is setTimeout safe for scheduling jobs over large spans of time?


I'm writing an application in Node.js that needs to schedule functions to be run at specific times. Hours or sometimes days in the future. Currently, I'm doing so with something similar to this:

const now = Date.now();
const later = getSomeFutureTimestamp();
setTimeout(function() {
  // do something
}, later - now);

I'm wondering if setTimeout is the proper tool for this job or if there is a tool more suited for long intervals of time. One thing to note is I don't need great precision; if the job runs within a few minutes of the scheduled time, everything should still be fine.


Solution

  • setTimeout should be fine. It's only really delayed if there's blocking code running at the moment when it's meant to execute. So setTimeout is typically 20 milliseconds late. But since your margin is minutes, I don't think it'll be an issue.

    However, I'd suggest storing the timestamp at which things should trigger, and just periodically check. That way you only have 1 timer running at any given time.

    You also get to keep your timestamps as absolute timestamps - not as relative, "milliseconds in the future" values. That also lets you store them between server restarts, which you can't do as easily with relative times. With your code, the only record of a job being queued is that there's a timer running. If that timer disappears for any reason, you lose all record of a job having been scheduled.

    Something like:

    function checkForScheduledJobs() {
      var now = Date.now(),
          job;
    
      // assuming here that the jobs array is sorted earliest to latest
      while(jobs.length && jobs[0].timestamp < now) {
        jobs.shift().callback();
      }
    
      setTimeout(checkForScheduledJobs, 60000); // check each minute
    }
    

    You just need to kick it off once. This could be done in an addScheduledJob function (which would also sort the jobs array after adding something to it, etc.)