为部分 graphQL 查询指定缓存策略

Posted

技术标签:

【中文标题】为部分 graphQL 查询指定缓存策略【英文标题】:Specify cache policy for parts of a graphQL query 【发布时间】:2021-03-07 20:51:26 【问题描述】:

在 Apollo 的 GraphQL 版本中,有fetch policies 指定获取查询是应该从服务器获取数据还是使用本地缓存(如果有数据可用)。

此外,缓存规范化允许使用缓存来减少需要从服务器获取的数据量。例如,如果我请求对象 A 和对象 B,但之前我请求了 A 和 C,那么在我当前的查询中,它将从缓存中获取 A,并从服务器获取 B。

但是,它们为整个查询指定缓存策略。我想知道是否有一种方法可以在各个字段上指定 TTL。

从开发人员的角度来看,我希望能够在我的查询中指定我想缓存我请求的某些信息,而不是其他信息。例如,采用以下查询:

query PersonInfo($id: String) 
  person(id: $id) 
    birthcertificate  // Once this is cached, it is cached forever. I should just always get this info from the cache if it is available.
    age // I want to have this have a TTL of a day before invalidating the cached value and going to network
    legalName // I want to always go to network for this information. 
  

换句话说,对于固定的id 值(并假设这是唯一涉及人员对象或其字段的查询):

第一次进行此查询时,我从服务器获取了所有三个字段。 现在,如果我在几秒钟内再次进行此查询,我应该只从服务器获取第三个字段 (legalName),从缓存中获取前两个。 现在,如果我等待超过一天,然后再次进行此查询,我会从缓存中获得birthCertificate,并从服务器获得age + legalName

目前,要按照我想要的方式执行此操作,我最终编写了三个不同的查询,每个查询一个 TTL。有没有更好的办法?

更新:在 ios 客户端 (https://github.com/apollographql/apollo-ios/issues/142) 上完成的缓存计时有一些进展,但没有具体说明?

【问题讨论】:

【参考方案1】:

这将是一个不错的功能,但 AFAIK [目前,采用 js/react 客户端,可能与 ios 相同]:

没有query normalization,只有cache normalization

如果缓存中不存在任何请求的字段,则从网络获取整个查询

没有时间存储在缓存 [规范化] 条目中(每个查询/每个类型)

目前 [仅?] 解决方案是 [保存在本地状态/] 存储每个/所有/某些查询/响应的时间戳(例如在 onCompleted 中),并在获取之前使用它使它们无效/驱逐。它可能是自动化的。在某些字段策略 fn 中启动计时器。

您可以在登录后开始(会话)时获取人员数据......任何后续和更精细的person(id: $id) birthcertificate 查询(如在反应子组件中)都可以有“自己的”“仅缓存”策略。如果您需要始终保持新鲜的legalName,请使用network-only 政策[单独或不] 获取它。

【讨论】:

您能否简要解释一下我如何在获取之前使用字段策略进行驱逐? 如果它可以用来读取localStorage,那么它可以使用任何全局对象/函数来启动监控/重置计时器,用于在一段时间后驱逐缓存条目 介意链接到如何实现这一点的示例?

以上是关于为部分 graphQL 查询指定缓存策略的主要内容,如果未能解决你的问题,请参考以下文章

Squid 缓存服务器的缓存代理,及配置 Squid 的ACL访问控制策略

缓存淘汰策略之LRU

缓存淘汰策略

自动为整个 S3 存储桶设置缓存控制(使用存储桶策略?)

Caffeine缓存

架构设计 | 缓存管理模式,监控和内存回收策略