概要
Amazon SNS のCreatePlatformEndpointというAPIは
同じトークンと属性であれば同じエンドポイントを返却する(冪等性)ということでしたので、
安心して毎回CreatePlatformEndpointを呼ぶようにしていました。
しかし、使っている内にいつの間にか同じトークンに対して複数のエンドポイントが作成される事態に。
さらに、これだけならまだよかったのですが3つを超えるエンドポイントを作成しようとすると
エラーが発生してそれ以上エンドポイントを作成できないという詰んだ状態に。。。
原因を特定するのにかなりの時間がかかってしまったため、
同じような境遇の人たちのため、以下に詳細を記載しておきます。
原因
GCMとSNSの仕様が原因ということがわかりました。
- GCM
- 古いトークンに対してプッシュするとGCMは最新のトークンを返却
- 古いトークンは一定期間有効で、複数前のトークンでも最新のトークンを返却
- SNS
- GCMから新しいトークンが返却されると、古いトークンを新しいトークンに自動で書き換え
- 同じトークンに対して異なるエンドポイントを4つ以上作成しようとするとInvalidParameterExceptionをthrow
- (プッシュのトークン自動書き換え時にExceptionは発生しない)
発生条件
- GCM or FCM?
- GCMでしか確認できていない。FCMも一緒?
- 古いトークンに対してプッシュ
再現手順
- GCM導入済みのアプリをインストール
- トークンAを取得し、DBに保存
- CreatePlatformEndpointでトークンAからエンドポイントAを取得し、DBに保存
- アプリをアンインストール
- アプリを再度インストール
- トークンBを取得し、DBに保存
- CreatePlatformEndpointでトークンBからエンドポイントBを取得、DBに保存
- トークンAを使用してSNSでプッシュ
- エンドポイントAに紐づくトークンAがトークンBに書き換わる
- SNS上ではトークンBに対してエンドポイントAとBの2つが作成された状態となる
上記5〜8を繰り返すと同じトークンに対して異なるエンドポイントが作成されていきます。
もし、9の時点でトークンBに紐づくエンドポイントが3つ作成された状態だった場合、
トークンBで再度CreatePlatformEndpointを実行すると、
「This endpoint is already registered with a different token」
というInvalidParameter例外がthrowされ、それ以上エンドポイントを作成することはできなくなります。
対応策
上記のInvalidParameterを回避するためには、エンドポイントを作成済みのトークンで
再度CreatePlatformEndpointを実行しないようにする必要があります。
AWSのサポートに問い合わせたところ、
以下のサイトにある方法でトークンを管理することで上記の問題を解決できるとのことでした。
プラットフォームエンドポイントの作成とデバイストークンの管理 擬似コード
つまり、一度作成したエンドポイントはトークンと共にDBやアプリ内に保存しておき、
2度目以降はCreatePlatformEndpointを実行しないようにすればいいわけですね。
みなさんも Amazon SNS を使用する際は上記に気をつけて実装してください。
参考
API Reference CreatePlatformEndpoint
プラットフォームエンドポイントの作成とデバイストークンの管理 擬似コード
プラットフォームエンドポイントの作成とデバイストークンの管理 トラブルシューティング
Amazon SNS のモバイルトークン管理についてのベストプラクティス