I wrap functions
I wrap them before
I wrap them after
I wrap them around
love
love is all you need
docs are TBD
experimenting with an AOP style caching:
let's create a database and db functions:
$ make repl
=>
(defn take-time [seconds]
(println "taking" seconds "seconds")
(Thread/sleep (* seconds 1000)))
(def db (atom {:mars {:nick "the red planet"
:age "4.603 billion years"
:mass "639000000000000000000000"}
:earth {:nick "the blue planet"
:age "4.543 billion years"
:mass "5974000000000000000000000"}}))
(defn find-planet [db {:keys [planet]}]
(take-time 3)
(@db planet))
(defn add-planet [db {:keys [planet intel]}]
(swap! db assoc planet intel))
(defn remove-planet [db {:keys [planet]}]
(swap! db dissoc planet))
;; #'dev/take-time
;; #'dev/db
;; #'dev/find-planet
;; #'dev/add-planet
;; #'dev/remove-planet
now let's wrap all these functions in cache
in this case redis:
=> (require '[obiwan.core :as redis]
'[wrap.core :as w]
'[wrap.cache.redis :as wc])
=> (def conn (redis/create-pool))
;; read through cache
=> (wc/cache conn "planets" #{#'dev/find-planet})
;; evict when removing the planet
=> (wc/evict conn "planets" #{#'dev/remove-planet})
;; put in cache when adding a planet
=> (wc/put conn "planets" #{#'dev/add-planet})
wrap follows calip so a set of functions in one or more namespaces
or a star search of functions to apply wrappers to will work the same
internally, these wrappers look something like this (you can define your own if these don't fit the need):
(defn cache [conn prefix fs]
(w/wrap fs
(c/cache (partial lookup conn prefix)
(partial store conn prefix))))
(defn evict [conn prefix fs]
(w/wrap fs
(c/evict (partial delete conn prefix))))
(defn put [conn prefix fs]
(w/wrap fs
(c/put (partial store conn prefix))))
now let's see wrappers in action:
=> (find-planet db {:planet :earth})
;; taking 3 seconds
;; {:nick "the blue planet", :age "4.543 billion years", :mass "5974000000000000000000000"}
took some time since we "went" to the database for this search
but once we did that, now it is cached:
=> (find-planet db {:planet :earth})
;; {:nick "the blue planet", :age "4.543 billion years", :mass "5974000000000000000000000"}
once we remove the planet, the cache entry for it is going to be evicted:
=> (remove-planet db {:planet :earth})
=> (find-planet db {:planet :earth})
;; taking 3 seconds
;; nil
now let's try to add pluto:
=> (find-planet db {:planet :pluto})
;; taking 3 seconds
;; nil
=> (add-planet db {:planet :pluto
:intel {:nick "tombaugh regio"
:age "4.5 billion years"
:mass "13090000000000000000000"}})
it is cached right away:
=> (find-planet db {:planet :pluto})
;; {:nick "tombaugh regio", :age "4.5 billion years", :mass "13090000000000000000000"}
functions can be also unwrapped (wrappers will be stripped):
=> (w/unwrap #{#'dev/find-planet})
=> (find-planet db {:planet :pluto})
;; taking 3 seconds
;; {:nick "tombaugh regio", :age "4.5 billion years", :mass "13090000000000000000000"}
this lib is not exactly for general use since it does have deps:
plus it "assumes things"
feel free to either use as is, or to steal code from it should you find it useful
Copyright © 2021 tolitius
Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.
Can you improve this documentation?Edit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close