Controlling the breaker
Fuse::run() is the normal path. breaker() is how you look at the circuit and how you override it.
$fuse = Fuse::for('billing-sdk', $store);
$breaker = $fuse->breaker();
Read the circuit
| Method | Returns |
|---|---|
name() |
The name you passed to Fuse::for(), such as billing-sdk |
storageKey() |
The full key, such as fuse:punt:billing:charge |
state() |
CircuitState::Closed, Open, or HalfOpen |
allowRequest() |
Whether the next call may run. Also moves an open circuit to half-open when the cooldown is over, and reserves a probe slot |
state() reads the snapshot. It does not change it. allowRequest() can change it: when the open duration has elapsed, the call that checks is the one that becomes the probe.
use Milon\Fuse\CircuitState;
if ($fuse->breaker()->state() === CircuitState::Open) {
return $this->fallback();
}
Prefer catching CircuitOpenException from run(). Checking state() and then calling run() races with other processes, and run() already does the check.
Open it for a dependency you know is down
$fuse->breaker()->forceOpen();
This writes an open snapshot with opened_at set to now and clears probe counters. Calls are rejected until open_seconds have passed. The next call after that is a half-open probe, the same as a circuit that opened because of failures.
One forceOpen() does not pin the circuit open forever. To cover a maintenance window longer than open_seconds, call forceOpen() again before the cooldown ends, or set open_seconds high on that breaker.
Close it, or wipe it
$fuse->breaker()->forceClosed();
The circuit is closed and the failure list is empty. The next call runs.
$fuse->breaker()->reset();
This deletes the snapshot from the store. The next read is the same as a circuit that was never written: closed, with no failures. forceClosed() leaves a closed snapshot in the store. reset() leaves nothing.
Record an outcome yourself
You only need these if you are not using run() or the Saloon trait.
| Method | Effect |
|---|---|
recordSuccess() |
While closed, clears failures. While half-open, counts a successful probe and closes the circuit when enough have passed. |
recordFailure() |
Adds a counted failure. Opens the circuit at the threshold, or immediately if it was half-open. |
releaseProbe() |
While half-open, frees one in-flight probe slot and does not change the success count. While closed or open, does nothing. |
run() calls these for you. The Saloon middleware calls them for you. Calling them as well as run() would count the same attempt twice.
A clock you control
Tests that need the window or the cooldown to pass should not sleep(). Pass a clock:
use Milon\Fuse\Clock;
use Milon\Fuse\Fuse;
$clock = new class implements Clock {
public int $now = 1_700_000_000;
public function now(): int
{
return $this->now;
}
};
$fuse = Fuse::for('billing-sdk', $store, clock: $clock);
$clock->now += 60;
now() is a unix timestamp in seconds. The production default is SystemClock.