Reputation: 5196
I'm trying to schedule out social media posts for up to 6 months in advance. I'm using node-cron, which was inspired by gnu cron. I set a script to run every second to log 'tick!' for testing. However if this nodeJS service restarts or goes down the job is lost.
I thought node-cron affected Crontab, but Crontab -l
returns no crontab for kevindanikowski
.
Is there a different (better) way I should schedule jobs months in advance?
Or is there something about node-cron I'm missing to make sure I don't lose the cronjob?
Upvotes: 0
Views: 1033
Reputation: 113866
For really long term timers you need to store the timeout data on disk somehow. As you mentioned, if you do it purely in memory you will lose timing information if the server restarts.
The way to handle this is simple. It's the same algorithm cron uses:
Record when you want the timeout to occur on disk - the format is up to you, you may use the cron format or invent your own. Since it's javascript I'd be tempted to simply record in in JSON format.
Read the timing file into your program. There are two ways you can do this. If you are concerned about run-time performance then read it once when your program starts. However this means you need to restart your server if you edit the file. If you want updates to the file to be picked up automatically then read it every time you want to process timing events.
Run a timer loop periodically. Cron for example has a resolution of one minute. Therefore cron runs a timer loop every one minute. If that's good enough than run every one minute. For me I'd do a setInterval()
every 30 seconds or so. Note that running an timer loop every second isn't that heavy in javascript on any decent processor.
Process the timer events from the file in the timer loop. Loop through all events and check to see if they have expired.
That's it. This is how all scheduling systems work (google calendar, cron etc.).
Here's a very simple javascript implementation:
var events = require("events.js");
// Assume events.js look something like:
// return [ {
// timeout: <millisecs like what Date.now() returns>,
// callback: <function>
// } ]
setInterval(function(){
var now = Date.now();
events.forEach(e=>{
if (e.timeout >= now) {
e.callback(); // execute event
}
});
events = events.filter(e=>e.timeout<now); // remove stale events
},10000); // every 10 seconds
You can add fancy features like saving current events to disk if there are any changes to it from the code, make the timeout format human readable for debugging, define a system to pass arguments to event callback etc. But the core is very simple.
Upvotes: 1