Easy to use Clojure wrappers for Caffeine
(require '[fmnoise.coldbrew :refer [cached defcached]])
The main building block is cached
function which accepts function and returns cached version of it.
Cache options are passed as meta attached to function. Supported options are:
:expire
, uses expireAfterWrite:refresh
, uses refreshAfterWriteLet's create a cached function with expiration time 1 hour (3600 sec):
(defn fetch-customer [base-url id]
(http/get (str base-url "/customers/" id)))
(def cached-customer-fetch
(cached (with-meta fetch-customer {:expire 3600})))
We can achieve same result using anonymous function:
(def cached-customer-fetch
(cached
(with-meta
(fn [base-url id]
(http/get (str base-url "/customers/" id))
{:expire 3600})))
There's also more flexible defcached
macro which uses cached
under the hood.
The main purpose of it is ability to build cache key from function agruments:
(defcached fetch-customer ;; function name
[{:keys [base-url timeout]} id] ;; function args
^{:expire 3600} ;; cache options passed as meta attached to cache key
[id] ;; cache key - a vector which will become args for internal caching function
;; function body
(let [result (deref (http/get (str base-url "/customer/" id)) timeout ::timeout)]
(if (= result ::timeout)
(throw (ex-info "Request timed out" {:id id}))
result))
All meta passed to function name is preserved, so we can have private cached function and add docstring:
(defcached
^{:private true
:doc "Fetches customer with given id"}
fetch-customer-impl [{:keys [base-url timeout]} id]
^{:expire 3600}
[id]
(let [result (deref (http/get (str base-url "/customer/" id)) timeout ::timeout)]
(if (= result ::timeout)
(throw (ex-info "Request timed out" {:id id}))
result)))
NB: Docstring is only supported as meta
Due to defn-like declaration it's very easy to refactor existing defn
to cached function using defcached
macro:
defn
to defcached
NB: If you later decide to return back to defn
and forget to remove cache key, nothing will break.
Same as consuming coldbrew drink in reality, make sure you don't exceed recommended coffeine amount, as each call to cached
creates separate Caffeine Loading Cache instance. Also make sure you understand risk of memory leaks when caching large objects or collections.
Coldbrew icon made by Eucalyp
Copyright © 2021 fmnoise
Distributed under the Eclipse Public License 2.0
Can you improve this documentation?Edit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close