缓存的API很特别。由于它们是不可变的缓存,因此任何通常会改变可变缓存中一些元数据的操作(如TTL、使用数据等)都必须返回缓存的新实例。
除了实际的缓存API之外,还构建了一个“类似映射”的API,以便你可以在它们上使用Clojure的get、assoc、dissoc操作,但这个外观可能(并且确实)有一些奇特的边缘情况,例如在检查项目是否在缓存中以及然后查找它(然后它“消失”)之间的竞争条件--即使在缓存本身不可变的情况下。这给上游消费者带来了问题,例如core.memoize,它必须包含spin/retry逻辑,以避免错误地返回nil。
这就是为什么我添加了包装名称空间,该名称空间提供了一种更直观的“可变缓存”(通过在不可变缓存周围包装一个atom),但这些缓存的“安全”API并不真正“映射类似”:lookup-or-miss是使用最安全的函数,提供了一种避免竞争条件和重复执行的方法,同时仍然可以在必要时按需查找请求的值。
在创建后在缓存中“播种”一个新的值哈希表是固有的更改操作,就像“驱逐”。有一个“映射类似”的get操作是方便的,但前提是你愿意得到nil(或一个“丢失”的值),如果请求的缓存条目已过期。
正如readme说明中指出:"core.cache API难以正确使用。" 并链接到这篇文章
https://dev.to/dpsutton/exploring-the-core-cache-api-57al ,其中讨论了将缓存当作“仅仅是映射”处理而引起的野外bug。