Skip to content

Commit 3e14f2d

Browse files
authored
Merge pull request #917 from dahlia/fix/issue-916-circuit-breaker-ttl
Expire circuit breaker state
2 parents 2d18272 + 873ba9b commit 3e14f2d

8 files changed

Lines changed: 1175 additions & 11 deletions

File tree

CHANGES.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,19 @@ Version 2.3.2
88

99
To be released.
1010

11+
### @fedify/fedify
12+
13+
- Fixed the outbound delivery circuit breaker retaining per-host state in the
14+
configured key–value store forever when a remote host never recovered.
15+
Circuit breaker state now receives a TTL on writes made with the default
16+
failure policy, custom failure policies can opt in with the new `stateTtl`
17+
option, and stale state written by earlier 2.3 releases is cleared
18+
automatically on CAS-backed stores after upgrade, with another sweep after a
19+
grace window to cover rolling deployments. [[#916], [#917]]
20+
21+
[#916]: https://github.com/fedify-dev/fedify/issues/916
22+
[#917]: https://github.com/fedify-dev/fedify/pull/917
23+
1124

1225
Version 2.3.1
1326
-------------

docs/manual/circuit-breaker.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,36 @@ For multi-worker deployments, use a `KvStore` implementation that supports
154154
Fedify still works without CAS, but it logs a warning because concurrent
155155
workers can race when opening or closing the same host's circuit.
156156

157+
Fedify expires stored circuit state after it is no longer useful. With the
158+
default numeric failure policy, the default `stateTtl` is derived from
159+
`failureWindow`, `recoveryDelay`, and `heldActivityTtl` so failure history,
160+
recovery probes, and held activities all have enough time to complete. If you
161+
provide a custom `failure` callback, Fedify cannot infer how long your policy
162+
needs its timestamp history, so stored state does not expire by default. Set
163+
`stateTtl` explicitly when using a custom policy and you want circuit state to
164+
be cleaned up automatically:
165+
166+
~~~~ typescript
167+
const federation = createFederation<void>({
168+
kv,
169+
queue,
170+
circuitBreaker: {
171+
failure(timestamps) {
172+
return timestamps.length >= 10;
173+
},
174+
stateTtl: { days: 14 },
175+
},
176+
});
177+
~~~~
178+
179+
When upgrading from Fedify 2.3.0 or 2.3.1, Fedify automatically rewrites
180+
legacy circuit state with a TTL only on `KvStore` implementations that support
181+
`cas()`. Stores without CAS, including `@fedify/postgres` and
182+
`@fedify/redis`, apply TTLs to new circuit state but cannot automatically
183+
clean up circuit state that was already written without a TTL. If that old
184+
state matters for your deployment, remove it with a one-off cleanup script or
185+
add a TTL directly in your storage backend.
186+
157187

158188
Observability
159189
-------------
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import type { KvStore } from "./kv.ts";
2+
3+
export function markCircuitBreakerLegacySweepDone(
4+
kv: Pick<KvStore, "set">,
5+
): Promise<void> {
6+
return kv.set([
7+
"_fedify",
8+
"circuit",
9+
"__fedify_meta",
10+
"circuit_breaker_state_ttl_sweep_v1",
11+
], { state: "final" });
12+
}

0 commit comments

Comments
 (0)