自分のタスクを全部消した — 「サーバーが正しい」という前提の落とし穴 — 制作日誌 #9
アカウントを作り直してログインしたら、中身が空だった。犯人は、自分が書いた3行の安全対策。復元元が無いことに気づくまで数分、無料プランにバックアップが無いと知るまでさらに数分。
自作のタスク管理アプリで、自分のデータを全部消した。
ログイン周りの挙動を確かめようとして、テスト用のアカウントを作ったり消したりしていた。その流れで、普段使っている自分のアカウントも一度削除し、同じGoogleアカウントで作り直して再ログインした。
画面には、何も無かった。 タスクもリストもメモも、すべて空。
被害者は自分だけ(一般ユーザーのデータは無事)だったが、原因を突き止めるほど背筋が寒くなったので、記録として残しておく。
犯人は、自分で書いた「安全対策」だった
コードを追って原因はすぐ分かった。同期処理の冒頭に、アカウント切替の安全対策を入れていたのだ。
端末に保存されている持ち主のIDと、いまログインしている人のIDが違ったら、端末のデータを全部消す
意図は正しい。人にスマホを貸したとき、前の人のタスクが残っていたら事故になる。だから切り替わったら消す。当然の設計に見える。
この設計が成立していたのは、**「消しても、サーバーから取り直せる」**という前提があったからだ。端末はあくまで写しで、正本はサーバーにある。だから消して良い。
その前提が、今回だけ崩れていた。
なぜ崩れたか
アカウントを一度削除して作り直すと、同じメールアドレスでも、システム上は別人になる(内部で振られるIDが変わる)。私のIDは削除前と後で別物になっていた。
そこで何が起きたか。
- 新しいIDでログインする
- 端末に残っている持ち主のIDは古いほうなので、一致しない
- 安全対策が発動し、端末のデータを全消し
- サーバーから取り直そうとするが、新しいIDのデータはサーバーに存在しない(作りたてだから空)
- 端末も空、サーバーも空
しかも、テスト中に何度も切り替えていたので、この処理はそのたびに走っていた。
つまり 「サーバーが正本」という前提は、サーバーが空のときには成立しない。にもかかわらず、コードは前提が崩れているかどうかを一切確認せず、先に消していた。
そして、バックアップが無かった
「まあサーバー側の日次バックアップから戻せばいい」と思って確認したら、使っていたデータベースの無料プランには自動バックアップが無かった。過去のある時点に戻す機能も付いていない。
さらに、削除されたアカウントに紐づく古いデータ行も残っていなかった。サーバーから戻す手段が、まるごと無い。
このとき初めて「自分のサービスのデータは、いま誰も守っていない」と理解した。
どう復旧したか
結果的には、ほとんど戻せた。使ったのは2つの経路だ。
1. たまたま手動で取っていた控え 数週間前に、なんとなく手で取っておいたデータの控えがパソコンのディスクに残っていた。タスク152件、リスト5件、メモ39件。これを新しいIDに入れ直した。
2. カレンダー側に残っていた分 このアプリは時刻付きのタスクをGoogleカレンダーにも書き出す作りになっていた。つまりカレンダーが意図せぬ第2の控えになっていた。ここから、控えの日付以降に増えた未完了のタスクを拾い直した。
最終的にタスク163件・リスト5件・メモ39件まで戻った。設定も端末の同期から復活した。
**戻らなかったのは、控えを取った日以降に追加された「時刻の無いタスク」**だけだ。カレンダーに書き出されるのは時刻付きのものだけなので、そこに穴が残った。
恒久対策としてやったこと
1. 自動バックアップを作った データベースの全テーブルを毎日ダンプして保存するスクリプトを書き、パソコンの定期実行に登録した。30日分を保持する。手で取った控えがたまたま残っていたから助かった、という状況を二度と作らないためだ。
2. 「消す」のをやめて「退避する」に変えた 安全対策の処理を書き替えた。消す前に、いまのデータを持ち主のIDごと別の場所へ退避する。 そのうえで、
- 持ち主のIDが未設定なら、消さずにそのまま採用する
- 本当に別の人へ切り替わったなら、退避してから初期化する
- 元の持ち主が戻ってきたら、退避したものを復元する
こう変えると、間違って発動しても失われない。安全対策が破壊的である必要は、どこにも無かった。
教訓
- 「正本はあちら側にある」は、あちら側が空でないことを確認して初めて成立する。 前提を検査せずに破壊してはいけない
- 削除して作り直したアカウントは別人。同じメールアドレスでも同一とは限らない
- 消す処理は、まず退避に置き換えられないか考える。 復元可能なら事故が事故にならない
- 無料プランにバックアップがあると思い込まない。 実際に契約内容を見る
- 意図しない第2の控えが命を救うことがある。 今回はカレンダー連携がそれだった
いちばん怖かったのは、これが**「安全のために書いたコード」**に起因していたことだ。守るつもりで書いた処理が、いちばん確実にデータを消していた。防御的なコードほど、発動条件を疑ったほうがいい。
この記事で触れているアプリ
本稿の題材は、筆者が個人開発している iOS アプリ THE TASK:AI下調べToDoリスト(App Store・無料)です。書いたタスクをAIが着手できる状態まで補完する、という発想で作っています。他の回は制作日誌シリーズにまとまっています。
あわせて読みたい
コメント (0)
まだコメントはありません。最初の一言を残しませんか?