概要
Amplifyが @model
で自動生成してくれるsubscriptionは何でもかんでも通知してくる。チャットを例にすると、チャットメッセージが投稿されたらどのチャットルームだろうが通知してくる。しかし現実的には特定のチャットルームの通知しか受けたくないはずだ。
公式ドキュメントにそういう場合の対応が書いてあるのだが、分かりづらいのと最後まで書かれていないのでやり方をメモ。
前提
例として、下記のようなスキーマが存在するとする。
Chatがチャットルームで、ChatMessageがその中でやり取りされるユーザのメッセージだ。
type Chat @model {
id: ID!
title: String!
}
type ChatMessage @model {
id: ID!
chatId: ID!
body: String
}
手順
Amplifyのsubscription自動生成を無効にする
まず、ChatMessageの @model
に subscriptions: null
を追加して、Subscriptionが勝手に作成されないようにする。
type ChatMessage @model(subscriptions: null) { # <-- これ
id: ID!
chatId: ID!
body: String
}
この段階で amplify push
する。しておかないと、後の手順で自分で定義するSubscriptionを push
する際に、既にAmplifyが自動生成したSubscriptionとぶつかってエラーになる。
% amplify push
パラメータ付きのSubscriptionを定義する
下記のように chatId
を引数に取るSubscriptionを記述する。当然、ChatMessage
typeに存在するフィールドを指定する必要がある。
type Subscription {
onCreateChatMessage(chatId: ID): ChatMessage @aws_subscribe(mutations: ["createChatMessage"])
}
onCreateChatMessage
の型は作成されたChatMessage
が返されるのでChatMessage
になる。
@aws_subscribe
ではsubscribeしたいmutationを指定する。この場合、createChatMessage
になる。
これで再度 amplify push
を実行する。
クライアントアプリで使用する
幸い、Amplifyがその他諸々は生成してくれるので、後は、クライアントアプリから呼び出すだけだ。JSの場合、下記のようになる。graphqlOperation
を使用して、追加した chatId
パラメータは見ての通りの渡し方になる。
import { API, graphqlOperation } from 'aws-amplify'
// 通知の受け取りを開始する
const subscription = API.graphql(
graphqlOperation(subscriptions.onCreateChatMessage, { chatId: currChatId }),
).subscribe({
next: ({ provider, value }) => {
console.log(value.data.onCreateChatMessage)
},
error: error => console.warn(error),
})
// 通知を止める(SPAなどで更新が不要になった場合など)
subscription.unsubscribe()
おまけ
これによりAmplifyが生成するコードには下記の変化がある。
-
amplify/backend/api/myapi/build/schema.graphql
の Subscription が自分で追加したonCreateChatMessage
に置き換わる。 - 自動生成してくれるsubscriptionのGraphQL(今回の場合
onCreateChatMessage
)がパラメータ付きに変わる。(JSの場合、 graphql/subscriptions.js にあたる。)
リゾルバには変化がない。GraphQLスキーマとGraphQLステートメントの変更だけでパラメータを追加できるようだ。