Home > other >  Node.js, command line data processing, queue up 43,200 setTimeouts at once?
Node.js, command line data processing, queue up 43,200 setTimeouts at once?

Time:01-23

I want to process an event every 10 seconds, exactly on the 10 second mark all day every weekday. More than about a second late or early is a problem.

I'll manually start the app up every Sunday evening, and shut it down every Saturday morning. There are 43,200 x 10 second blocks for a five day week.

I already have an array with all those 43,200 times in it (needed for other parts of the app).

I could potentially do this with setInterval, or with a setTimeout where the callback sets another setTimeout afterwards. I'm having issues with both those -- for a separate question/post if the following won't work.

So third option: 14,200x setTimeout all racked up at once. If I start the app on Sunday evening and run this:

datesArray.forEach(theDate => {
    ms = theDate.valueOf() - Date.Now();
    setTimeout(eventFn, ms)
}

where datesArray has 14K elements... are there technical limits to where a large number of setTimeouts break down or drift, or anything else?

More specifically:

  1. Assuming my hardware has enough resources to handle each event when it happens, can racking up a lot of setTimeouts at once break anything, overload anything, cause them to mess with each other in any way, etc?
  2. Is setTimeout reliable enough such that an event running 4-5 days after it's set up, will run at the exact right time, or is there any chance it will drift or anything like that?
  3. Are there any other reasons this would be a bad idea? Or... is this a technically sound approach?

Please note, SO doesn't like opinion-based questions. I'm not asking people's opinions here on whether you like this idea or not, or whether there are other ways to do this. Feel free to volunteer any of that if you want, but specifically, I'm asking if this is technically sound, based on limits with JS, node, setTimeout, etc. as they're documented/technically defined (assuming they are, somewhere)?

Thanks!

CodePudding user response:

I share your concerns about scheduling thousands of timers.

The desired behavior could be achieved in the following way:

// 43200 Date objects
const dates = [
    new Date(2023, 0, 22, 12, 56, 0),
    new Date(2023, 0, 22, 12, 56, 10),
    new Date(2023, 0, 22, 12, 56, 20),
    new Date(2023, 0, 22, 12, 56, 30),
    new Date(2023, 0, 22, 12, 56, 40),
];

const eventFn = () => {
    console.log('event', new Date());
};

let nowDate = new Date();
let dateIndex = dates.findIndex((date) => nowDate < date);

const scheduleNextRun = (scheduled) => {
    if (scheduled) {
        eventFn();
    }
    if (dateIndex >= 0 && dateIndex < dates.length) {
        nowDate = new Date();
        setTimeout(() => scheduleNextRun(true), dates[dateIndex].getTime() - nowDate.getTime());
        dateIndex   ;
    }
};

scheduleNextRun(false);

The output of my test run was:

event 2023-01-22T01:56:10.003Z
event 2023-01-22T01:56:20.001Z
event 2023-01-22T01:56:30.001Z
event 2023-01-22T01:56:40.001Z

The error is between 1-3 msec which sounds acceptable based on your requirements.

Benefits of this approach:

  • Code can be started at any moment, and it will find the next run date/time
  • Only one timer is scheduled at a time
  • Lightweight and easy to follow
  • Stops automatically after all events executed

Please let me know if this helps.

  • Related