java 60 lines · 7 steps

How a circuit breaker guards failing calls

A three-state machine that stops hammering a failing dependency and probes for recovery before letting traffic back through.

Explained by highlit
1public final class CircuitBreaker {
2 
3 private enum State { CLOSED, OPEN, HALF_OPEN }
4 
5 private final int failureThreshold;
6 private final int successThreshold;
7 private final long openDurationMillis;
8 
9 private volatile State state = State.CLOSED;
10 private final AtomicInteger failureCount = new AtomicInteger();
11 private final AtomicInteger successCount = new AtomicInteger();
12 private volatile long openedAt = 0L;
13 
14 public CircuitBreaker(int failureThreshold, int successThreshold, Duration openDuration) {
15 this.failureThreshold = failureThreshold;
16 this.successThreshold = successThreshold;
17 this.openDurationMillis = openDuration.toMillis();
18 }
19 
20 public <T> T execute(Supplier<T> action) throws Exception {
21 if (state == State.OPEN) {
22 if (System.currentTimeMillis() - openedAt < openDurationMillis) {
23 throw new CircuitOpenException("circuit is open");
24 }
25 transitionTo(State.HALF_OPEN);
26 }
27 
28 try {
29 T result = action.get();
30 onSuccess();
31 return result;
32 } catch (RuntimeException ex) {
33 onFailure();
34 throw ex;
35 }
36 }
37 
38 private synchronized void onSuccess() {
39 if (state == State.HALF_OPEN) {
40 if (successCount.incrementAndGet() >= successThreshold) {
41 transitionTo(State.CLOSED);
42 }
43 } else {
44 failureCount.set(0);
45 }
46 }
47 
48 private synchronized void onFailure() {
49 if (state == State.HALF_OPEN || failureCount.incrementAndGet() >= failureThreshold) {
50 openedAt = System.currentTimeMillis();
51 transitionTo(State.OPEN);
52 }
53 }
54 
55 private void transitionTo(State next) {
56 state = next;
57 failureCount.set(0);
58 successCount.set(0);
59 }
60}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1A circuit breaker trades occasional fast failures for protecting a struggling dependency from a flood of doomed requests.
  2. 2The HALF_OPEN state lets exactly a probe of traffic through so recovery is detected without fully reopening the floodgates.
  3. 3Marking mutable state volatile and confining transitions to synchronized methods keeps the machine consistent under concurrent calls.

Related explainers

Share this explainer

Here's the card — post it anywhere.

How a circuit breaker guards failing calls — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code