

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 使用中的过滤器取消订阅 WebSocket 连接 Amazon AppSync
<a name="aws-appsync-real-time-invalidation"></a>

**重要**  
从 2025 年 3 月 13 日起， WebSockets 您可以使用 Amazon AppSync 事件构建实时 PubSub API。有关更多信息，请参阅[事件开发者指南 WebSocket中的通过发布Amazon](https://docs.amazonaws.cn/appsync/latest/eventapi/publish-websocket.html)*AppSync 事件*。

在中 Amazon AppSync，您可以根据特定的筛选逻辑强制取消订阅并关闭（使 WebSocket连接失效）来自已连接客户端的连接。这在与授权相关的场景中非常有用，例如，在您从组中删除用户时。

订阅失效是针对变更中定义的负载做出的响应。我们建议您将用于使订阅连接失效的变更视为 API 中的管理操作，并仅限管理员用户、组或后端服务使用这些变更以相应地设置其权限范围。例如，使用架构授权指令，例如 `@aws_auth(cognito_groups: ["Administrators"])` 或 `@aws_iam`。有关更多信息，请参阅[使用其他授权模式](https://docs.amazonaws.cn/appsync/latest/devguide/security-authz.html#using-additional-authorization-modes)。

失效筛选条件使用与[增强订阅筛选条件](https://docs.amazonaws.cn/appsync/latest/devguide/aws-appsync-real-time-enhanced-filtering.html)相同的语法和逻辑。请使用以下实用程序定义这些筛选条件：
+ `extensions.invalidateSubscriptions()` - 在变更的 GraphQL 解析器响应处理程序中定义。
+ `extensions.setSubscriptionInvalidationFilter()` - 在链接到变更的订阅的 GraphQL 解析器响应处理程序中定义。

有关失效筛选扩展插件的更多信息，请参阅[JavaScript解析器](https://docs.amazonaws.cn/appsync/latest/devguide/resolver-reference-overview-js.html)概述。

## 使用订阅失效
<a name="aws-appsync-real-time-invalidation-using-invalidations"></a>

要查看订阅失效的工作原理 Amazon AppSync，请使用以下 GraphQL 架构：

```
type User {
  userId: ID!
  groupId: ID!
}
    
type Group {
  groupId: ID!
  name: String!
  members: [ID!]!
}

type GroupMessage {
  userId: ID!
  groupId: ID!
  message: String!
}

type Mutation {
    createGroupMessage(userId: ID!, groupId : ID!, message: String!): GroupMessage
    removeUserFromGroup(userId: ID!, groupId : ID!) : User @aws_iam
}

type Subscription {
    onGroupMessageCreated(userId: ID!, groupId : ID!): GroupMessage
        @aws_subscribe(mutations: ["createGroupMessage"])
}

type Query {
	none: String
}
```

在 `removeUserFromGroup` 变更解析器代码中定义失效筛选条件：

```
import { extensions } from '@aws-appsync/utils';

export function request(ctx) {
	return { payload: null };
}

export function response(ctx) {
	const { userId, groupId } = ctx.args;
	extensions.invalidateSubscriptions({
		subscriptionField: 'onGroupMessageCreated',
		payload: { userId, groupId },
	});
	return { userId, groupId };
}
```

在调用变更时，`payload` 对象中定义的数据用于取消订阅 `subscriptionField` 中定义的订阅。还会在 `onGroupMessageCreated` 订阅的响应映射模板中定义一个失效筛选条件。

如果`extensions.invalidateSubscriptions()`有效载荷包含的 ID 与过滤器中定义的 IDs 来自已订阅客户端的 ID 相匹配，则相应的订阅将被取消订阅。此外， WebSocket 连接已关闭。定义 `onGroupMessageCreated` 订阅的订阅解析器代码：

```
import { util, extensions } from '@aws-appsync/utils';

export function request(ctx) {
	// simplfy return null for the payload
	return { payload: null };
}

export function response(ctx) {
	const filter = { groupId: { eq: ctx.args.groupId } };
	extensions.setSubscriptionFilter(util.transform.toSubscriptionFilter(filter));

	const invalidation = { groupId: { eq: ctx.args.groupId }, userId: { eq: ctx.args.userId } };
	extensions.setSubscriptionInvalidationFilter(util.transform.toSubscriptionFilter(invalidation));

	return null;
}
```

请注意，订阅响应处理程序可以同时定义订阅筛选条件和失效筛选条件。

例如，假设客户端 A 使用以下订阅请求为具有 ID `{{user-1}}` 的新用户订阅具有 ID `{{group-1}}` 的组：

```
onGroupMessageCreated(userId : "{{user-1}}", groupId: :"{{group-1}}"){...}
```

Amazon AppSync 运行订阅解析器，该解析器生成前面的`onGroupMessageCreated`响应映射模板中定义的订阅和失效过滤器。对于客户端 A，订阅筛选条件仅允许将数据发送到 `{{group-1}}`，并为 `{{user-1}}` 和 `{{group-1}}` 定义了失效筛选条件。

现在假设客户端 B 使用以下订阅请求为具有 ID `{{user-2}}` 的用户订阅具有 ID `{{group-2}}` 的组：

```
onGroupMessageCreated(userId : "{{user-2}}", groupId: :"{{group-2}}"){...}
```

Amazon AppSync 运行订阅解析器，它会生成订阅和失效过滤器。对于客户端 B，订阅筛选条件仅允许将数据发送到 `{{group-2}}`，并为 `{{user-2}}` 和 `{{group-2}}` 定义了失效筛选条件。

接下来，假设使用变更请求创建 ID 为 `{{message-1}}` 的新组消息，如以下示例中所示：

```
createGroupMessage(id: "{{message-1}}", groupId :
      "{{group-1}}", message: "test message"){...}
```

与定义的过滤器匹配的订阅客户端会自动通过 WebSockets以下方式接收以下数据负载：

```
{
  "data": {
    "onGroupMessageCreated": {
      "id": "message-1",
      "groupId": "group-1",
      "message": "test message",
    }
  }
}
```

客户端 A 收到该消息，因为筛选条件与定义的订阅筛选条件匹配。不过，客户端 B 不会收到该消息，因为该用户不属于 `{{group-1}}`。此外，请求与订阅解析器中定义的订阅筛选条件不匹配。

最后，假设使用以下变更请求从 `{{group-1}}` 中删除了 `{{user-1}}`：

```
removeUserFromGroup(userId: "user-1", groupId : "group-1"){...}
```

该突变会启动订阅失效，如其`extensions.invalidateSubscriptions()`解析器响应处理程序代码中所定义。 Amazon AppSync 然后取消订阅客户端 A 并关闭其连接。 WebSocket 客户端 B 不受影响，因为变更中定义的失效负载与其用户或组不匹配。

当连接 Amazon AppSync 失效时，客户端会收到一条消息，确认他们已取消订阅：

```
{
  "message": "Subscription complete."
}
```

## 在订阅失效筛选条件中使用上下文变量
<a name="aws-appsync-real-time-invalidation-context"></a>

与增强订阅筛选条件一样，您可以在订阅失效筛选条件扩展中使用 [`context` 变量](https://docs.amazonaws.cn/appsync/latest/devguide/resolver-context-reference-js.html)以访问某些数据。

例如，可以在变更中将电子邮件地址配置为失效负载，然后将其与通过 Amazon Cognito 用户池或 OpenID Connect 授权的订阅用户的电子邮件属性或声明进行匹配。失效筛选条件（在 `extensions.setSubscriptionInvalidationFilter()` 订阅失效器中定义）检查变更的 `extensions.invalidateSubscriptions()` 负载设置的电子邮件地址是否与从用户 JWT 令牌的 `context.identity.claims.email` 中检索的电子邮件地址匹配，从而启动失效。