darkterra / mongo-scheduler

Persistent event schedule for node.js using mongo as storage
MIT License
8 stars 8 forks source link

Duplicated Events #14

Closed dfliess closed 5 years ago

dfliess commented 5 years ago

Hi @darkterra

I found that some cron event's are being fired twice.

I think that the issue is here: https://github.com/darkterra/mongo-scheduler/blob/04dfb87814bce8c6f51fd7017841df637c42c3f5/lib/scheduler.js#L108

You are rescheduling in the next second and maybe the parser.next may return that it's the same minute. Not sure the best way to solve it but maybe you can pass the parser currentDate as the next time you will poll ...but should think better what can happen with expressions that repeat by seconds.

Here you have an example that reproduce this:

const moment = require('moment');
const msm = require('mongo-scheduler-more');
const scheduler =  new msm('mongodb://localhost:27017/test');

scheduler.purge({ force: true }, ()=> {
  scheduler.on('test', (e)=> console.log('Test Event', e));

  const now = moment();
  const time = now.clone().add(1,'minutes');
  const expr = `* ${time.minutes()} ${time.hours()} * * ${time.day()}`;
  console.log('Now:',now.toDate());
  console.log('Setting to fire in next minute', time.toDate(), expr);

  scheduler.schedule({
    name: 'test',
    cron: expr
  })

});

This was the output after waiting for 2 minutes or 2 polls

Now: 2019-06-19T21:40:48.795Z
Setting to fire in next minute 2019-06-19T21:41:48.795Z * 41 18 * * 3
Test Event { _id: 5d0aabe0cce03f4230927821,
  status: 'ready',
  name: 'test',
  storage: { collection: null, query: null, id: null },
  conditions: { after: 2019-06-19T21:41:00.000Z, endDate: null },
  cron: '* 41 18 * * 3',
  data: null,
  options: { emitPerDoc: false } }
Test Event { _id: 5d0aabe0cce03f4230927821,
  status: 'ready',
  name: 'test',
  storage: { collection: null, query: null, id: null },
  conditions: { after: 2019-06-19T21:41:50.000Z, endDate: null },
  cron: '* 41 18 * * 3',
  data: null,
  options: { emitPerDoc: false } }

image

dfliess commented 5 years ago

Hi @darkterra, do you have any idea on how we should fix this, I can help but maybe this is a big change.

darkterra commented 5 years ago

Hello @dfliess,

There is no error in the operation of the Mongo Scheduler More module.

By default, MSM queries the database every 60 sec (60000 mili sec) to see if there are any events to trigger.

This condition "cron": 41 18 * 3 is true every second on day number 3 (Wednesday) at 18:41.

So with the default conf and your condition "cron" you have ~ 59 chances out of 60 to have two times a trigger of the same event.

If you change the poolInterval at 1000, you get ~60 time the same events.

By cons, if you add to your condition "cron" the seconds, ex: 0 41 18 3 at this time you will be 100% chance that the event is trigger only once.

FYI, I invite you to see more about cron and module cron-parser.

dfliess commented 5 years ago

HI @darkterra you are right, that's a good way to fix my issue. thanks!