Skip to content

Instantly share code, notes, and snippets.

View krukow's full-sized avatar

Karl Krukow krukow

View GitHub Profile
(ns org.higher-order.integration.circuit-breaker.states
(:gen-class))
(deftype TransitionPolicy [fail-count timeout])
(defprotocol CircuitBreakerTransitions
"Transition functions for circuit-breaker states"
(proceed [s] "true if breaker should proceed with call in this state")
(on-success [s] "transition from s to this state after a successful call")
(on-error [s] "transition from s to this state after an unsuccessful call")
(comment
"Implementation of Michael Nygaard's Circuit breaker stability pattern.
A circuit breaker acts as an intemediary between a caller and a callee.
Typically the callee is an interface to an integration point, and
the caller is a client of that integration point.
If the circuit breaker detects a number of failures in the callee it
'trips' (i.e., transitions to the open state) and prevents further
calls to the callee for a fixed period (fail fast).
(deftype TransitionPolicy [fail-count timeout])
(defprotocol CircuitBreakerTransitions
"Transition functions for circuit-breaker states"
(proceed [s] "true if breaker should proceed with call in this state")
(on-success [s] "transition from s to this state after a successful call")
(on-error [s] "transition from s to this state after an unsuccessful call")
(on-before-call [s] "transition from s to this state before a call"))
(deftype ClosedState [policy fail-count] [clojure.lang.IPersistentMap])
(defn- to-closed-state-from [s] (ClosedState (:policy s) 0))
(extend
::ClosedState CircuitBreakerTransitions
(merge abs-transitions
{:proceed (constantly true)
:on-success (fn [s] (if (zero? (:fail-count s)) s (to-closed-state-from s)))
:on-error (fn [s]
(let [p (:policy s)
f (:fail-count s)]
(ns org.higher-order.integration.circuit-breaker.atomic
(:use org.higher-order.integration.circuit-breaker.states)
(:gen-class))
(def default-policy (TransitionPolicy 5 5000))
(def initial-state (ClosedState default-policy 0))
(def state (atom initial-state))
(def transition-by!)
(comment test
(def #^{:private true}s (wrap (constantly 42)))
(def #^{:private true}f (wrap (fn [_] (assert nil))))
(dotimes [i 10]
(s))
(assert (= (ClosedState default-policy 0) @state))
(ns net.higher-order.integration.circuit-breaker.states)
(deftype TransitionPolicy [fail-count timeout])
(defprotocol CircuitBreakerTransitions
"Transition functions for circuit-breaker states"
(proceed [s] "true if breaker should proceed with call in this state")
(on-success [s] "transition from s to this state after a successful call")
(on-error [s] "transition from s to this state after an unsuccessful call")
(on-before-call [s] "transition from s to this state before a call"))
(extend
::ClosedState CircuitBreakerTransitions
(merge abs-transitions
{:proceed (constantly true)
:on-success (fn [s] (if (zero? (:fail-count s)) s (to-closed-state-from s)))
:on-error (fn [s]
(let [p (:policy s)
f (:fail-count s)]
(if (= f (:fail-count p))
(OpenState p (System/currentTimeMillis))
(ns net.higher-order.integration.circuit-breaker.atomic
(:use net.higher-order.integration.circuit-breaker.states))
(def default-policy (TransitionPolicy 5 5000))
(def initial-state (ClosedState default-policy 0))
(defn make-circuit-breaker
([] (atom initial-state))
([s] (atom s)))
(let [[sf st] (wrap (constantly 42))]
(def #^{:private true}s sf)
(def #^{:private true}f (wrap-with (fn [] (throw (Exception.))) st))
(def state st))
(dotimes [i 10]
(s))
(assert (= (ClosedState default-policy 0) @state))