Circuit-breaker state, kept where every replica can see it.
A breaker in one JVM's atom protects that JVM. With N replicas a failing service gets N breakers, each of which has to trip on its own, so it still takes N times the load — and when the window elapses, all N probe at once, which is the stampede the breaker was meant to prevent. Keeping the state in the cache port makes it one breaker.
The cache adapter decides how far that goes: Redis shares it across replicas, the in-memory one does not. That is the same trade the rate limiter makes, and it is a property of the adapter rather than of this namespace.
Circuit-breaker state, kept where every replica can see it. A breaker in one JVM's atom protects that JVM. With N replicas a failing service gets N breakers, each of which has to trip on its own, so it still takes N times the load — and when the window elapses, all N probe at once, which is the stampede the breaker was meant to prevent. Keeping the state in the cache port makes it one breaker. The cache adapter decides how far that goes: Redis shares it across replicas, the in-memory one does not. That is the same trade the rate limiter makes, and it is a property of the adapter rather than of this namespace.
(allow? cache-component config base-url now-ms)Whether to attempt a call to base-url.
Half-open lets exactly one caller through. The probe is a lease taken with
set-if-absent! — atomic in Redis — so N replicas reaching the end of the
window together produce one trial request rather than N. Without it the
recovery is its own thundering herd.
Whether to attempt a call to `base-url`. Half-open lets exactly one caller through. The probe is a lease taken with `set-if-absent!` — atomic in Redis — so N replicas reaching the end of the window together produce one trial request rather than N. Without it the recovery is its own thundering herd.
(open-error cache-component config base-url operation now-ms)The error for a call the breaker declined to make.
The error for a call the breaker declined to make.
(record-failure! cache-component config base-url now-ms)Count a failure, and open the breaker if it is the one that crosses the line.
The count is an atomic increment, not read-modify-write. A shared breaker exists for the case where many callers hit one outage at the same moment, and that is exactly when a read-modify-write loses increments: each reads the same value and writes back the same successor, so a burst of twenty failures advances the counter by one and the breaker never trips.
set-if-absent! on the open marker keeps the moment the first crosser
opened it, rather than every subsequent failure pushing the window forward.
Count a failure, and open the breaker if it is the one that crosses the line. The count is an atomic increment, not read-modify-write. A shared breaker exists for the case where many callers hit one outage at the same moment, and that is exactly when a read-modify-write loses increments: each reads the same value and writes back the same successor, so a burst of twenty failures advances the counter by one and the breaker never trips. `set-if-absent!` on the open marker keeps the moment the *first* crosser opened it, rather than every subsequent failure pushing the window forward.
(record-success! cache-component base-url)Close the breaker: the service answered.
Close the breaker: the service answered.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |