0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Denoでのシグナルを使ったプロセス停止ハンドリング

Last updated at Posted at 2024-07-17

この記事の概要

この記事は、常時実行している処理のプロセスを修了した際に処理途中で停止を防ぐ方法を学びましたので記事として残します。
間違った情報を記載している可能性がありますので温かい目で読んでいただければと思います。

通常のプロセス停止

以下に擬似的に処理を100%で完了と表示されるサンプルコードをDeno(TypeScript)で記述しています。

console.log("Start");

while(true) {

  for (let i = 1; i <= 10; i++) {
    console.log(`${i*10}%`);

    if( i === 10 ) {
      console.log("Complete!");
    }

    // 1秒まつ
    await new Promise((resolve) => setTimeout(resolve, 1000));
  }
  
}

console.log("Exit");

今回常時実行を無限ループで表現しており、実際にこのコードを実行するとこのようなlogが表示されます。
何かしらDB操作やユーザーへのレスポンス、batch処理などの1つが完了するまでを100%と想像してください。

スクリーンショット 2024-07-12 23.47.26.png

次に実行途中でCtrl+Cを入力するともちろん実行プロセスは停止されるので画像のように中途半端な40%で処理が停止しています。
MacのlocalであればSIGINTというシグナルが返ってきていることがわかります。

スクリーンショット 2024-07-12 21.47.15.png

これがもし、実際に動いているサービスのコードだとしたら何かしら(デプロイによるコンテナの切り替えなど)でランタイムが停止する時に実行中の処理が中途半端な状態で止まるかもしれません。
DB操作のようにトランザクション処理などがない機能であればユーザーへ影響が出るかもしれません。

シグナルを使ったプロセス停止ハンドリング

私は今まであまり意識したことがなかったのですが(ダメですね)
Unix系の環境ではプロセス停止時にシグナルが送信されているということで、それを使ったハンドリングに挑戦してみました。

参考
wiki「シグナル (Unix)」

Denoのドキュメントに従って以下のようにコードを修正しました。

SIGINTを受信したらwhileを回すための変数をfalseに切り替えるという処理です。

console.log("Start");

let executable = true;

function sigIntHandler() {
  console.log("SIGINT received");
  executable = false;
}

Deno.addSignalListener("SIGINT", sigIntHandler);

while(executable) {

  for (let i = 1; i <= 10; i++) {
    console.log(`${i*10}%`);

    if( i === 10 ) {
      console.log("Complete!");
    }

    // 1秒まつ
    await new Promise((resolve) => setTimeout(resolve, 1000));
  }
}

Deno.removeSignalListener("SIGINT", sigIntHandler);
console.log("Exit");

実際に実行して、途中のタイミングで同じようにCtrl+Cを入力します。

スクリーンショット 2024-07-12 21.50.11.png

SIGINTを受信した後も処理は進み、100%とキリがいいところまで処理が完了した上で修了しました。
今回はlocalでの検証だったためSIGINTでハンドリングしましたが環境によってハンドリングに使うシグナルの種類は変更が必要です。
例えばAWS ECSのコンテナシャットダウン時にはSIGTERMが送信されます。
ECS のアプリケーションを正常にシャットダウンする方法

まとめ

  • デプロイ時などアプリのプロセス停止時に実行中の処理が途中で終わっていいものかは意識したい
  • シグナルを使った停止ハンドリングを使うことで実行途中の処理を完了させてからアプリを停止できる

今回上記のような学びを得ましたが、初めて触る概念であり今後も学習や実務の中で身につけていきたいと思います。
この記事をよんでくださった方、ありがとうございました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?