Skip to content

Instantly share code, notes, and snippets.

@vedang
Created October 8, 2013 17:13
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vedang/6888076 to your computer and use it in GitHub Desktop.
Save vedang/6888076 to your computer and use it in GitHub Desktop.
A gist to demonstrate how the redis API can be wrapped in Hystrix.
(ns example.hystrix.redis
(:require [com.netflix.hystrix.core :as hystrix]
[taoensso.carmine :as car :refer [wcar]])
(:refer-clojure :exclude [time get set key keys type sync sort eval]))
(def server-spec {:spec {:host "127.0.0.1"
:port 6379}
:pool {:max-active 8}})
(defmacro defhystrix-carmine-wrapper
"Wrap a carmine function inside hystrix"
[rname rfn rmeta]
`(do (println "Generating Hystrix wrapper for " ~rfn)
(hystrix/defcommand ~(symbol rname)
~rmeta
[& args#]
(let [[a1# & an#] args#
spec-a1?# (map? a1#)
rconn# (if spec-a1?# a1# server-spec)
body# (if spec-a1?# an# args#)]
(wcar rconn# (apply ~rfn body#))))))
(defmacro defhystrix-carmine-fns
[]
`(do ~@(map (fn [[k v]]
`(defhystrix-carmine-wrapper
~(name k)
~(var-get v)
{:arglists (quote ~(:arglists (meta v)))
:doc ~(:doc (meta v))}))
(filter (comp :redis-api meta second)
(ns-publics 'taoensso.carmine)))))
;;; Build Hystrix wrappers for Redis functions by running this code:
;;
;; (defhystrix-carmine-fns)
;;
;;; Use any of the Hystrix wrapped redis functions directly:
;;
;; (sadd "test:key" "a" "b")
;; => 2
;;
;; (sadd {:spec {:host "127.0.0.1"
;; :port 6379}}
;; "test:key"
;; "a" "b")
;; => 2
;;
;; This code is essentially useless because it loses all the
;; pipelining and 'clojury' features that `wcar` provides. Instead the
;; macro defined below is a better wrapper for Hystrix.
(defmacro redis
[& [a1 & an :as args]]
(let [spec-a1? (map? a1)
rconn (if spec-a1? a1 server-spec)
body (if spec-a1? an args)]
`(let [run-fn# (fn [] (wcar ~rconn ~@body))
command-map# (hystrix/command {:command-key (str *ns* "/redis-batch")
:group-key (str *ns*)
:run-fn run-fn#})]
(hystrix/execute command-map#))))
;;; Example usage:
;; (redis (car/sadd "vedang.testing" "1" "2" "1" "3" "!")
;; (car/scard "vedang.testing"))
;;
;; OR you could also specify a redis server spec as follows
;;
;; (redis {:spec {:host "192.168.254.111"
;; :port 6379}}
;; (car/sadd "vedang.testing" "1" "2" "1" "3" "!")
;; (car/scard "vedang.testing"))
@helpshift
Copy link

Nice work! 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment