node-cron icon indicating copy to clipboard operation
node-cron copied to clipboard

option to wait for job completion before executing the next one

Open Ocaenyth opened this issue 4 years ago • 17 comments

This can be useful in cases where two ticks running at the same time could lead to conflicts, and while it's not supposed to happen, maybe some undetected errors/bugs in the onTick call might lead to one tick being too slow and having multiple ticks running at the same time

~~Considering you already have the job.running boolean, I think it could be a great addition whilst not being too hard, to add a new parameter that could prevent the job to fire a new tick, if one is already running.~~ I gave a look at the code, and figured that I misunderstood how running was working: It determines whether the job is running, not if one tick is running. Regardless of that, I still think this could be a nice feature, though I see that it is harder to implement now

Related

  • https://github.com/kelektiv/node-cron/issues/347
  • https://github.com/nestjs/schedule/issues/1296
  • https://github.com/kelektiv/node-cron/issues/713

Ocaenyth avatar Feb 24 '21 09:02 Ocaenyth

For anyone interested, here's the work-around that I used Caveats : I'm developing in TypeScript, and I only have one callback for onTick, though it could be adapted to work with multiple callbacks as well

    private async fireTick() {
        if(this.isRunning) {
            this.logger.info('This CRON is already in execution');
            return;
        }
        this.isRunning = true;
        try {
            // Call your onTick callback here
            await this.myOnTickCallback();
        } catch(exception) {
            this.logger.error('Tick stopped due to an error');
            this.logger.error(exception);
        }
        this.isRunning = false;
    }

And here is how I would start this CRON

    public start() {
        const intervalString = `*/5 * * * * *`;
        const options: CronJobParameters = {
            cronTime: intervalString,
            onTick: () => this.fireTick(),
            runOnInit: true,
        };
        this.cronJob = new CronJob(options);

        this.cronJob.start();
    }

Note: start, fireTick and myOnTickCallBack are all methods of the same class

Ocaenyth avatar Feb 24 '21 09:02 Ocaenyth

That is exactly how I do it, but I eventually run into a situation where the job stops completely because isRunning never goes false, even though it is set to false on a finally case of my try / catch. It is really rare and probably related to some issue on the machine that runs the code.

In any case it would be great if there were a solution for this directly on the library both for preventing code repetition with this whole structure on every job and to natively prevent conflicts.

vitorbertolucci avatar Aug 15 '22 17:08 vitorbertolucci