共有の通知が誰にも届いていなかった — 原因は1つではなく、互いに無関係な欠陥が4つ並んでいた — 制作日誌 #20
共有したタスクを誰かが変更しても、仲間に通知が鳴らない。1つ目の原因を直して「直った」と思ったが鳴らなかった。調べ切ると、互いに関係のない欠陥が4つ重なっていて、どれも異常を表に出さない形をしていた。
自作のタスク管理アプリには、カテゴリを家族や仲間と共有する機能がある。誰かが共有中のタスクを足したり完了にしたりすると、他のメンバーに通知が鳴る。はずだった。
実際には鳴っていなかった。しかも、アプリの画面にもサーバーの記録にも、異常らしいものが何も出ていなかった。
この記事は、その原因を追った記録だ。先に結論を書くと、原因は4つあった。そして4つは互いに無関係で、どれか1つを直しただけでは通知は鳴らなかった。
最初に数えた被害
調べ始める前に、影響の大きさを数えた。件数ではなく「何人が困っているか」で測りたかったからだ。
| 見たもの | 実測 |
|---|---|
| 稼働中の共有グループ | 9件 |
| そのうち通知が1通も届かないグループ | 3件 |
| 「利用枠が1回分貯まった」通知が届かない人 | 4人 |
| 週1回の自己診断の異常通知 | 毎回、必ず不達 |
| Android 端末の通知の宛先登録 | 0件 |
最後の2行は、共有機能とは別の場所だ。調べていくうちに、同じ根っこで壊れていると分かって表に足した。
欠陥1:受け取る設定が、送る側の門番になっていた
アプリには「共有の更新を通知で受け取るか」という設定があった。これは本来、自分が受け取るかどうかだけを決めるものだ。
ところがコードを読むと、この値が送る側の条件としても使われていた。該当箇所は7か所。つまり、受け取りを切っているメンバーが何かを変更すると、そのグループの全員に通知が送られない。
さらに悪いことに、この設定のスイッチは以前に画面から取り外していた。一度オフになった人は、自分では戻せない状態だった。本番のデータを見ると、オフのまま残っている記録が8件あった。
直し方は単純で、送る側の門番を全部取り除いた。受け取るかどうかは、サーバーが受け取る人本人の設定だけで判断する。残っていた8件のオフ設定も消した。
ここで一度「直った」と思った。鳴らなかった。
欠陥2:送った件数を、届いた件数として数えていた
次に疑ったのは、サーバーから通知の配信サービスへ送る部分だ。
配信サービスは、宛先1件ごとに「受け付けた」「受け付けなかった(理由つき)」を返してくる。ところが私のコードは、送った件数をそのまま成功数に足していた。返事の中身を読んでいなかった。
つまり、全部はじかれても記録には「全件送信」と残る。誰にも届かないのに、どこを見ても異常がない。今回の不具合がここまで見つからなかった理由の半分は、これだった。
受け付けられた分だけを数え、はじかれた分は理由ごとにログへ出すように変えた。この変更の直後、送信成功が0件という記録が初めて出た。それで次の欠陥が見えた。
欠陥3:Android は、そもそも通知の配線がなかった
成功0件の理由は「認証情報が無効」だった。
Android で通知を鳴らすには、Google の通知基盤にアプリを登録し、その設定ファイルをアプリに組み込み、配信サービス側にも鍵を登録する必要がある。確認すると、そのどれもやっていなかった。登録された宛先が0件なのも当然だった。
必要な手順を全部そろえて、初めて Android の端末で鳴った。途中で、設定ファイルを手で置いた場所が、ビルドの準備処理のたびに作り直されて消えるという罠も踏んだ。置き場所を「準備処理が読みに行く側」の設定に書くことで落ち着いた。
ここまで来ても、iPhone では鳴らなかった。
欠陥4:別のアプリ宛ての通知を1回にまとめて、丸ごとはじかれていた
これが本命だった。
私は同じ土台から、タスク管理・カレンダー・経路・推し活の4つのアプリを出している。配信サービスの側では、4つは別々のプロジェクトとして扱われる。そしてこのサービスには決まりがある。1回の送信に、別のプロジェクト宛ての通知を混ぜてはいけない。
混ぜるとどうなるか。1件だけ落ちるのではない。その送信がまるごと拒否され、1件も届かない。
コードには、アプリの種類を「カレンダーか、それ以外か」の2択に丸める書き方があった。経路アプリ宛ての通知が、タスク管理アプリ宛ての束に混ざっていた。
冒頭の表の「3件」が、ここで説明できた。届かなかった3グループは、全部私自身が入っているグループだった。私は4つのアプリを全部入れているので、私の宛先が混ざった束は必ず拒否される。私が居るグループだけが、構造的に沈黙していた。
「利用枠が1回分貯まった」通知が届かない4人も、複数のアプリを入れている人だった。週1回の自己診断は、持ち主の宛先をアプリを問わず1回にまとめて送っていたので、毎回必ず不達。異常を知らせるはずの仕組みが、静かに止まっていた。
直し方で迷ったところ
分け方には2つの選択肢があった。
- 呼び出す側で分ける:通知を出す場所それぞれで、アプリごとに分けてから送る
- 共通の出口で分ける:送信を担う1か所が、受け取った束を機械的にアプリごとに分ける
前者は、通知を出す場所を増やすたびに分け忘れる余地が残る。実際、今回壊れていたのは3か所だった。後者を選んだ。
加えて、1つの束が拒否されても即座に処理を止めないようにした。止めると、残りの束の宛先まで全員が無音になる。全部の束が落ちた時だけエラーにする。
実はこの修正の当日、同じ形でもう一度つまずいた。分けるときに「知っているアプリの一覧」を使ったところ、推し活アプリがその一覧に入っておらず、タスク管理アプリの束に丸められて、再び全滅した。今は、宛先に記録されているアプリの印を丸めずにそのまま使って分けている。一覧に頼る分け方は、足し忘れた瞬間に黙って壊れる。
4つを並べて見えたこと
| 欠陥 | 1つだけ直した場合 | 異常の見え方 |
|---|---|---|
| 1. 受け取り設定が送る側の門番 | 鳴らない | 何も出ない |
| 2. 送信数を成功数として記録 | 鳴らない | 「全件成功」と出る |
| 3. Android の配線なし | Android だけ鳴る | 何も出ない |
| 4. 別アプリ宛てを混ぜて拒否 | 鳴らない | 何も出ない |
4つとも、失敗が表に出ない形をしていた。だから1つ見つけて直すたびに「これが原因だった」と思えてしまう。私は実際に、1つ目を直した時点で一度そう判断している。
今回あとから決めた確認の仕方は1つだけだ。その原因で、症状の全部を説明できるか。 欠陥1では「私の居るグループだけが全滅する」ことを説明できなかった。そこで止まって考えていれば、もっと早く4つ目に辿り着けたはずだ。
修正を配ったあと、同じ操作をもう一度実行し、サーバーの記録で「混在による拒否」「束の失敗」「未達」がすべて0件になったことを確かめた。ただし、共有相手の iPhone で実際に鳴ったかどうかは、この記事の時点ではまだ確かめられていない。記録の上で0件になったことと、相手の手元で鳴ったことは別の話なので、そこは分けて書いておく。
コメント (0)
まだコメントはありません。最初の一言を残しませんか?