code wiki / _hdl_build / nx_apistack_breaker.nx
nx_apistack_breaker.nx source
↩ module page · 34 lines · 1545 B
1// nx_apistack_breaker.nx -- CAP-API-BREAKER: per-dependency circuit-breaker for /api downstream calls. Pure state
2// machine CLOSED -> (threshold failures) OPEN -> (cooldown) HALF-OPEN -> (probe) CLOSED|OPEN. When OPEN it fails fast
3// (no wasted calls to a dead dependency); one probe in HALF-OPEN decides recovery. Pure integer logic, gateable
4// offline = the sovereign exceed over a library breaker (no framework, deterministic). Caller holds per-dependency
5// state cb[0]=status cb[1]=fail_count cb[2]=open_since. license_tier: ORIGINAL
6import "nx_syscalls.nx"
7
8const CB_CLOSED: i64 = 0
9const CB_OPEN: i64 = 1
10const CB_HALF: i64 = 2
11
12// may the call proceed? CLOSED=yes; OPEN=no until cooldown elapses (then transition to HALF and allow ONE probe); HALF=yes.
13func cb_allow(cb: *i64, now: i64, cooldown: i64) -> i64 {
14 if cb[0] == CB_CLOSED { return 1 }
15 if cb[0] == CB_OPEN {
16 if now - cb[2] >= cooldown { cb[0] = CB_HALF; return 1 }
17 return 0
18 }
19 return 1 // HALF -> allow the probe
20}
21
22// record the outcome. success resets (HALF->CLOSED = recovered); failure increments (>=threshold => OPEN), and a
23// failure while HALF re-opens immediately.
24func cb_record(cb: *i64, success: i64, threshold: i64, now: i64) -> i64 {
25 if success == 1 {
26 if cb[0] == CB_HALF { cb[0] = CB_CLOSED }
27 cb[1] = 0
28 return cb[0]
29 }
30 if cb[0] == CB_HALF { cb[0] = CB_OPEN; cb[2] = now; return cb[0] }
31 cb[1] = cb[1] + 1
32 if cb[1] >= threshold { cb[0] = CB_OPEN; cb[2] = now }
33 return cb[0]
34}