A simple Redis client wrapping Carmine
It's not meant to be a fancy DSL or an ORM. Just helps with componentizing the connection
and invoking Redis commands in more idiomatic way, without using macros, like the wcar*
macro in Carmine's readme.
The idea is that the component wraps the conection, and you pass "raw" Redis commands, like in the Redis shell or CLI, rather than invoking Carmine command functions + their arguments. The way it works is that we convert the first keyword (command) to a Carmine function, cache it and then invoke it. The lookup/conversion is cached for later so that we don't pay the cost of the lookup too often.
If you want to mock the component - you'll need something that implements the following protocol (defined as omega-red.protocol.Redis
):
(execute this [:command + args])
- for single commands(exececute-pipeline this [ [:command1 + args] [:command2 + args]...])
- for pipeline operationsand fakes Redis behavior as needed.
Omega Red also supports a very simple "fetch from cache or populate on miss" workflow - it's not complicated but nicely DRYs up your code. See example below
(ns omega-red.redis-test
(:require [omega-red.protocol :as redis]
[omega-red.redis]
[com.stuartsierra.component :as component]))
(let [conn (componet/start (omega-red.redis/create {:host "127.0.0.1" :port 6379}))]
(is (= 0 (redis/execute conn [:exists "test.some.key"]))) ; true
(is (= "OK" (redis/execute conn [:set "test.some.key" "foo"]))) ; true
(is (= 1 (redis/execute conn [:exists "test.some.key"]))) ; true
(is (= "foo" (redis/execute conn [:get "test.some.key"]))) ; true
(is (= 1 (redis/execute conn [:del "test.some.key"]))) ; true
(component/stop red)
(is (nil? (redis/execute conn [:get "test.some.key"])))) ; true
;; pipeline execution
(is (= [nil "OK" "oh ok" 1]
(redis/execute-pipeline conn
[[:get "test.some.key.pipe"]
[:set "test.some.key.pipe" "oh ok"]
[:get "test.some.key.pipe"]
[:del "test.some.key.pipe"]]))) ; true
;; caching example
(let [fetch! (fn []
(redis/cache-get-or-fetch {:fetch (fn [] (slurp "http://example.com"))
:cache-set (fn [fetch-res]
(redis/execute conn [:setex "example" 10 fetch-res]))
:cache-get (fn []
(redis/exeucte conn [:get "example"]))}))]
(fetch!) ;; => returns contents of http://example.com as a result of direct call
(fetch!) ;; => pulls from cache
(fetch!) ;; => pulls from cache
(Thread/sleep (* 10 1000))
(fetch!) ;; => makes http request again
)
execute
to accept a vector, and execute-pipeline
to accept a vector of vectors. This makes it easier to work with variadic Redis commands (hmset
etc) and compose commandsIn alphabetical order
Can you improve this documentation?Edit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close