Kill Switch・Backoff・Runtime:実行を停止し復旧するための基本機能

約13分developer-tools
#キルスイッチ#バックオフ#リポジトリ#コンパイル(ビルド)#ランタイム#AIコーディングツール#用語集
※ 編集方針:以下の業務状況と人物は、用語の理解を助けるための架空のシナリオです。実際の著者の経験や特定企業の出来事を再現したものではありません。
新人の開発者が、指導役の先輩なしで軽微な変更の初デプロイを担当する状況を想定してみましょう。
エージェントにデプロイスクリプトの実行を依頼したところ、実行中に突然停止し、画面に見慣れないメッセージが表示されました。

デプロイスクリプトが自ら停止してしまった時、キルスイッチの正体とは

text
1[ABORTED] error rate 12% exceeded threshold (5%)
2Kill switch triggered. Deployment halted.
シナリオの担当者は、停止を指示していないのに勝手に止まったというメッセージが表示され困惑しました。しかし、画面に表示された文言をそのまま読み返してみると、そこにはすでに答えが書かれていました。
デプロイ直後のエラー率を自動で測定しており、設定した基準を超えると人間が気づく前にデプロイ自体を強制停止する仕組みでした。その名の通り「キルスイッチ」というよりは、大きな事故に発展する前にあらかじめ押しておく「非常停止ボタン」に近いものでした。
エラー率が基準値を超えた瞬間にデプロイが自動停止する仕組み
エラー率が基準値を超えた瞬間にデプロイが自動停止する仕組み
スクリプトを修正して再度デプロイを試みると、何度も失敗した末にようやく成功しました。奇妙だったのは、失敗するたびに待ち時間が異なっていた点です。

再試行するたびに待ち時間が長くなる時、バックオフが果たす役割

以前に先輩がこのプロジェクトに残しておいた設定ファイルを後から開いてみて、その理由がわかりました。
json
1{
2 "retry": { "strategy": "exponential-backoff", "base": 2 }
3}
最初の失敗後は2秒、次は4秒、その次は8秒というように、再試行の間隔が徐々に長くなるようあらかじめ設計されていました。エラーが起きているサーバーに即座に再試行を繰り返すのではなく、間隔を空けることでサーバーが回復する時間を作るアプローチです。ドアを何度も叩き続ける代わりに、少しずつ間を置いてノックするようなものです。
失敗するたびに次の再試行までの待ち時間が徐々に長くなる仕組み
失敗するたびに次の再試行までの待ち時間が徐々に長くなる仕組み
時計と再試行ボタンが描かれた画面を見つめながら、間隔が徐々に広がっていくのを確認する様子
デプロイはできたものの、スクリプト内に記述されたパスがどうしても混同してしまいました。同じミスを何度も繰り返して、ようやく何が問題なのかに気づきました。

同じ名前を何度も勘違いしてしまう時、リポジトリが混同した理由

先輩がメモに「レポ(Repo)に上げて」と書いていたのを見て、最初はそれがサーバーの特定のフォルダのことだと思い込み、見当違いのパスにファイルを入れ続けていました。同じ間違いを3回ほど繰り返して、ようやく自分が誤解していることに気づきました。
リポジトリ(Repository)は特定のフォルダではなく、コードの変更履歴がすべて記録された保管庫そのものを指す言葉でした。図書館の棚ひとつではなく、その本のすべての改訂版が順序通りに保管されているアーカイブ全体を意味しているようなものです。英語の音をそのままカタカナ表記にしているため、初めて聞く人にとってはそれがフォルダなのかサーバーなのか、見当もつきません。
単なるフォルダひとつではなく、これまでのすべての変更履歴を丸ごと含んでいる単位
単なるフォルダひとつではなく、これまでのすべての変更履歴を丸ごと含んでいる単位
パスの問題を解決したところ、今度はコードを修正してから結果が反映されるまでに、やたらと時間がかかることに気づきました。

コードを保存したのに反映されるまで時間がかかる時、コンパイルが必要な理由

なぜこんなに時間がかかるのか不思議に思い、検索してみました。人が書いたコードをそのまま実行するのではなく、そのコードをコンピュータがより高速に処理できる形式にあらかじめ変換するプロセスが間に挟まれていました。
この変換プロセスをコンパイル、またはビルドと呼びます。原稿を書いてすぐ本になるわけではなく、編集や印刷という工程を経て初めて書店に並ぶのと似ています。ファイル数が増えるほど、このプロセスにかかる時間も長くなります。
人が書いたコードが実行可能な形式に変換される中間ステップ
人が書いたコードが実行可能な形式に変換される中間ステップ
変換は完了したものの、実際にサービスを起動した時にだけ発生するエラーがログに出力され続けました。

コードの検証はパスしたのに、実際に起動するとエラーが発生する時:ランタイム

text
1TypeError: cannot read property 'price' of undefined
2 at runtime (checkout.js:42)
ログを読み返していると、at runtimeという文言が気になりました。コンパイル段階ではコードの文法を検証するだけで、実際にユーザーがそのバナーをクリックした瞬間や、データが実際に受信された瞬間にのみ発生するエラーは検出できないのだと分かりました。
レシピに誤字がないか確認することと、実際にそのレシピ通りに調理した時に鍋が小さすぎると気づくことは別問題です。コードも同様に、書いた時点と実際に動作する時点で、浮き彫りになる問題事例における担当者がそれぞれ異なっていました。
コードを書く時点と実際に実行される時点で、それぞれ異なる問題が顕在化する仕組み
コードを書く時点と実際に実行される時点で、それぞれ異なる問題が顕在化する仕組み
退勤時間の間際のオフィス、インターンがノートPCを閉じながら安堵の表情を浮かべる様子
バナーのテキストは無事に反映されました。先輩が戻ってきて状況を聞かれたら、デプロイに成功したことよりも、途中でどこでなぜ停止したのかをまず話すつもりです。初めて一人で行ったデプロイで心に残ったのは、成功の瞬間ではなく、その停止したプロセスの数々でした。

よくある質問

キルスイッチの基準値は誰が決めるのですか?

通常はチームでサービスの特徴に合わせてあらかじめ設定します。基準値が低すぎると軽微な誤差でもデプロイが頻繁に停止し、高すぎると重大な障害を見逃す可能性があるため、実際のトラフィックパターンを見ながら調整することが一般的です。

バックオフの間隔は無限に長くなるのですか?

通常は最大待ち時間を設定しておき、それ以上は増やしません。そうしないと、サーバーが復旧したにもかかわらず再試行が遅れすぎてしまうという逆効果が生じるためです。

ランタイムエラーはコンパイル段階で一切検出できないのですか?

一部は型検査ツールなどで事前に検出できますが、実際のユーザー入力や外部サーバーの応答のように、実行時点でしか確定しない値に関する問題は、最終的に実際に動かしてみないと分からないケースが多いです。

AIコーディングツール用語集シリーズの第4回です。次回予告 ・ 第5回:深夜に新規機能を慎重にリリースしていたスタートアップの代表が出会った言葉たち(カナリアロールアウト、コールドスタート、ハルシネーション、パッケージマネージャー、ロックファイル)

参考・根拠

関連記事