/
circuit_breaker.clj
69 lines (55 loc) · 2.27 KB
/
circuit_breaker.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
(ns diehard.circuit-breaker
(:require [diehard.util :as u])
(:import [java.time Duration]
[java.time.temporal ChronoUnit]
[net.jodah.failsafe CircuitBreaker]))
(def ^{:const true :no-doc true}
allowed-circuit-breaker-option-keys
#{:failure-threshold :failure-threshold-ratio
:success-threshold :success-threshold-ratio
:delay-ms :timeout-ms
:fail-if :fail-on :fail-when
:on-open :on-close :on-half-open})
(defn circuit-breaker [opts]
(u/verify-opt-map-keys-with-spec :circuit-breaker/circuit-breaker opts)
(let [cb (CircuitBreaker.)]
(when (contains? opts :fail-on)
(.handle cb (u/predicate-or-value (:fail-on opts))))
(when (contains? opts :fail-if)
(.handleIf cb (u/bipredicate (:fail-if opts))))
(when (contains? opts :fail-when)
(.handleResult cb (:fail-when opts)))
(when-let [timeout (:timeout-ms opts)]
(.withTimeout cb timeout ChronoUnit/MILLIS))
(when-let [delay (:delay-ms opts)]
(.withDelay cb (Duration/ofMillis delay)))
(when-let [failure-threshold (:failure-threshold opts)]
(.withFailureThreshold cb failure-threshold))
(when-let [[failures executions] (:failure-threshold-ratio opts)]
(.withFailureThreshold cb failures executions))
(when-let [success-threshold (:success-threshold opts)]
(.withSuccessThreshold cb success-threshold))
(when-let [[successes executions] (:success-threshold-ratio opts)]
(.withSuccessThreshold cb successes executions))
(when-let [on-open (:on-open opts)]
(.onOpen cb (u/fn-as-runnable on-open)))
(when-let [on-half-open (:on-half-open opts)]
(.onHalfOpen cb (u/fn-as-runnable on-half-open)))
(when-let [on-close (:on-close opts)]
(.onClose cb (u/fn-as-runnable on-close)))
cb))
(defn state
"Get current state of this circuit breaker, values in `:open`, `:closed` and `half-open` "
[^CircuitBreaker cb]
(cond
(.isOpen cb) :open
(.isClosed cb) :closed
:else :half-open))
(defn allow-execution?
"Test if this circuit breaker allow code execution. The result is based
on current state:
* `:open` will deny all execution requests
* `:close` allows all executions
* `:half-open` only allows some of execution requests"
[^CircuitBreaker cb]
(.allowsExecution cb))