コンテンツにスキップ

プッシュ通知の設計

プッシュは「合図」

Taylis では、プッシュ通知は 「新しいデータがあるかもしれない」という合図 で、同期の手段ではありません。 通知が遅れる・重複する・順番が入れ替わる・届かない、のどれが起きても、システムは正しく動きます。 通知を受け取ったアプリは、サーバと同期してから内容を表示します。

流れ

flowchart TD
  E["メッセージの作成<br>(outbox のイベント)"] --> PL["送る相手を決める<br>PushPlanner"]
  PL --> Q[("送信待ちの行<br>同じイベント × 端末は 1 行")]
  Q --> PS["送信 PushSender<br>直前に既読かを確かめる"]
  PS -- "iOS(.p8 の鍵)" --> APNS["APNs"]
  PS -- "Android(サービスアカウント)" --> FCM["FCM"]
  APNS --> DEV["スマートフォン"]
  FCM --> DEV
  DEV -. "通知を受けたら" .-> SYNC["サーバと同期して<br>から表示"]
  • 送信待ちの行はデータベースに残るので、送信中にサーバが落ちても、再起動の後に続きから送ります。
  • 同じ通知が 2 回送られても、端末の側で 1 つにまとめます(collapse)。
  • プロバイダの違いは PushProvider の実装(APNs / FCM)に閉じ込めています。
  • デスクトップ版はプッシュを使わず、WebSocket のイベントからアプリが OS の通知を出します。

送らない場面

場面 理由
自分の投稿 自分には知らせない
別の端末で使っている間 パソコンで読んでいるときにスマートフォンを鳴らさない
すでに既読 送る直前にも確かめる
通知のレベルが「なし」・ミュート・一時停止・おやすみ時間 本人の設定
参加していないスレッドの返信 フォローしている人とメンションされた人だけ
ブロックしている相手から 本人の設定
参加・退出の 1 行 知らせる必要がない
古すぎる通知 期限を過ぎたものは送らない

通知が届かなくても困らない理由

  • アプリは起動のとき・前面に戻ったときに必ずサーバと同期します。
  • 未読はサーバに残っているので、通知が届かなかったメッセージも失われません。
  • 無効になったトークン(アプリを消した端末など)は自動で消し、アプリが開かれたときに登録し直します。

通知の内容

通知の本文にはメッセージの抜粋が入ります。サーバの設定 PUSH_INCLUDE_CONTENT=false にすると、本文を入れず 「新しいメッセージがあります」のような文だけにできます(APNs や FCM に本文を渡したくない場合)。

詳しくは docs/PUSH_NOTIFICATIONS.md をご覧ください。