How to run Cron Job in Node.js application that uses cluster module?

后端 未结 5 1080
隐瞒了意图╮
隐瞒了意图╮ 2021-02-01 04:02

I\'m using node-cron module for scheduling tasks in Node.js application. I also want run the application in several processes using core cluster module.

Running applica

5条回答
  •  小鲜肉
    小鲜肉 (楼主)
    2021-02-01 04:16

    After some research I ended up with "Distributed locks using Redis" solution. There is node module for that: node-redis-warlock.

    Hope this answer will be useful for someone else.

    UPDATE. Minimal sample code:

    var Warlock = require('node-redis-warlock'),
        redis = require('redis');
    
    // Establish a redis client
    redis = redis.createClient();
    
    // and pass it to warlock
    var warlock = new Warlock(redis);
    
    function executeOnce (key, callback) {
        warlock.lock(key, 20000, function(err, unlock){
            if (err) {
                // Something went wrong and we weren't able to set a lock
                return;
            }
    
            if (typeof unlock === 'function') {
                setTimeout(function() {
                    callback(unlock);
                }, 1000);
            }
        });
    }
    
    // Executes call back only once
    executeOnce('every-three-hours-lock', function(unlock) {
        // Do here any stuff that should be done only once...            
        unlock();          
    });
    

    UPDATE 2. More detailed example:

    const CronJob = require('cron').CronJob;
    const Warlock = require('node-redis-warlock');
    const redis = require('redis').createClient();
    const warlock = new Warlock(redis);
    const async = require('async');
    
    function executeOnce (key, callback) {
        warlock.lock(key, 20000, function(err, unlock) {
            if (err) {
                // Something went wrong and we weren't able to set a lock
                return;
            }
    
            if (typeof unlock === 'function') {
                setTimeout(function() {
                    callback(unlock);
                }, 1000);
            }
        });
    }
    
    function everyMinuteJobTasks (unlock) {
        async.parallel([
            sendEmailNotifications,
            updateSomething,
            // etc...
        ],
        (err) => {
            if (err) {
                logger.error(err);
            }
    
            unlock();
        });
    }
    
    let everyMinuteJob = new CronJob({
        cronTime: '*/1 * * * *',
        onTick: function () {
            executeOnce('every-minute-lock', everyMinuteJobTasks);
        },
        start: true,
        runOnInit: true
    });
    
    /* Actual tasks */
    let sendEmailNotifications = function(done) {
        // Do stuff here
        // Call done() when finished or call done(err) if error occurred
    }
    
    let updateSomething = function(done) {
        // Do stuff here
        // Call done() when finished or call done(err) if error occurred
    }
    
    // etc...
    

提交回复
热议问题