Name:
interface
Value:
Amplify has re-imagined the way frontend developers build fullstack applications. Develop and deploy without the hassle.

Page updated Jul 2, 2024

Maintenance ModeYou are viewing Amplify Gen 1 documentation. Amplify Gen 1 has entered maintenance mode and will reach end of life on May 1, 2027. New project should use Amplify Gen 2. For existing Gen 1 projects, a migration guide and tooling are available to help you upgrade. Switch to the latest Gen 2 docs →

リアルタイムイベントの購読

このガイドでは、リアルタイムデータ統合を有効にする利点と、これらのサブスクリプションを設定およびフィルタリングする方法について説明します。また、サブスクリプションの登録を解除する方法についても説明します。

始める前に、以下が必要です:

With versions of Amplify CLI @aws-amplify/cli@12.12.2 and API Category@aws-amplify/amplify-category-api@5.11.5, an improvement was made to how relational field data is handled in subscriptions when different authorization rules apply to related models in a schema. The improvement redacts the values for the relational fields, displaying them as null or empty, to prevent unauthorized access to relational data. This redaction occurs whenever it cannot be determined that the child model will be protected by the same permissions as the parent model.

Because subscriptions are tied to mutations and the selection set provided in the result of a mutation is then passed through to the subscription, relational fields in the result of mutations must be redacted.

If an authorized end-user needs access to the redacted relational field they should perform a query to read the relational data.

Additionally, subscriptions will inherit related authorization when relational fields are set as required. To better protect relational data, consider modifying the schema to use optional relational fields.

Based on the security posture of your application, you can choose to revert to the subscription behavior before this improvement was made.

To do so, use the subscriptionsInheritPrimaryAuth feature flag under graphqltransformer in the amplify/backend/cli.json file.

  • If enabled, subscriptions will inherit the primary model authorization rules for the relational fields.
  • If disabled, relational fields will be redacted in mutation response when there is a difference between auth rules between primary and related models.

リアルタイムサブスクリプションの設定

サブスクリプションはGraphQL機能で、特定のイベントが発生したときにサーバーがクライアントにデータを送信できます。例えば、APIを通じて新しいレコードが作成、更新、または削除されるときのイベントを購読できます。アプリケーションでサブスクリプションを使用してリアルタイムデータ統合を有効にすることができます。

import { Amplify, API } from 'aws-amplify';
import { GraphQLSubscription } from '@aws-amplify/api';
import * as subscriptions from './graphql/subscriptions';
import {
OnCreateTodoSubscription,
OnUpdateTodoSubscription,
OnDeleteTodoSubscription
} from './API';
// Subscribe to creation of Todo
const createSub = API.graphql<GraphQLSubscription<OnCreateTodoSubscription>>({
query: subscriptions.onCreateTodo
}).subscribe({
next: ({ provider, value }) => console.log({ provider, value }),
error: (error) => console.warn(error)
});
// Subscribe to update of Todo
const updateSub = API.graphql<GraphQLSubscription<OnUpdateTodoSubscription>>({
query: subscriptions.onUpdateTodo
}).subscribe({
next: ({ provider, value }) => console.log({ provider, value }),
error: (error) => console.warn(error)
});
// Subscribe to deletion of Todo
const deleteSub = API.graphql<GraphQLSubscription<OnDeleteTodoSubscription>>({
query: subscriptions.onDeleteTodo
}).subscribe({
next: ({ provider, value }) => console.log({ provider, value }),
error: (error) => console.warn(error)
});
// Stop receiving data updates from the subscription
createSub.unsubscribe();
updateSub.unsubscribe();
deleteSub.unsubscribe();
import { Amplify, API } from 'aws-amplify';
import * as subscriptions from './graphql/subscriptions';
// Subscribe to creation of Todo
const createSub = API.graphql({ query: subscriptions.onCreateTodo }).subscribe({
next: ({ provider, value }) => console.log({ provider, value }),
error: (error) => console.warn(error)
});
// Subscribe to update of Todo
const updateSub = API.graphql({ query: subscriptions.onUpdateTodo }).subscribe({
next: ({ provider, value }) => console.log({ provider, value }),
error: (error) => console.warn(error)
});
// Subscribe to deletion of Todo
const deleteSub = API.graphql({ query: subscriptions.onDeleteTodo }).subscribe({
next: ({ provider, value }) => console.log({ provider, value }),
error: (error) => console.warn(error)
});
// Stop receiving data updates from the subscription
createSub.unsubscribe();
updateSub.unsubscribe();
deleteSub.unsubscribe();

