code wiki / _hdl_build / nx_restart_strategy_gate.nx
nx_restart_strategy_gate.nx source
↩ module page · 81 lines · 5686 B
1// nx_restart_strategy_gate.nx -- MEASURED gate for the S-class supervision restart strategy. Pure/offline. Proves
2// the crash-loop CONTAINMENT the operator wants (vs today's infinite restart): a flapping daemon is QUARANTINED
3// once it exceeds the OTP restart intensity, with exponential-backoff+jitter spacing and correct window aging.
4// T1 within intensity -> RESTART
5// T2 over intensity -> QUARANTINE (contained, not looped)
6// T3 exponential backoff capped -> 100,200,400,800,... -> cap
7// T4 window ages out old crashes -> a now-stable daemon is NOT quarantined for ancient crashes
8// T5 jitter bounded [d/2, d] -> no thundering herd
9// T6 the LIVE crash-loop case -> gallery/vroom-style rapid restarts -> QUARANTINE (the operator's exact bug, contained)
10// GREEN iff 6/6. Appends knowledge/status/restart_strategy_gate.log. license_tier: ORIGINAL
11import "nx_restart_strategy.nx"
12import "nx_syscalls.nx"
13
14func g_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
15func g_num(v: i64) -> i64 {
16 let bb: *u8 = sys_mmap(28); var m: i64 = v; if m < 0 { m = 0 - m; sys_write(1, "-" as *u8, 1) }
17 let t: *u8 = sys_mmap(28); var k: i64 = 0; if m == 0 { t[0] = 48 as u8; k = 1 }
18 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
19 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 } sys_write(1, bb, k); return 0
20}
21func g_w(fd: i64, s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(fd, s, n); return 0 }
22func g_wn(fd: i64, v: i64) -> i64 {
23 let bb: *u8 = sys_mmap(28); var m: i64 = v; if m < 0 { m = 0 - m }
24 let t: *u8 = sys_mmap(28); var k: i64 = 0; if m == 0 { t[0] = 48 as u8; k = 1 }
25 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
26 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 } sys_write(fd, bb, k); return 0
27}
28
29func main() -> i64 {
30 g_puts("=== RESTART STRATEGY GATE (S-class crash-loop containment: OTP intensity + exp backoff + jitter) ===\n" as *u8)
31 let now: i64 = 1000
32 let win: i64 = 5
33 let maxr: i64 = 5
34 var pass: i64 = 0
35
36 // T1: 3 restarts within the 5s window, max 5 -> RESTART
37 let t1a: *i64 = sys_mmap(8 * 8) as *i64; t1a[0] = 997; t1a[1] = 998; t1a[2] = 999
38 var c1: i64 = 0; if rs_should_restart(t1a, 3, now, win, maxr) == RS_RESTART { c1 = 1 } pass = pass + c1
39 g_puts(" T1 within intensity -> RESTART: "); if c1 == 1 { g_puts("PASS\n" as *u8) } else { g_puts("FAIL\n" as *u8) }
40
41 // T2: 6 restarts within the window, max 5 -> QUARANTINE
42 let t2a: *i64 = sys_mmap(8 * 8) as *i64; t2a[0] = 995; t2a[1] = 996; t2a[2] = 997; t2a[3] = 998; t2a[4] = 999; t2a[5] = 1000
43 var c2: i64 = 0; if rs_should_restart(t2a, 6, now, win, maxr) == RS_QUARANTINE { c2 = 1 } pass = pass + c2
44 g_puts(" T2 over intensity -> QUARANTINE: "); if c2 == 1 { g_puts("PASS\n" as *u8) } else { g_puts("FAIL\n" as *u8) }
45
46 // T3: exponential backoff, capped at 30000
47 var c3: i64 = 0
48 if rs_backoff_ms(0, 100, 30000) == 100 { if rs_backoff_ms(1, 100, 30000) == 200 { if rs_backoff_ms(2, 100, 30000) == 400 { if rs_backoff_ms(3, 100, 30000) == 800 { if rs_backoff_ms(20, 100, 30000) == 30000 { c3 = 1 } } } } }
49 pass = pass + c3
50 g_puts(" T3 exp backoff 100,200,400,800..cap(20)=30000: "); if c3 == 1 { g_puts("PASS\n" as *u8) } else { g_puts("FAIL\n" as *u8) }
51
52 // T4: 7 ancient crashes (all ~900s ago, outside the 5s window) -> 0 in-window -> RESTART (not punished for old history)
53 let t4a: *i64 = sys_mmap(8 * 8) as *i64; var z: i64 = 0; while z < 7 { t4a[z] = 100 + z; z = z + 1 }
54 var c4: i64 = 0; if rs_should_restart(t4a, 7, now, win, maxr) == RS_RESTART { c4 = 1 } pass = pass + c4
55 g_puts(" T4 window ages out old crashes -> RESTART: "); if c4 == 1 { g_puts("PASS\n" as *u8) } else { g_puts("FAIL\n" as *u8) }
56
57 // T5: jitter stays within [d/2, d] for several seeds
58 var c5: i64 = 1
59 let d: i64 = 800
60 var s: i64 = 0
61 while s < 20 { let j: i64 = rs_jitter_ms(d, s * 37 + 11); if j < d / 2 { c5 = 0 } if j > d { c5 = 0 } s = s + 1 }
62 pass = pass + c5
63 g_puts(" T5 jitter bounded [d/2,d] (no thundering herd): "); if c5 == 1 { g_puts("PASS\n" as *u8) } else { g_puts("FAIL\n" as *u8) }
64
65 // T6: the LIVE crash-loop (gallery/vroom): 8 rapid restarts in the window -> QUARANTINE (the operator's bug, contained)
66 let t6a: *i64 = sys_mmap(8 * 16) as *i64; var q: i64 = 0; while q < 8 { t6a[q] = 996 + (q % 5); q = q + 1 }
67 var c6: i64 = 0; if rs_should_restart(t6a, 8, now, win, maxr) == RS_QUARANTINE { c6 = 1 } pass = pass + c6
68 g_puts(" T6 live crash-loop -> QUARANTINE (contained): "); if c6 == 1 { g_puts("PASS\n" as *u8) } else { g_puts("FAIL\n" as *u8) }
69
70 g_puts("----\nRESTART-STRATEGY rows=6 pass="); g_num(pass); g_puts("\n" as *u8)
71 let lg: i64 = sys_openat_append("knowledge/status/restart_strategy_gate.log" as *u8, 0x1a4)
72 if lg >= 0 {
73 g_w(lg, "RESTART-STRATEGY within_restart="); g_wn(lg, c1); g_w(lg, " over_quarantine="); g_wn(lg, c2); g_w(lg, " exp_backoff="); g_wn(lg, c3)
74 g_w(lg, " window_aging="); g_wn(lg, c4); g_w(lg, " jitter_bounded="); g_wn(lg, c5); g_w(lg, " crashloop_contained="); g_wn(lg, c6)
75 g_w(lg, " rows=6 pass="); g_wn(lg, pass)
76 if pass == 6 { g_w(lg, " verdict=GREEN\n" as *u8) } else { g_w(lg, " verdict=RED\n" as *u8) }
77 sys_close(lg)
78 }
79 if pass == 6 { g_puts("RESTART-STRATEGY GREEN (crash-loops CONTAINED by OTP intensity + exp backoff + jitter -- measured)\n" as *u8); sys_exit(0); return 0 }
80 g_puts("RESTART-STRATEGY RED\n" as *u8); sys_exit(1); return 1
81}