-
-
Save ghoseb/267088 to your computer and use it in GitHub Desktop.
Clojure Memoize to Redis
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns redis-memo | |
(:require redis) | |
(:import (java.net URLEncoder))) | |
;; -------------------------------------------------------------------------------- | |
;; Default connection params | |
;; -------------------------------------------------------------------------------- | |
(def memo-server {:host "localhost" :port 6379 :db 14}) | |
;; -------------------------------------------------------------------------------- | |
;; Helpers | |
;; -------------------------------------------------------------------------------- | |
(defn- encode-value | |
"Encode an object so that it is safe to pass to Redis, which complains about key | |
strings containing spaces etc. (redis-clojure doesn't escape keys)" | |
[value] | |
(pr-str value)) | |
(defn- decode-value [value] | |
(with-in-str value (read))) | |
(defn- encode-key | |
"Encode an object so that it is safe to use as a Redis key, | |
avoiding invalid command strings containing spaces." | |
[key] | |
(URLEncoder/encode (encode-value key))) | |
;; -------------------------------------------------------------------------------- | |
;; Public API | |
;; -------------------------------------------------------------------------------- | |
(defmacro with-memo-server | |
"Executes forms with a redis connection to memo-server." | |
[& forms] | |
`(redis/with-server memo-server ~@forms)) | |
(defn memoize-with-redis | |
"Returns a memoized version of a referentially transparent function. The | |
memoized version of the function uses Redis to keep a cache of the | |
mapping from arguments to results. | |
Unlike clojure.core/memoize, this explicitly shortcuts calling the oroginal | |
function when a nil result has previously been memoized." | |
[keyprefix f] | |
(fn [& args] | |
(with-memo-server | |
(let [k (encode-key (cons keyprefix args))] | |
(if-let [v (redis/get k)] | |
(decode-value v) | |
(let [ret (apply f args)] | |
(redis/set k (encode-value ret)) | |
ret)))))) | |
(defmacro defn-redis-memo | |
"Just like defn, but memoizes the function using memoize-with-redis" | |
[fn-name & defn-stuff] | |
`(do | |
(defn ~fn-name ~@defn-stuff) | |
(alter-var-root (var ~fn-name) (partial memoize-with-redis (str (var ~fn-name)))) | |
(var ~fn-name))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment