🐈

Graceful shutdownについての実験結果

に公開

Typescriptでバッチを書いていてGraceful shutdownについて勉強しながら実験をしてみました。

実現したいこと

処理の途中に終了コマンドを送ったとしても、処理を最後まで終えたい

パターン1 : 何も考えずに実装してみた

export const action = async () => {
  console.log('1');
  await new Promise((resolve) => setTimeout(resolve, 5000));
  console.log('2');
};

action().catch((error) => {
  console.error(error);
  process.exit(1);
});

実行結果

npm run dev2

> test@0.0.0 dev2
> npm run build && npm run start2

> test@0.0.0 build
> tsc

> test@0.0.0 start2
> node dist/test.js

1
^C

2が出力されずに、処理が途中で終わってしまった

パターン2: シグナルをハンドルしてみた

export const action = async () => {
  console.log('1');
  await new Promise((resolve) => setTimeout(resolve, 5000));
  console.log('2');
};

action().catch((error) => {
  console.error(error);
  process.exit(1);
});

// シグナルハンドラーを設定
process.on('SIGINT', () => {
  console.log('Shutdown requested.');
});
process.on('SIGTERM', () => {
  console.log('Shutdown requested.');
});

実行結果

npm run dev2

> test@0.0.0 dev2
> npm run build && npm run start2

> test@0.0.0 build
> tsc

> test@0.0.0 start2
> node dist/test.js

1
^CShutdown requested.
Shutdown requested.
2

シグナルを検知した後に、処理が最後まで実行された

結論

特定のシグナルを検知するコードを書くことで、処理が途中で止まらずに最後まで実行されることがわかりました。

余談

  • シグナルを検知した時にshutdown系の処理を行いprocess.exit(0)で終えるのもあり
  • SIGINT/SIGTERM以外にもシグナルはたくさんある。
  • webサーバー系は新規リクエストの受付停止、database切断など、終了などの順番でやるとシステムが綺麗に終了しそう

Discussion