Job will be executed twice
Hi, I define schedule like this
var festivalSchedule = later.parse.recur().on('10:00:00').time();
later.setInterval(function() {
d.run(function() {
log.debug('Festival Notify Factory Execute...');
festivalNotify.notify();
});
}, festivalSchedule);
But this Job will be executed twice. and this bug only happen in production environment( use pm2).
Can you help me to solve this problem.
Do you mean the task is executed twice immediately? Or is it executing twice at 10:00? If you only want to execute it once, would setTimeout work better for you?
Since it is only happening in one of your environments and I can't get it to reproduce on my machine, I unfortunately don't know what could be causing it. On your production server what does later.schedule(festivalSchedule).next(10) return? Did you happen to start the interval exactly at 10:00:00?
later.schedule(festivalSchedule).next(10) in my production server return
[
"2014-12-25T02:00:00.000Z",
"2014-12-26T02:00:00.000Z",
"2014-12-27T02:00:00.000Z",
"2014-12-28T02:00:00.000Z",
"2014-12-29T02:00:00.000Z",
"2014-12-30T02:00:00.000Z",
"2014-12-31T02:00:00.000Z",
"2015-01-01T02:00:00.000Z",
"2015-01-02T02:00:00.000Z",
"2015-01-03T02:00:00.000Z"
]
I see to logs, if I define a job will be executed in 10:00:00, it will be executed on 09:59:57 and 09:59:59. and i promise I only execute init function once.
And even more unfortunate this problem was happen not every time.
When somebody was having a similar issue it was because there was a problem somewhere else in their code. If you just run something like this:
var festivalSchedule = later.parse.recur().on('10:00:00').time();
later.setInterval(function() {
log.debug('Festival Notify Factory Execute...');
}, festivalSchedule);
Do you still see the double execution?
Hi, I replace later with node-schedule and this bug no longer occur in production environment.(with same code) I doubt this bug may cause by pm2
Edit: Ignore this, reading https://github.com/bunkat/later/issues/60#issuecomment-51303289 I now understand what I did wrong. I'll leave this reply anyway in case someone else finds this and might find it useful.
I too ran into this issue, and I have tried to figure it out for a about half a day now without coming anywhere (me being rather new to node.js and not used at all to Javascript doesn't really help).
I'll make a quick example of what I do. Let's take an example module, modules/schedules.js:
var later = require('later');
var jsonfile = require('jsonfile');
var schedules = [];
function findByTitle(title) {
for (var i = 0; i < schedules.length; i++) {
if (schedules[i].title === title) return i;
}
return null;
}
var backupRunner = function(title) {
return function() {
var scheduleIndex = findByTitle(title);
console.log(schedules[scheduleIndex].clients);
console.log(new Date());
};
};
var Schedule = {
loadSchedules: function() {
console.log("load schedules");
jsonfile.readFile('config/schedules.json', function(err, obj) {
if(err) {
console.log(err);
} else {
schedules = obj;
console.log("Schedules: " + schedules.length);
for(var i = 0; i < schedules.length; i++) {
console.log(schedules[i].title);
schedules[i].scheduleInstance = later.setInterval(backupRunner(schedules[i].title),
later.parse.text(schedules[i].when));
}
}
});
}
};
module.exports = Schedule;
config/schedules.json:
[
{
"title": "iii",
"when": "every 55 seconds",
"clients": [
{
"name": "devadmin"
}
],
"scheduleInstance": {}
},
{
"title": "kkkkk",
"when": "every 5 hours",
"clients": [
{
"name": "devadmin"
}
],
"scheduleInstance": {}
}
]
Then in app.js, I just do var schedules = require('./modules/schedules'); schedules.loadSchedules()
The output is the following:
"C:\Program Files (x86)\JetBrains\IntelliJ IDEA 14.0.2\bin\runnerw.exe" "C:\Program Files\nodejs\node.exe" bin\www
load schedules
Tue, 13 Jan 2015 09:36:40 GMT latertest Express server listening on port 3000
Schedules: 2
iii
kkkkk
[ { name: 'devadmin' } ]
Tue Jan 13 2015 10:36:55 GMT+0100 (W. Europe Standard Time)
[ { name: 'devadmin' } ]
Tue Jan 13 2015 10:37:00 GMT+0100 (W. Europe Standard Time)
Ass you can see, it run twice within 5 seconds of each other. The iii schedule is supposed to run every 55 seconds, but it is run every xx:xx:55 and xx:xx:00 seconds. Letting it run for a couple of minutes, it's obvious the interval is not the expected "every 55 seconds", it is actually every time the clock second is 55 and every time it's 00.
Here we have a definition issue, since "every 55 seconds" can mean either an interval of 55 seconds (what I wanted) (example: 10:00:55, 10:01:50...) but it could also mean every time the second is 55. According how I understand the documentation (// fires every 5 minutes every day var text2 = later.parse.text('every 5 mins');, I believe it should be what I expected, the first definition. However, it seems to be the latter definition and ALSO every xx:xx:00. So in this case we have a schedule that runs every minute, and 5 seconds after every minute.
If I change the interval from "every 55 seconds" to "every 30 seconds", it works as expected, every 00 and every 30 seconds.
If I change to "every 45 seconds" the issue shows up again, now it fires every xx:xx:45 and every xx:xx:00.
I noticed the time seems to be "snapped" to always assume the interval starts att xx:xx:00, and I believe this might contribute to the issue. On an interval of 30 seconds, it fires at xx:xx:00 and xx:xx:30, here one of the interval coincides with xx:xx:00, so it isn't a problem. However, when you have an interval that isn't run at xx:xx:00, you get the "every 1 minute" and at xx:xx:00 interval instead.
I dunno what I can help to fix it, but maybe it provides a clue.
I'm running Windows 7 64-bit, using IntelliJ 14 to run the code, node.js 0.10.33 and later 1.1.6.
Every 55 seconds doesn't mean what you think it means, I think that is causing some of the confusion. Later works by telling it what things should be considered valid (such as day = Tuesday, hour = 9 or 12, seconds = 0, 15, 30, 45, week number = 52). Later than finds a date where all of those things are true (in this case a Tuesday in week number 52 at 9:00:00 would be the first returned). This is one of the strengths of Later, the dates calculated are completely deterministic. By storing just the schedule, you can always calculate the same set of valid occurrences.
In the case of every, it starts at 0 and then increments based on the number you pass in. So every 55 seconds translates to seconds 0 and 55 as you discovered. You can also do offsets so you can say every 15 seconds starting on second 10 which would translate to seconds 10, 25, 40, and 55. If you ever want to know what Later thinks is valid, just do a console.log(sched) and print out the schedule.
If you want just 55 to be valid, you want the on constraint, not the every constraint. If you say on 55 seconds then it would only trigger when seconds is equal to 55.
If you really just need every 55 seconds starting from now than you probably don't really need Later, just specify a delay to setTimeout using the appropriate amount of milliseconds.
hi,
I'm still not sure I understand: I have been using later.js and either this hasn't happened for me before, or I haven't noticed it. — for a task I am running every 1 hours, it is run twice. this is unexpected and doesn't happen for another task in the same program that is executed every 10 mins:
// schedule
{ m: [ 0, 10, 20, 30, 40, 50 ] }
// next(2)
[ Wed Jun 03 2015 15:50:00 GMT+0200 (CEST),
Wed Jun 03 2015 16:00:00 GMT+0200 (CEST) ]
// schedule
{ h: [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 ] }
// next(2)
[ Wed Jun 03 2015 15:49:11 GMT+0200 (CEST), // ← start time of the program. at first I this seemed unexpected (expected 16:00:00), but it actually makes sense. probably 'on 0 mins' is what I want ...
Wed Jun 03 2015 16:00:00 GMT+0200 (CEST) ]
// output
// [...]
03-06-2015 15:50:00 i: <every 10 mins>
03-06-2015 16:00:00 i: <every 1 hours>
03-06-2015 16:00:00 i: <every 1 hours> // ← why twice?
03-06-2015 16:00:00 i: <every 10 mins>
// [...]