サーバー側のサブスクリプションフィルターの設定

サブスクリプションはサービス側のサブスクリプションフィルターを定義するためのオプションのfilter引数を受け取ります:

// ...
import { GraphQLSubscription } from '@aws-amplify/api';
import {
OnCreateTodoSubscriptionVariables,
OnCreateTodoSubscription
} from './API';
const variables: OnCreateTodoSubscriptionVariables = {
filter: {
// Only receive Todo messages where the "type" field is "Personal"
type: { eq: 'Personal' }
}
};
const sub = API.graphql<GraphQLSubscription<OnCreateTodoSubscription>>({
query: subscriptions.onCreateTodo,
variables
}).subscribe({
next: ({ provider, value }) => console.log({ provider, value }),
error: (error) => console.warn(error)
});
// ...
const variables = {
filter: {
// Only receive Todo messages where the "type" field is "Personal"
type: { eq: 'Personal' }
}
};
const sub = API.graphql({
query: subscriptions.onCreateTodo,
variables
}).subscribe({
next: ({ provider, value }) => console.log({ provider, value }),
error: (error) => console.warn(error)
});

すべてのサブスクリプションイベントを取得したい場合は、filterパラメーターを指定しないでください。

制限事項:

  • フィルターとして空のオブジェクト{}を指定することは推奨されません。フィルターとして{}を使用すると、データモデルの認可ルールに基づいて一貫性のない動作が発生する可能性があります。
  • 動的グループ認可を使用しており、レコードごとに単一のグループに基づいて認可している場合、サブスクリプションはユーザーが5つ以下のユーザーグループに属している場合にのみサポートされます。
  • さらに、グループの配列(groups: [String])を使用して認可している場合、
    • サブスクリプションはユーザーが20以下のグループに属している場合にのみサポートされます
    • レコードごとに20以下のユーザーグループのみを認可できます

サブスクリプション接続ステータスの更新

アプリケーションがサブスクリプションを使用するように設定されたので、サブスクリプションが最終的に確立されたときを知りたい場合や、サブスクリプションが正常でないことをユーザーに示したい場合があります。Hubローカルイベントシステムを通じて接続状態の変更を監視できます。

import { CONNECTION_STATE_CHANGE, ConnectionState } from '@aws-amplify/pubsub';
import { Hub } from 'aws-amplify';
Hub.listen('api', (data: any) => {
const { payload } = data;
if (payload.event === CONNECTION_STATE_CHANGE) {
const connectionState = payload.data.connectionState as ConnectionState;
console.log(connectionState);
}
});

サブスクリプション接続ステート

  • Connected - 接続されており、問題なく動作しています。
  • ConnectedPendingDisconnect - 接続にはアクティブなサブスクリプションがなく、切断しています。
  • ConnectedPendingKeepAlive - 接続は開いていますが、予期されたキープアライブメッセージを見落としています。
  • ConnectedPendingNetwork - 接続は開いていますが、ネットワーク接続が中断されています。ネットワークが回復すると、接続はトラフィックの提供を継続します。
  • Connecting - 接続を試みています。
  • ConnectionDisrupted - 接続が中断され、ネットワークが利用可能です。
  • ConnectionDisruptedPendingNetwork - 接続が中断され、ネットワーク接続が利用不可です。
  • Disconnected - 接続にはアクティブなサブスクリプションがなく、切断しています。
トラブルシューティング
接続の問題のトラブルシューティングと自動再接続

アプリケーションとバックエンドサブスクリプション間の接続は、ネットワーク障害やデバイスがスリープモードに入るなど、さまざまな理由で中断される可能性があります。サブスクリプションは、接続できるようになったときに自動的に再接続します。

オフラインの間、アプリケーションはメッセージを見落とし、再接続時に自動的に追いつくことはありません。ユースケースによっては、アプリケーションが再度オンラインになったときに追いつくためにアクションを取りたい場合があります。

