Skip to content
13 changes: 13 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,19 @@ Version 2.3.2

To be released.

### @fedify/fedify

- Fixed the outbound delivery circuit breaker retaining per-host state in the
configured key–value store forever when a remote host never recovered.
Circuit breaker state now receives a TTL on writes made with the default
failure policy, custom failure policies can opt in with the new `stateTtl`
option, and stale state written by earlier 2.3 releases is cleared
automatically on CAS-backed stores after upgrade, with another sweep after a
grace window to cover rolling deployments. [[#916], [#917]]

[#916]: https://github.com/fedify-dev/fedify/issues/916
[#917]: https://github.com/fedify-dev/fedify/pull/917


Version 2.3.1
-------------
Expand Down
22 changes: 22 additions & 0 deletions docs/manual/circuit-breaker.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,28 @@ For multi-worker deployments, use a `KvStore` implementation that supports
Fedify still works without CAS, but it logs a warning because concurrent
workers can race when opening or closing the same host's circuit.

Fedify expires stored circuit state after it is no longer useful. With the
default numeric failure policy, the default `stateTtl` is derived from
`failureWindow`, `recoveryDelay`, and `heldActivityTtl` so failure history,
recovery probes, and held activities all have enough time to complete. If you
provide a custom `failure` callback, Fedify cannot infer how long your policy
needs its timestamp history, so stored state does not expire by default. Set
`stateTtl` explicitly when using a custom policy and you want circuit state to
be cleaned up automatically:

~~~~ typescript
const federation = createFederation<void>({
kv,
queue,
circuitBreaker: {
failure(timestamps) {
return timestamps.length >= 10;
},
stateTtl: { days: 14 },
},
});
~~~~


Observability
-------------
Expand Down
12 changes: 12 additions & 0 deletions packages/fedify/src/federation/circuit-breaker-test-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { KvStore } from "./kv.ts";

export function markCircuitBreakerLegacySweepDone(
kv: Pick<KvStore, "set">,
): Promise<void> {
return kv.set([
"_fedify",
"circuit",
"__fedify_meta",
"circuit_breaker_state_ttl_sweep_v1",
], { state: "final" });
}
Loading