Welcome! Please see the About page for a little more info on how this works.

0 votes
in core.cache by

I've been trying to wrap my head around core.cache, and it seems to me that the suggest use in the documentation, i.e.

`
(defn get-data [key]
(cache/lookup (swap! cache-store

                   #(if (cache/has? % key)
                      (cache/hit % key)
                      (cache/miss % key (retrieve-data key))))
            key))

`

will result in a (link: https://en.wikipedia.org/wiki/Cache_stampede text: Cache Stampede) since {{(retrieve-data key)}} might be called multiple times if swap! retries due to compare-and-swap misses. Unfortunately I don't have a suggestion on how this could be fixed.

4 Answers

0 votes
by
 
Best answer

This is fixed in org.clojure/core.cache "0.8.1" with the addition of the clojure.core.cache.wrapped namespace and, in particular, the new lookup-or-miss function in that namespace.

0 votes
by

Comment made by: seancorfield

It took me a while to find this suggested usage -- https://github.com/clojure/core.cache/wiki/Using

I should update that to use {{through-cache}} which is more idiomatic now:

(defn get-data [key] (cache/lookup (swap! cache-store cache/through-cache key retrieve-data) key))

It would still suffer from the same possibility of Cache Stampede but at least it would be consistent with the newer API.

I suspect using a local {{delay}} would mitigate the stampede issue but it would make for very ugly code and it would not play well with {{through-cache}} -- so I'll have to give that some thought.

0 votes
by

Comment made by: seancorfield

The local {{delay}} version would look like this:

`
(defn get-data [key]
(let [data (delay (retrieve-data key)]

(cache/lookup (swap! cache-store cache/through-cache key (fn [_] @data)) key)))

`

0 votes
by
Reference: https://clojure.atlassian.net/browse/CCACHE-50 (reported by alex+import)
...