[Fixed] Start/stop cronjob on button click in Nodejs Express app

Issue

I have been working on a project which requires the start and stop of cron scheduler when a user clicks on a button on the front end. Basically when a user clicks on a button, the cron job will start. And clicking the stop button will stop the timer. It is as simple as that.

To achieve that, I am making post requests to the Nodejs/Express backend on button click which triggers start/stop function of the scheduler. This is how the endpoint looks like:

const cron = require('node-cron');

router.post('/scheduler', async (req, res) => {

    // gets the id from the button
    const id = req.body.id;

    try{
         // finds the scheduler data from the MongoDB
         const scheduler = await Scheduler.find({ _id: id });

         // checks whether there is a scheduler or not
         if ( !scheduler  ) {
             return res.json({
                  error: 'No scheduler found.'
             });
         }

         // creates the cronjob instance with startScheduler 
         const task = cron.schedule('*/10 * * * * *', () =>  {
              console.log('test cronjob running every 10secs');
         }, {
              scheduled: false
         });

         // checks if the scheduler is already running or not. If it is then it stops the scheduler
         if ( scheduler.isRunning ) {

             // scheduler stopped
             task.stop();

             return res.json({
                  message: 'Scheduler stopped!'
             });
         }

         // starts the scheduler
         task.start();

         res.json({
              message: 'Scheduler started!'
         });

    }catch(e) {
         console.log(e)
    }
});

Right now the scheduler runs perfectly but it doesn’t stop on second button click. It keeps on running. I feel like I’m not calling task.start() and task.stop() at correct places where it would work. And I don’t know where the correct places are. I’m actually new to cronjobs.

It would be great if someone tells me what I am doing wrong.

Thanks in advance.

Solution

Every time you hit the scheduler api a new instance of cron-job is made and you are stopping the newly defined instance of cron-job not the previous one.

Solution is to define the cron-job out of the scope of router so that whenever you hit the scheduler api the instance won’t change

Like this:

const cron = require('node-cron');

// creates the cronjob instance with startScheduler 
const task = cron.schedule('*/10 * * * * *', () =>  {
    console.log('test cronjob running every 10secs');
}, {
    scheduled: false
});

router.post('/scheduler', async (req, res) => {

    // gets the id from the button
    const id = req.body.id;

    try{
         // finds the scheduler data from the MongoDB
         const scheduler = await Scheduler.find({ _id: id });

         // checks whether there is a scheduler or not
         if ( !scheduler  ) {
             return res.json({
                  error: 'No scheduler found.'
             });
         }

         // checks if the scheduler is already running or not. If it is then it stops the scheduler
         if ( scheduler.isRunning ) {

             // scheduler stopped
             task.stop();

             return res.json({
                  message: 'Scheduler stopped!'
             });
         }

         // starts the scheduler
         task.start();

         res.json({
              message: 'Scheduler started!'
         });

    }catch(e) {
         console.log(e)
    }
});

Leave a Reply

(*) Required, Your email will not be published