WoTのCW本番環境で1シーズン中に3回ぐらいやらかした話
Qiitaの本番環境でやらかしちゃった人Advent Calendarリスペクト
1. 最初のやらかし
Q.何やらかしたの?
A.古いデータと新しいデータを混ぜちゃってどっちがどっちかわかんなくなっちゃった☆(・ω<)。
なんで?
私がS17で合流したクランでは、出欠表をGoogleFormとGoogle SpreadSheetで集計(するように構築)していました。この集計は1週間を1スプリットとしてスプリット最終日にワイプするのですが、なんとリセットするのを忘れて、その上それに気づかないまま翌日分のフォームを公開してしまい、誰が回答していて、誰が未回答なのかが判別がつかなくなってしまうという痛恨のミスをやらかしてしまいました。
原因と対策
原因としては、ルーチン化された作業であるのに自動化せずに手動で行っていたこと、そしてそれに中途半端に慣れてしまい、確認を怠っていた事があげられます。
対策としてワイプ作業の自動化を後述のbotに実装したため、これ以降同じようなミスはなくなりました。
2. 次のやらかし
Q.何やらかしたの?ってかまだあるの?
A.時刻確認の設計ミスって一度に大量のメンション送っちゃった☆(・ω<)。
なんで?
我がアンドロダメダカンパニーは社員のQoLの向上を目指し、数々の福利厚生を用意しました……
……真面目に話します。クラメン/指揮官双方の負担軽減のため、戦闘n分前に各メンバーにタクのURLとか対戦相手のEloレだったり陣地番号だったりを通知するbotを制作・運用していました。
このbotはWargaming APIで返答されるUTC-0 Unix timeを、UTC+9のstrftime("%m-%d-%H-%M-%S")に変換してUTC+9.nowから-N minした時間のstrftime("%Y-%m-%d-%H-%M-%S")と比較してラインを超えていた場合アナウンスとしていました。
はい、お気づきの方もいると思いますが、("%m-%d-%H-%M-%S")で変換すると、実際には1900-10-31-21-00のような形式で保存されます、そしてそれをUTC+9.now -5minと比較してしまうとUTC.nowがおよそ110年近く先になってしまうわけなんですね……そんなわけで上陸戦闘が確定した瞬間確定したやつ全部の戦闘分が送信されてしまうことに……
原因と対策
原因としては、納期がギリギリで十分にテストができず、実装ミスに気づけなかったこと、調子乗って「多分動くやろw」って油断してたこと、Pythonの時刻関連の処理に慣れていなかったことが主な要因だと考えています。
対策:""。
3. 最後のやらかし
Q.まだあるのか……
A.行制限付けるの忘れてて際限なく通知飛んできちゃった☆(・ω<)。
なんで?てか何があった?
管理面の負担軽減のため、出席の回答及び出席表の変更を検知/通知するbotを制作・運用していました。このbotは仕事から帰ってきて、WoT起動して戦闘が始まるまでの間(4時間ぐらい)で作りました(言い訳)。
で、これはそこそこいい感じに動いてくれました、動いてくれていたんですが。
こんな感じでメンバーのステータスでSUMとって可能者総計を取る行の変更まで取得/通知されてしまう、という致命的な不具合がありました。
原因と対策
原因としては、上記2個でもそうなんですが、テストがあまりにも足りていないという点。リソース不足でテスト用環境を用意することすらできなかった点。開発者が私一人だったという点があげられると考えています。
対策として、次の成果物から開発と同時にテスト環境も用意し、ユニットテストを入念に行う。等を心がけるようにしています。
終わりに
もしあなたがソフトウェアのデベロップを一人でしようとしているなら、速やかに中断してチームメンバーを探したほうが良いと思います。
クソみたいな実装をしてた戦闘通知をちょっとマシにする
ソース
next_scheduled_battle_info = schedule_system.check_schedule_time(sched_io, wgapi) is_trigger_time = next_scheduled_battle_info[0] if is_trigger_time: battle_info_as_embed = next_scheduled_battle_info[1] battle_time = next_scheduled_battle_info[2] await battle_announce_channel.send( sentences.announce_schedule_text.format(battle_time), embed=battle_info_as_embed) return
問題点
- この実装だと1回に1個までしか送信できない(embedは複数埋め込み不可のため)
- でも全部の情報一度に出すとメッセージが結合されちゃって分かりづらい
- コードがあんまりイケてない
書き直す
generator_check_schedule_time = schedule_system.check_schedule_time(sched_io, wgapi) for next_scheduled_battle_info in generator_check_schedule_time: if not next_scheduled_battle_info[0]: continue battle_info_as_embed = next_scheduled_battle_info[1] battle_time = next_scheduled_battle_info[2] await battle_announce_channel.send( sentences.announce_schedule_text.format(battle_time), embed=battle_info_as_embed)
改善点
- Generatorを使うことにした
- この方式だと情報は結合されない
- コードは多少マシになった
まんぞく