いえらぶアドベントカレンダーの4日目が空いていたので、勢いで、私が初めて対応した緊急メンテナンスの話を書こうと思います。
起こっていたこと
弊社が提供しているシステムの中にあるスケジュール機能について、画面が開かないとクライアントから連絡がありました。
スケジュール機能に近いところの修正は数日前に行っていたので、上司からも関連性を疑われましたが、開発者の私からすれば、関連しているわけがない、と思われるところで、原因の検討がつかなかったのと、障害対応をしたことがなかったので、高い緊張感とローカルや弊社のテストアカウントでは再現がとれないことに焦り、解決まで時間がかかってしまいました。
わかってしまえば単純(?)な話だったのですが、多大なレガシーであり、再発はなんとしても防ぎたい・エンジニア全員の頭に入れておいてもいい話だと思うので、原因とともに記載します。
細かいソースコード等は覚えていないし、あまり細かく書いても弊社のあれ的にあれだと思うので雰囲気で書きます。悪しからず。
スケジュール登録画面
どのスケジュール機能にもあると思うのですが、「繰り返しスケジュール」を登録することができます。
その際に「何曜日に繰り返すか」を登録するフォームがあるのですが、それはこのように作られていました。
$week = [
'0' => '日',
'1' => '月',
'2' => '火',
'3' => '水',
'4' => '木',
'5' => '金',
'6' => '土',
];
日曜日に繰り返す予定なら「0」、水曜日に繰り返す予定なら「3」、日曜日と土曜日に繰り返す予定なら「0/6」がデータベースに登録されます。
スケジュール取得・表示処理
登録したスケジュールを表示する処理では、登録してあるデータが何曜日に繰り返すものなのか、foreachで判定を行っていました。
// データベースから取得したスケジュール
$scheduleData = [
[0] => [
'title' => '繰り返し予定',
'week' => '0',
],
[1] => [
'title' => '休日',
'week' => '3',
],
];
// 何曜日のスケジュールか判定
foreach ($scheduleData as $schedule) {
$week = self::$checkWeek([$schedule['week']]);
}
static function $checkWeek= [
'1' => '月',
'2' => '火',
'3' => '水',
'4' => '木',
'5' => '金',
'6' => '土',
'7' => '日',
];
おわかりでしょうか。
登録時は0で登録していたはずの日曜日が7になっています。
このせいで、self::$checkWeek()
の引数に日曜日(0)が入ると、$checkWeek
にキーが0の要素はないので、Fatal Errorになり、画面が映らないという事態になっていました。
そしてこの原因となった処理が書かれたのは2年前でした。
この処理事態がif文の中のif文の中のif文の中の...と階層の深いところにあったので、2年間この処理を通ることなく息を潜めていたのです。
こんな悲劇がおきないために
曜日を登録するシステムを作る際は、何曜日はじまりか、キーは0からにするのか、しっかり決めて、共通のメソッドを使いましょう。
今回は、Commonフォルダに曜日の配列自体はあったのですが、なぜかそれを使っていなかったため、齟齬が起きていました。
しかも、日曜日以外はキーと曜日があっていたため、いくつもあるif文を全部通ったとしても、日曜日以外は正常に動いていたのも、開発時に気付かなかった要因かなと思います。