カスタムリアルタイムサブスクリプションを追加
任意のミューテーションに対するカスタムリアルタイムサブスクリプションを作成して、PubSubユースケースを有効にします。
カスタムサブスクリプションを定義
カスタムサブスクリプションごとに、以下を設定する必要があります:
- サブスクリプションイベントをトリガーするミューテーション
- サブスクリプション対象のミューテーションの戻り値の型と一致する戻り値の型
- 認可ルール
オプションで、フィルター引数を設定してサーバー側のサブスクリプションフィルタールールをカスタマイズできます。
amplify/data/resource.ts ファイルで a.subscription() を使用してカスタムサブスクリプションを定義します:
import { type ClientSchema, a, defineData } from '@aws-amplify/backend';
const schema = a.schema({ // このPubSubサンプルで使用されるMessageタイプ Message: a.customType({ content: a.string().required(), channelName: a.string().required() }),
// メッセージパブリッシュミューテーション publish: a.mutation() .arguments({ channelName: a.string().required(), content: a.string().required() }) .returns(a.ref('Message')) .handler(a.handler.custom({ entry: './publish.js' })) .authorization(allow => [allow.publicApiKey()]),
// 受信メッセージをサブスクライブ receive: a.subscription() // 'publish'ミューテーションをサブスクライブ .for(a.ref('publish')) // カスタムフィルターを設定するサブスクリプションハンドラー .handler(a.handler.custom({entry: './receive.js'})) // データにサブスクライブできるユーザーの認可ルール .authorization(allow => [allow.publicApiKey()]),
// チャネルを管理するデータモデル Channel: a.model({ name: a.string(), }).authorization(allow => [allow.publicApiKey()]),});
export type Schema = ClientSchema<typeof schema>;
export const data = defineData({ schema});この例では、汎用的なPubSub機能を構築しています。これには publish の引数を Channel の形式に変換する必要があります。amplify/data/ フォルダに以下の内容の新しい publish.js ファイルを作成します:
// このハンドラーは単にミューテーションの引数を結果として渡すだけですexport function request() { return {}}
/** * @param {import('@aws-appsync/utils').Context} ctx */export function response(ctx) { return ctx.args}次に、amplify/data/ フォルダに新しい receive.js ファイルを作成してサブスクリプションのハンドラーを定義します。この場合は単純なパススルーです。次のセクションでは、このハンドラーを使用してより高度なサブスクリプションフィルターを構築する方法を説明します。
export function request() { return {};}
export const response = (ctx) => { return ctx.result;};クライアント側でカスタムサブスクリプションをサブスクライブ
生成されたDataクライアントから、client.subscriptions の下にすべてのカスタムサブスクリプションが見つかります。.subscribe() 関数を使用してサブスクライブし、next 関数を使用して受信イベントを処理します。
import { generateClient } from 'aws-amplify/data'import type { Schema } from '../amplify/data/resource'
const client = generateClient<Schema>()
const sub = client.subscriptions.receive() .subscribe({ next: event => { console.log(event) } })カスタムミューテーションを使用してイベントをパブリッシュすることで、リアルタイムサブスクリプションをテストできます。
client.mutations.publish({ channelName: "world", content: "My first message!"})サブスクリプションイベントが受信され、ペイロードがアプリの開発者コンソールにログされます。unsubscribe() 関数を使用してサブスクリプションを切断します。
sub.unsubscribe()(オプション)サーバー側のサブスクリプションフィルターを追加
カスタムサブスクリプションに引数を追加することで、サブスクリプションフィルターを追加できます。
フィルターをカスタマイズしたい場合は、サブスクリプションハンドラーを変更します。この例では、顧客が namePrefix パラメータを渡すことができるようにして、エンドユーザーが namePrefix で始まるチャネル内のチャネルイベントのみを受信できるようにします。
import { type ClientSchema, a, defineData } from '@aws-amplify/backend';
const schema = a.schema({ Channel: a.model({ name: a.string(), }).authorization(allow => [allow.publicApiKey()]),
Message: a.customType({ content: a.string().required(), channelName: a.string().required() }),
publish: a.mutation() .arguments({ channelName: a.string().required(), content: a.string().required() }) .returns(a.ref('Message')) .handler(a.handler.custom({ entry: './publish.js' })) .authorization(allow => [allow.publicApiKey()]),
receive: a.subscription() .for(a.ref('publish')) .arguments({ namePrefix: a.string() }) .handler(a.handler.custom({entry: './receive.js'})) .authorization(allow => [allow.publicApiKey()])});
export type Schema = ClientSchema<typeof schema>;
export const data = defineData({ schema});ハンドラーで、カスタムサブスクリプションに渡される引数に基づいてカスタムサブスクリプションフィルターを設定できます。この例では、amplify/data/resource.ts ファイルの横に新しい receive.js ファイルを作成します:
import { util, extensions } from "@aws-appsync/utils"
// サブスクリプションハンドラーはリクエストで `null` ペイロードを返す必要がありますexport function request() { return { payload: null } }
/** * @param {import('@aws-appsync/utils').Context} ctx */export function response(ctx) { const filter = { channelName: { beginsWith: ctx.args.namePrefix } }
extensions.setSubscriptionFilter(util.transform.toSubscriptionFilter(filter))
return null}