Circuit Breaker Pattern
A SCION example of the circuit breaker resilience pattern.
This example models the circuit breaker resilience pattern. The statechart keeps calls flowing while closed, fails fast while open, and uses a half-open probe to decide whether the dependency has recovered.
Circuit state
closed
Requests flow normally.
Failures
0 / 3
Last result
none
SCXML source
<scxml datamodel="ecmascript"
initial="closed"
name="CircuitBreaker"
version="1.0"
xmlns="http://www.w3.org/2005/07/scxml">
<datamodel>
<data id="failureCount" expr="0"/>
<data id="failureThreshold" expr="3"/>
<data id="lastResult" expr="'none'"/>
</datamodel>
<state id="closed">
<onentry>
<send event="trace">
<content expr="'Circuit is closed: requests flow to the dependency.'"/>
</send>
</onentry>
<transition event="call.success">
<assign location="failureCount" expr="0"/>
<assign location="lastResult" expr="'success'"/>
<send event="trace">
<content expr="'Call succeeded; failure count reset.'"/>
</send>
</transition>
<transition event="call.failure" cond="failureCount + 1 >= failureThreshold" target="open">
<assign location="failureCount" expr="failureCount + 1"/>
<assign location="lastResult" expr="'failure'"/>
<send event="trace">
<content expr="'Failure threshold reached; opening circuit.'"/>
</send>
</transition>
<transition event="call.failure">
<assign location="failureCount" expr="failureCount + 1"/>
<assign location="lastResult" expr="'failure'"/>
<send event="trace">
<content expr="'Call failed; failure count increased.'"/>
</send>
</transition>
</state>
<state id="open">
<onentry>
<send event="trace">
<content expr="'Circuit is open: calls fail fast.'"/>
</send>
<send event="cooldown.elapsed" delay="3000ms" id="cooldown"/>
</onentry>
<onexit>
<cancel sendid="cooldown"/>
</onexit>
<transition event="cooldown.elapsed" target="halfOpen"/>
<transition event="reset" target="closed">
<assign location="failureCount" expr="0"/>
<assign location="lastResult" expr="'manual reset'"/>
</transition>
</state>
<state id="halfOpen">
<onentry>
<send event="trace">
<content expr="'Circuit is half-open: allow one probe request.'"/>
</send>
</onentry>
<transition event="call.success" target="closed">
<assign location="failureCount" expr="0"/>
<assign location="lastResult" expr="'probe success'"/>
<send event="trace">
<content expr="'Probe succeeded; closing circuit.'"/>
</send>
</transition>
<transition event="call.failure" target="open">
<assign location="failureCount" expr="failureThreshold"/>
<assign location="lastResult" expr="'probe failure'"/>
<send event="trace">
<content expr="'Probe failed; reopening circuit.'"/>
</send>
</transition>
<transition event="reset" target="closed">
<assign location="failureCount" expr="0"/>
<assign location="lastResult" expr="'manual reset'"/>
</transition>
</state>
</scxml>