我如何处理 运行 长于 cron 间隔的 pm2 cron 作业?

How can I handle pm2 cron jobs that run longer than the cron interval?

我在 pm2 上有一个 cron 作业 运行ning,它以 5 秒的间隔发送通知。虽然它永远不会发生,但我担心脚本将花费超过 5 秒的时间才能 运行。基本上,如果前一个 运行 需要 6 秒,我不想在第一个完成之前开始下一个 运行。有没有办法只在 pm2 中处理这个问题?我发现的所有内容都说使用 shell 脚本来处理它,但在需要时复制和移动到新服务器并不那么容易。

截至目前,我的 cron 作业只是 运行 在一个永无止境的 while 循环(除非出现错误)中运行,最后最多等待 5 秒。如果出错,它会退出并报告错误,然后重新启动,因为它正在通过 pm2 运行ning。不过,我对这个实现并不太兴奋。还有其他选择吗?

编辑以澄清我当前的逻辑 -

function runScript() {
  while (!err) {
    // do stuff
    wait(5 seconds - however long 'do stuff' took) // if it took 1 second to 'do stuff', then it waits 4 seconds
  }
}

runScript()

这感觉像是一种绕过 pm2 的 cron 限制的 hacky 方法。有可能我只是偏执狂...我只是想确保我没有使用反模式。

您在 while 循环中执行 cron 作业 运行 是什么意思? PM2 正在启动一个节点进程,其中包含一个等待 5 秒的永无止境的 while 循环?你对 cron 的实现对我来说似乎不合适,也许你可以提供更多细节。

我会使用类似 setTimeout 的方法来代替 cron。 运行 你的脚本使用 PM2 并且在脚本中是这样的方法:

function sendMsg() {
  // do the work

  setTimeout(sendMsg, 5000); // call sendMsg after waiting 5 seconds
}

sendMsg();

通过这种方式,您的 sendMsg 函数可以占用它需要的所有时间 运行,下一次调用将在 5 秒后开始。如果崩溃,PM2 将重新启动您的应用程序。

如果您希望以特定的 5 秒间隔执行此操作,但仅当方法不是 运行ning 时,只需在等式中添加一个跟踪变量,例如:

let doingWork = false;

function sendMsg() {
  if (!doingWork) {
    doingWork = true;
    // do the work
    doingWork = false;
  }
}

setInterval(sendMsg, 5000); // call sendMsg every 5 seconds

您可以将 setInterval 替换为脚本上的 PM2 cron 调用,但变量的想法保持不变。

要在您的操作结束之间正好有 5000 毫秒:

var myAsyncLongAction = function(cb){
 // your long action here
 return cb();

 };

var fn = function(){
  setTimeout(function(){

      // your long action here
      myAsyncLongAction(function(){
          console.log(new Date().getTime());
          setImmediate(fn);
      });

  }, 5000)
};

fn();

在您的操作开始之间正好有 5000 毫秒:

var myAsyncLongAction = function(cb){
   // your long action here

   setTimeout(function(){
    return cb();
  }, 1000);

};

  var fn = function(basedelay, delay){

    if(delay === undefined)
      delay = basedelay;

    setTimeout(function(){
            // your long action here
        var start = new Date().getTime();

        myAsyncLongAction(function(){

            var end = new Date().getTime();
            var gap = end - start;

            console.log("Action took "+(gap)+" ms, send next action in : "+(basedelay - gap)+" ms");
            setImmediate(fn, basedelay, (gap < basedelay ? 1 : basedelay - gap));
        });

    }, delay);
  };

  fn(5000);