// ...
import { GraphQLQuery, GraphQLSubscription } from '@aws-amplify/api';
import {
ListTodosQuery
OnCreateTodoSubscription,
OnUpdateTodoSubscription,
OnDeleteTodoSubscription
} from './API';
const fetchRecentData = () => {
// Retrieve some/all data from AppSync
const allTodos = await API.graphql<GraphQLQuery<ListTodosQuery>>({
query: queries.listTodos
});
}
let priorConnectionState: ConnectionState;
Hub.listen("api", (data: any) => {
const { payload } = data;
if (
payload.event === CONNECTION_STATE_CHANGE
) {
if (priorConnectionState === ConnectionState.Connecting && payload.data.connectionState === ConnectionState.Connected) {
fetchRecentData();
}
priorConnectionState = payload.data.connectionState;
}
});
const createSub = API.graphql<GraphQLSubscription<OnCreateTodoSubscription>>(
{ query: subscriptions.onCreateTodo }
).subscribe({
next: data => // Process incoming messages
});
const updateSub = API.graphql<GraphQLSubscription<OnUpdateTodoSubscription>>(
{ query: subscriptions.onUpdateTodo }
).subscribe({
next: data => // Process incoming messages
});
const deleteSub = API.graphql<GraphQLSubscription<OnDeleteTodoSubscription>>(
{ query: subscriptions.onDeleteTodo }
).subscribe({
next: data => // Process incoming messages
});
const cleanupSubscriptions = () => {
createSub.unsubscribe();
updateSub.unsubscribe();
deleteSub.unsubscribe();
}
// ...
const fetchRecentData = () => {
// Retrieve some/all data from AppSync
const allTodos = await API.graphql({ query: queries.listTodos });
}
let priorConnectionState: ConnectionState;
Hub.listen("api", (data: any) => {
const { payload } = data;
if (
payload.event === CONNECTION_STATE_CHANGE
) {
if (priorConnectionState === ConnectionState.Connecting && payload.data.connectionState === ConnectionState.Connected) {
fetchRecentData();
}
priorConnectionState = payload.data.connectionState;
}
});
const createSub = API.graphql(
{ query: subscriptions.onCreateTodo }
).subscribe({
next: data => // Process incoming messages
});
const updateSub = API.graphql(
{ query: subscriptions.onUpdateTodo }
).subscribe({
next: data => // Process incoming messages
});
const deleteSub = API.graphql(
{ query: subscriptions.onDeleteTodo }
).subscribe({
next: data => // Process incoming messages
});
const cleanupSubscriptions = () => {
createSub.unsubscribe();
updateSub.unsubscribe();
deleteSub.unsubscribe();
}
ウォークスルー
IDによるカスタムGraphQLサブスクリプションの作成

このウォークスルーでは、引数として特定のIDを含むミューテーションによってのみ接続および トリガーされるカスタムGraphQLサブスクリプションを作成するための追加のステップバイステップガイダンスを提供します。例えば、次のGraphQLスキーマを参照してください:

type Post @model @auth(rules: [{ allow: public }]) {
id: ID!
title: String!
content: String
comments: [Comment] @hasMany
}
type Comment @model @auth(rules: [{ allow: public }]) {
id: ID!
content: String
}

デフォルトでは、次のミューテーションのサブスクリプションが作成されます:

# Post type
onCreatePost
onUpdatePost
onDeletePost
# Comment type
onCreateComment
onUpdateComment
onDeleteComment

カバーされていない1つの操作は、1つの特定のポストのコメントのみを購読する方法です。

スキーマではポストとコメント間の1対多の関係が有効になっているため、自動生成されたフィールドpostCommentsIdを使用できます。これは関係を定義し、新しいサブスクリプションでこれを設定できます。

これを実装するには、スキーマを以下で更新してください:

type Post @model @auth(rules: [{ allow: public }]) {
id: ID!
title: String!
content: String
comments: [Comment] @hasMany
}
type Comment @model @auth(rules: [{ allow: public }]) {
id: ID!
content: String
postCommentsId: ID!
}
type Subscription {
onCommentByPostId(postCommentsId: ID!): Comment
@aws_subscribe(mutations: ["createComment"])
}

これで、特定のポストIDでコメント作成のカスタムサブスクリプションを作成できます:

import { API } from 'aws-amplify';
import { onCommentByPostId } from './graphql/subscriptions';
API.graphql({
query: onCommentByPostId,
variables: {
postCommentsId: '12345'
}
}).subscribe({
next: (data) => {
console.log('data: ', data);
}
});

サブスクリプションから登録を解除する

次のを実装することで、サブスクリプションによってイベントから登録を解除することもできます:

// Stop receiving data updates from the subscription
sub.unsubscribe();

まとめ

おめでとうございます! リアルタイムイベントの購読ガイドが完了しました。このガイドでは、リアルタイムイベントのサブスクリプションを設定し、これらのサブスクリプションをフィルタリングして必要に応じてキャンセルする方法を学びました。

次のステップ

推奨される次のステップには、データの情報アーキテクチャを継続して構築およびカスタマイズすることが含まれます。この作業に役立つリソースをいくつか紹介します: