|
34 | 34 | ((http/wrap-exceptions (constantly resp)) req)) |
35 | 35 | resp)) |
36 | 36 |
|
37 | | -(def ^:private ^:const hystrix-defaults |
| 37 | +(def ^:private ^:const hystrix-base-configuration |
38 | 38 | {:hystrix/command-key :default |
39 | 39 | :hystrix/fallback-fn default-fallback |
40 | 40 | :hystrix/group-key :default |
|
47 | 47 | :hystrix/bad-request-pred client-error?}) |
48 | 48 |
|
49 | 49 | (def ^:private hystrix-keys |
50 | | - (keys hystrix-defaults)) |
| 50 | + (keys hystrix-base-configuration)) |
| 51 | + |
| 52 | +(defn ^:private hystrix-defaults [defaults] |
| 53 | + (merge hystrix-base-configuration (select-keys defaults hystrix-keys))) |
51 | 54 |
|
52 | 55 | (defn ^:private group-key [s] |
53 | 56 | (HystrixCommandGroupKey$Factory/asKey (name s))) |
|
96 | 99 | (fn [req resp] |
97 | 100 | (contains? status-codes (:status resp))))) |
98 | 101 |
|
99 | | -(defn wrap-hystrix |
100 | | - "Wrap a clj-http client request with hystrix features (but only if a |
101 | | - command-key is present in the options map)." |
102 | | - [f req] |
103 | | - (if (not-empty (select-keys req hystrix-keys)) |
104 | | - (let [req (merge hystrix-defaults req) |
105 | | - bad-request-pred (:hystrix/bad-request-pred req) |
106 | | - fallback (:hystrix/fallback-fn req) |
107 | | - wrap-bad-request (fn [resp] (if (bad-request-pred req resp) |
108 | | - (throw (HystrixBadRequestException. "Ignored bad request" |
109 | | - (wrap {:object resp |
110 | | - :message "Bad request pred" |
111 | | - :stack-trace (stack-trace)}))) |
112 | | - resp)) |
113 | | - wrap-exception-response (fn [resp] ((http/wrap-exceptions (constantly resp)) (assoc req :throw-exceptions true))) |
114 | | - configurator (configurator req) |
115 | | - logging-context (or (MDC/getCopyOfContextMap) {}) |
116 | | - command (proxy [HystrixCommand] [configurator] |
117 | | - (getFallback [] |
118 | | - (MDC/setContextMap logging-context) |
119 | | - (log-error (:hystrix/command-key req) this) |
120 | | - (let [exception (.getFailedExecutionException ^HystrixCommand this) |
121 | | - response (when exception (get-thrown-object exception))] |
122 | | - (fallback req response))) |
123 | | - (run [] |
124 | | - (MDC/setContextMap logging-context) |
125 | | - (-> req |
126 | | - (assoc :throw-exceptions false) |
127 | | - f |
128 | | - wrap-bad-request |
129 | | - wrap-exception-response)))] |
130 | | - (handle-exception #(.execute command) req)) |
131 | | - (f req))) |
| 102 | +(defn hystrix-wrapper |
| 103 | + "Create a function that wraps clj-http client requests with hystrix features |
| 104 | + (but only if a hystrix key is present in the options map). |
| 105 | + Accepts a possibly empty map of default hystrix values that will be used as |
| 106 | + fallback configuration for each hystrix request." |
| 107 | + [custom-defaults] |
| 108 | + (let [defaults (hystrix-defaults custom-defaults)] |
| 109 | + (fn [f req] |
| 110 | + (if (not-empty (select-keys req hystrix-keys)) |
| 111 | + (let [req (merge defaults req) |
| 112 | + bad-request-pred (:hystrix/bad-request-pred req) |
| 113 | + fallback (:hystrix/fallback-fn req) |
| 114 | + wrap-bad-request (fn [resp] (if (bad-request-pred req resp) |
| 115 | + (throw |
| 116 | + (HystrixBadRequestException. |
| 117 | + "Ignored bad request" |
| 118 | + (wrap {:object resp |
| 119 | + :message "Bad request pred" |
| 120 | + :stack-trace (stack-trace)}))) |
| 121 | + resp)) |
| 122 | + wrap-exception-response (fn [resp] |
| 123 | + ((http/wrap-exceptions (constantly resp)) |
| 124 | + (assoc req :throw-exceptions true))) |
| 125 | + configurator (configurator req) |
| 126 | + logging-context (or (MDC/getCopyOfContextMap) {}) |
| 127 | + command (proxy [HystrixCommand] [configurator] |
| 128 | + (getFallback [] |
| 129 | + (MDC/setContextMap logging-context) |
| 130 | + (log-error (:hystrix/command-key req) this) |
| 131 | + (let [exception (.getFailedExecutionException ^HystrixCommand this) |
| 132 | + response (when exception (get-thrown-object exception))] |
| 133 | + (fallback req response))) |
| 134 | + (run [] |
| 135 | + (MDC/setContextMap logging-context) |
| 136 | + (-> req |
| 137 | + (assoc :throw-exceptions false) |
| 138 | + f |
| 139 | + wrap-bad-request |
| 140 | + wrap-exception-response)))] |
| 141 | + (handle-exception #(.execute command) req)) |
| 142 | + (f req))))) |
132 | 143 |
|
133 | 144 | (defn add-hook |
134 | 145 | "Activate clj-http-hystrix to wrap all clj-http client requests as |
135 | | - hystrix commands." |
| 146 | + hystrix commands. |
| 147 | + Provide custom hystrix defaults by providing an optional defaults map: |
| 148 | +
|
| 149 | + ;; use clj-http-hystrix.core default configuration |
| 150 | + (add-hook) |
| 151 | +
|
| 152 | + ;; 6 second timeout fallback, if not specified in request |
| 153 | + (add-hook {:hystrix/timeout-ms 6000}) |
| 154 | + " |
| 155 | + ([] (add-hook {})) |
| 156 | + ([defaults] |
| 157 | + (hooke/add-hook #'http/request ::wrap-hystrix (hystrix-wrapper defaults)))) |
| 158 | + |
| 159 | +(defn remove-hook |
| 160 | + "Deactivate clj-http-hystrix." |
136 | 161 | [] |
137 | | - (hooke/add-hook #'http/request #'wrap-hystrix)) |
| 162 | + (hooke/remove-hook #'http/request ::wrap-hystrix)) |
0 commit comments