Skip to content
Svante edited this page Sep 26, 2017 · 23 revisions

Using core.cache

note: see the page on including core.cache before you begin this section

Basic usage pattern

To use the cache implementations or extend the core.cache protocols you first need to require the proper namespace:

(require '[clojure.core.cache :as cache])

Next you should create an instance of a specific cache type, optionally seeded:

(def C (cache/fifo-cache-factory {:a 1, :b 2}))

Note that caches are immutable. To actually use it, you need to put it somewhere you can give it a lifecyle (see below “Putting it together”).

To find a value in a map by its key you have a couple choices:

(cache/lookup C :a)
;=> 1

(:b C)
;=> 2

To ensure the proper cache policies are followed for each specific type, the following has?/hit/miss pattern should be used:

(if (cache/has? C :c)     ;; has? checks that the cache contains an item
  (cache/hit C :c)        ;; hit returns a cache with any relevant internal information updated
  (cache/miss C :c 42))   ;; miss returns a new cache with the new item and without evicted entries
	
;=> {:a 1, :b 2, :c 42}

Using the has?/hit/miss pattern ensures that the thresholding and eviction logic for each implementation works properly. Avoid this pattern at your own risk.

Finally, to explicitly evict an element in a cache, use the evict function:

(cache/evict C :b)
	
;=> {:a 1}

For specific information about eviction policies and thresholds, view the specific documentation for each cache type listed in the next section.

Putting it together

The simplest way to get a cache that actually changes is to put it into an atom:

(defonce cache-store (atom (cache/lru-cache-factory {})))

Now, assuming that you have a function retrieve-data which actually gets your data, you do the has?-hit-miss triad in a transaction, then lookup on the returned cache:

(defn get-data [key]
  (cache/lookup (swap! cache-store
                       #(if (cache/has? % key)
                          (cache/hit % key)
                          (cache/miss % key (retrieve-data key))))
                key))

Builtin cache implementations

core.cache comes with a number of builtin immutable cache implementations, including (click through for specific information):

The core.cache implementations are backed by any map-like object. Additionally, each cache implements the Clojure map behaviors and can therefore serve as special maps or even as backing stores for other cache implementations. For caches taking a limit argument, the eviction policies tend not to apply until the limit has been exceeded.

Extending core.cache

See the section on creating custom caches for more information.

Nesting cache types

See the section on composing caches for more information.

Clone this wiki locally