所以我使用congomongo(接近结尾的fetch函数)从mongodb集合中提取一些文档.我想将选项传递给fetch调用,所以我可以做类似的事情(posts :limit 1)并且已经{:limit 1}传递给fetch.我正在手动"memoization" @posts,因为我希望能够重置缓存,这对我的理解是不能完成的clojure.core/memoize.
现在,我在这里看到的问题是,(fetch :posts options)调用非常简单,如果dosync必须重试事务,我真的不想锤击我的数据存储区.我虽然是一个完全的clojure/fp noob,我不知道如何解决这个问题.此外,由于我是一个菜鸟,如果我在这里做任何让你畏缩的事情,我很想知道如何正确地写这个.
(def posts (ref nil))
(defn reset-posts [] (dosync alter posts nil))
(defn fetch-posts [& options]
(let [options (apply array-map options)]
(or @posts
(dosync alter posts (fetch :posts options)))))
Run Code Online (Sandbox Code Playgroud)
我不相信你的交易阻止((dosync alter...)按照你的想法行事!
user=> (def posts (ref nil))
#'user/posts
user=> (dosync (ref-set posts [1 2 3 4 5]))
[1 2 3 4 5]
user=> @posts
[1 2 3 4 5]
user=> (dosync alter posts nil)
nil
user=> @posts
[1 2 3 4 5]
Run Code Online (Sandbox Code Playgroud)
在reset-posts,您可能希望(dosync (ref-set posts nil))并且在fetch-posts语法修复中(dosync (ref-set posts (fetch :posts options))).
然而,有一个竞争条件fetch-posts,一个检查然后行动.可能不是那么大的交易; 不确定谁使用fetch-posts,但移动or @posts事务内的位将避免2个并发事务最终提交更改的情况.
关于重试fetch-posts,是的,这可能发生,虽然你的缓存解决方案避免了大多数.不过,我不确定它是否有办法绕过它.通常在事务中使用I/O内容将其存储到代理中,但事务的成功取决于返回值fetch,因此我不清楚它是如何工作的.