Created
October 8, 2013 17:13
-
-
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.
This file contains 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 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")) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Nice work! 👍