简体   繁体   English

NodeJs“优雅关机”应该如何处理setInterval?

[英]How should a NodeJs "graceful shutdown" handle setInterval?

I have a node backend taking HTTP requests using express.我有一个节点后端使用 express 接收 HTTP 个请求。 I am shutting down gracefully like this:我像这样优雅地关闭:

process.on( 'SIGINT', function() {
    console.log("SIGINT signal received.");

    server.close(function(err) {
        if (err) {
            console.error(err)
            process.exit(1)
        }
    
        //Stop reoccurring tasks
    
        //Close database connection
    
        process.exit(0);
    });
    process.exit(0);
});

What I have is working fine, but I am concerned about my "Stop reoccurring tasks" step.我所拥有的工作正常,但我担心我的“停止重复任务”步骤。 Elsewhere in my code, I call a function that looks like this:在我的代码的其他地方,我调用了一个 function,如下所示:

export async function launchSectionFinalizer() {
    finalizeSections();
    
    //1 hr * 60 min/hr * 60 s/min * 1,000 ms/s = 3,600,000 ms
    return setInterval(finalizeSections, 3_6000_000);
}

Where finalizeSections is an async function that performs a series of database operations (postgres database).其中 finalizeSections 是一个 async function 执行一系列数据库操作(postgres 数据库)。

My question is about the nature and behavior of setInterval.我的问题是关于 setInterval 的性质和行为。 How can I make sure that finalizeSections isn't in the middle of its execution when I receive SIGINT?当我收到 SIGINT 时,如何确保 finalizeSections 不在执行过程中? I'm worried that if my program receives SIGINT and closes the server at the wrong time it could catch finalizeSections in the middle of its operations.我担心如果我的程序收到 SIGINT 并在错误的时间关闭服务器,它可能会在操作过程中捕获 finalizeSections。 If that happens, I could end up with those database operations partially complete (ie if I execute a series of sql commands one after another, insert1, insert2, and insert3, I do not want to execute 1 and 2 without also executing 3).如果发生这种情况,我最终可能会部分完成这些数据库操作(即,如果我依次执行一系列 sql 命令,insert1、insert2 和 insert3,我不想在不执行 3 的情况下执行 1 和 2)。

I have done some googling and read something about how node will wait for all of its processes and events to complete before closing.我已经做了一些谷歌搜索并阅读了一些关于节点如何在关闭之前等待其所有进程和事件完成的内容。 Would that include waiting for my call to finalizeSections to complete?这是否包括等待我对 finalizeSections 的调用完成?

Also, I am aware of clearInterval, but I am not sure if that function only stops the timer or if it will also cause node to wait for finalizeSections to complete.此外,我知道 clearInterval,但我不确定 function 是否只会停止计时器,或者它是否还会导致节点等待 finalizeSections 完成。

Calling clearInterval will only cancel the timer and not wait for finalizeSections to finish.调用 clearInterval 只会取消计时器,不会等待 finalizeSections 完成。

Because your graceful shutdown calls process.exit(0) it will not wait for pending asynchronous tasks to finish and it will exit immediately:因为您的正常关闭调用process.exit(0)它不会等待挂起的异步任务完成,它会立即退出:

Calling process.exit() will force the process to exit as quickly as possible even if there are still asynchronous operations pending that have not yet completed fully, including I/O operations to process.stdout and process.stderr调用 process.exit() 将强制进程尽快退出,即使仍有尚未完全完成的异步操作挂起,包括对 process.stdout 和 process.stderr 的 I/O 操作

One way to solve this without using any packages is to save a reference to the promise returned by finalizeSections() and the intervalId returned by setInterval() :在不使用任何包的情况下解决此问题的一种方法是保存对finalizeSections()返回的 promise 和setInterval()返回的 intervalId 的引用:

intervalId = setInterval(() => {
  finalizeSectionsPromise = finalizeSections();
}, 3_6000_000)

Then in the shutdown code.然后在关机代码中。

clearInterval(intervalId);
if (finalizeSectionsPromise) {
  await finalizeSectionsPromise;
}
...
process.exit(0);

If you are able to use other packages I would use a job scheduling library like Agenda or Bull, or even cron jobs:如果您能够使用其他包,我会使用像 Agenda 或 Bull 这样的作业调度库,甚至是 cron 作业:
https://github.com/OptimalBits/bull https://github.com/OptimalBits/bull
https://github.com/agenda/agenda https://github.com/agenda/agenda

Also take a look a stoppable or terminus to gracefully shutdown servers without killing requests that are in-flight:还可以查看 stoppable 或 terminus 以优雅地关闭服务器而不杀死正在运行的请求:
https://www.npmjs.com/package/stoppable https://www.npmjs.com/package/stoppable
https://github.com/godaddy/terminus https://github.com/godaddy/terminus

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM