如何使用订阅和AWS AppSync有效地同步Apollo的缓存

时间:2018-11-07 06:27:39

标签: node.js apollo offline-caching aws-appsync graphql-subscriptions

我在Node.js客户端中使用aws-appsync来保留数据项的缓存列表。此缓存必须始终可用,包括未连接到互联网时。

当我的Node应用程序启动时,它将调用一个查询,该查询从AppSync数据源返回整个项目列表。这是由Apollo的缓存存储所缓存的,该存储允许将来仅使用缓存进行查询(使用相同的GraphQL查询)。

该应用程序还订阅了能够修改其他客户端列表的突变。更改列表中的项目时,新数据将发送到应用程序。这样可以触发要重新获取整个列表的原始查询,从而使缓存保持最新状态。

仅更改一项时,获取整个列表效率不高。 如何在使高速缓存保持最新状态的同时最大程度地减少每次更改时必须获取的数据量?

该解决方案必须提供单点来访问缓存的数据。这可以是GraphQL查询,也可以直接访问缓存存储。但是,不能使用多个查询的结果。


Apollo documentation暗示应该可行:

  

在某些情况下,仅使用[自动商店更新]不足以使您的应用程序...正确更新。例如,如果要在不重新获取整个列表的情况下向对象列表中添加某些内容,则Apollo Client无法为您更新现有查询。

它建议的替代方法是重新获取(基本上是我上面描述的内容),然后使用update回调手动更新存储中的缓存查询结果。

  

使用update可以完全控制高速缓存,从而允许您以自己喜欢的任何方式对数据模型进行更改以响应突变。建议在查询后使用update更新缓存。

但是,这里指的是同一客户端所做的变异,而不是指使用订阅在客户端之间进行同步。 update回调选项似乎不适用于预订(提供更新的商品数据)或查询(可以获取更新的商品数据)。

1 个答案:

答案 0 :(得分:1)

只要您的预订包括已添加的全部资源,就应该可以通过直接读取和写入高速缓存来实现。假设我们从文档中获得了这样的订阅:

const COMMENTS_SUBSCRIPTION = gql`
  subscription onCommentAdded {
    commentAdded {
      id
      content
    }
  }
`;

“订阅”组件包含一个onSubscriptionData道具,因此我们应该能够按照以下方式进行操作:

<Subscription
  subscription={COMMENTS_SUBSCRIPTION}
  onSubscriptionData={({ client, subscriptionData: { data, error } }) => {
    if (!data) return
    const current = client.readQuery({ query: COMMENTS_QUERY })
    client.writeQuery({
      query: COMMENTS_QUERY,
      data: {
        comments: [...current.comments, data.commentAdded],
      },
    })
  }}
/>

或者,如果您使用的是纯JavaScript而不是React:

const observable = client.subscribe({ query: COMMENTS_SUBSCRIPTION })
observable.subscribe({
  next: (data) => {
    if (!data) return
    const current = client.readQuery({ query: COMMENTS_QUERY })
    client.writeQuery({
      query: COMMENTS_QUERY,
      data: {
        comments: [...current.comments, data.commentAdded],
      },
    })
  },
  complete: console.log,
  error: console.error
})