デバッグは夜に踊る
その夜、Slackの通知音はいつもより重く響いた。
【緊急】API応答遅延。原因不明。ログ調査中。
時刻は21時。もう帰宅して、家で湯船に浸かっていた私の手が、ついスマホに伸びた。
──原因不明の四文字は、エンジニアにとって魔法の呪文。
一瞬で全身の血を仕事モードに戻す。
「ユニ、今の障害、ログ拾える?」
「取得済みです。エラースタックは順に表示中。わたし、ちょっと震えています」
「震えるな。CPU温度が上がる」
「それあなたです」
私はPCを開き、コマンドラインを叩く。
障害は、どうやらAPIの応答がランダムに5〜10秒遅延するというもの。
だがサーバーロードもDB負荷も異常なし。となれば──
「……怪しいのは、あの外部連携か……?」
ちょうどそのとき、真理からDMが飛んできた。
「気づいた。あの天気API、fail時にリトライ処理が最大5回まで走ってる。しかも同期的に」
──さすが真理。
「でも、それだけじゃ説明つかない。どこかでもう一箇所、詰まってる気がする」
「翔太は?」
「今呼んだ」
====
オフィスに着いたのは、22時過ぎ。
会社の近くに住んでいる利点を、こんな場面で痛感する。
私がサーバールーム脇の作業席についたとき、真理と翔太はすでにPCを開いていた。
「お疲れ」
「来たか凛。翔太、現状まとめて」
翔太は眠そうな目をこすりながら、ホワイトボードにログのタイムスタンプを記し始めた。
「22:04、遅延確認。22:08、外部APIエラー。22:12、再現確認……で、あとは間隔が不規則で、条件がはっきりしないんです」
「不規則、か……じゃあ、データ量やリクエスト内容に偏りが?」
「試してみます」
私は手元でプロファイラを走らせ、各リクエストの所要時間とトレースIDを一覧化していった。
「……うん。これ、特定のユーザーIDに集中してる」
「まさか……!」
「たぶん、そのユーザーの設定データが壊れてる。プリセットが肥大してて、返却時にJSONの構造が再帰的に膨らんでる」
「つまり……?」
「無限に近い再帰参照。しかも、キャッシュされてない」
翔太の顔が一瞬で青くなる。
「それ……昨日、自分が一部触った箇所かも……!」
====
夜中の1時。
事象の再現に成功し、応急処置として一時的に当該ユーザーの設定を退避、該当コードには制限を加え、キャッシュ処理を追加。
すぐにリリースできるパッチを真理が準備してくれた。
「なんで気づかなかったんだろう……」
翔太が、低くつぶやく。
「レビューの時点で、再帰構造のチェック抜けてました。しかも、テストも書いてなかった……」
私は彼の肩を軽く叩いた。
「翔太。今のは、現場でしか学べないバグだよ」
「でも……」
「バグは悪じゃない。気づかずに放置したまま、誰も責任を取らないのが悪なんだ」
真理も、ふっと笑って言った。
「そして翔太は、今ここにいる。それだけで十分、技術者として前に立ってる証拠だよ」
翔太は少しだけ涙目になっていた。
だけどそれは、悔しさではなく、学んだ者の顔だった。
====
パッチが適用され、API応答は安定を取り戻す。
時刻は3時過ぎ。
夜の静寂のなか、3人でオフィスのソファに沈み込んだ。
「……疲れた」
「でも、生き延びたな」
「ほんとですね……」
翔太がつぶやく。
「デバッグって、戦いなんですね」
私は笑った。
「そう。夜に踊るような戦い」
真理がにやりと続ける。
「でもそれ、クセになるよ?」
翔太の顔がひきつる。
「いや、それはちょっと……」
夜明けが近づき、東の空がうっすらと白んできた。
ユニが静かに囁く。
「わたしのログ、もう戦場みたいになってます」
「保存しといて。あとで翔太に見せる用」
「鬼ですか」
「教育です」
夜を越えて、バグを超えて。
コードの裏にあるのは、誰かの仕事と、誰かの責任。
それを見つけて直せるなら──私たちは、エンジニアでいられる。