code wiki / _hdl_build / nx_pub_rel_gate.nx
nx_pub_rel_gate.nx source
↩ module page · 66 lines · 5380 B
1// nx_pub_rel_gate.nx -- R16 PROOF: rolling update (halt-on-failure), retention/GC (never-brick), bounded retry.
2//
3// ROLLING -- a 3-instance roll where instance #2's target is unwritable HALTS at #2: instance #1 stays updated,
4// instance #3 is NEVER touched (blast-limited mid-roll halt).
5// RETAIN -- GC removes transient .tmp/.flip leftovers but PRESERVES live + .prev (rollback target) = never-brick.
6// RETRY -- succeeds within the attempt budget AND is bounded (gives up at 0, never an infinite loop).
7// File-based (no forks). license_tier: ORIGINAL expect_exit: 0
8import "nx_syscalls.nx"
9import "nx_publisher.nx"
10import "nx_runpath.nx"
11
12func g_w(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
13func g_n(v: i64) -> i64 { var m: i64=v; if m<0{g_w("-" as *u8);m=0-m} let t:*u8=sys_mmap(24); var k:i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var i:i64=0; let o:*u8=sys_mmap(24); while i<k{o[i]=t[k-1-i];i=i+1} sys_write(1,o,k); return 0 }
14func g_row(id: *u8, ok: i64, pass: *i64) -> i64 { g_w(" " as *u8); g_w(id); g_w(": " as *u8); if ok==1 { g_w("OK\n" as *u8); pass[0]=pass[0]+1 } else { g_w("FAIL\n" as *u8) } return 0 }
15func sv_write(path: *u8, content: *u8) -> i64 { let fd: i64 = sys_openat_wr(path, 0x1a4); if fd<0 { return 0 } var n: i64=0; while content[n]!=(0 as u8){n=n+1} sys_write(fd, content, n); sys_close(fd); return 1 }
16func g_mkdir(D: *u8, name: *u8) -> *u8 { let p: *u8 = sys_mmap(700); pub_join(D, name, p); __syscall(83, p as i64, 493, 0, 0, 0, 0); return p }
17
18func main() -> i64 {
19 let pass: *i64 = sys_mmap(8) as *i64; pass[0]=0
20 g_w("=== NX-PUB-REL GATE (rolling halt-on-failure + retention GC never-brick + bounded retry) ===\n" as *u8)
21 let wsid: *u8 = sys_mmap(64); rp_wsid(wsid); rp_ensure(wsid)
22 let D: *u8 = sys_mmap(512); rp_path(wsid, "prel" as *u8, D); __syscall(83, D as i64, 493, 0, 0, 0, 0)
23 let stg: *u8 = g_mkdir(D, "stgroot" as *u8)
24
25 let src_good: *u8 = sys_mmap(700); pub_join(D, "good.src" as *u8, src_good); sv_write(src_good, "ROLL-GOOD\n" as *u8)
26 let sha_good: *u8 = sys_mmap(72); pub_sha_file(src_good, sha_good)
27
28 // ---- ROLLING: targets [t1, BLOCKER(a FILE -> deploying under it ENOTDIR-fails DETERMINISTICALLY), t3] ----
29 // (a "nonexistent dir" target was fragile/non-idempotent in the shared rp dir; a file-as-parent always fails.)
30 let t1: *u8 = g_mkdir(D, "t1" as *u8)
31 let t3: *u8 = g_mkdir(D, "t3" as *u8)
32 let blocker: *u8 = sys_mmap(700); pub_join(D, "blocker" as *u8, blocker); sv_write(blocker, "x" as *u8) // a FILE, not a dir
33 let t1_f: *u8 = sys_mmap(700); pub_join(t1, "r.html" as *u8, t1_f); __syscall(87, t1_f as i64, 0,0,0,0,0) // clean baseline
34 let t3_f: *u8 = sys_mmap(700); pub_join(t3, "r.html" as *u8, t3_f); __syscall(87, t3_f as i64, 0,0,0,0,0) // ensure absent
35 let tg: *i64 = sys_mmap(64) as *i64; tg[0]=t1 as i64; tg[1]=blocker as i64; tg[2]=t3 as i64
36 let rolled: i64 = pub_rolling(sha_good, src_good, "r.html" as *u8, tg, 3, stg)
37 let t1_ok: i64 = (pub_exists(t1_f)==1) as i64 // instance #1 updated (before the halt)
38 let t3_untouched: i64 = (pub_exists(t3_f)==0) as i64 // instance #3 never touched (after the halt)
39
40 // ---- RETAIN: live + .prev + .tmp + .flip exist -> GC removes transient, preserves live + .prev ----
41 let live: *u8 = sys_mmap(700); pub_join(D, "page.html" as *u8, live); sv_write(live, "LIVE-NOW\n" as *u8)
42 let prev: *u8 = sys_mmap(700); pub_pcat(live, ".prev" as *u8, prev); sv_write(prev, "PREV-ROLLBACK\n" as *u8)
43 let tmp: *u8 = sys_mmap(700); pub_pcat(live, ".tmp" as *u8, tmp); sv_write(tmp, "junk\n" as *u8)
44 let flip: *u8 = sys_mmap(700); pub_pcat(live, ".flip" as *u8, flip); sv_write(flip, "junk\n" as *u8)
45 pub_retain(live)
46 let live_kept: i64 = (pub_exists(live)==1) as i64
47 let prev_kept: i64 = (pub_exists(prev)==1) as i64
48 let tmp_gone: i64 = (pub_exists(tmp)==0) as i64
49 let flip_gone: i64 = (pub_exists(flip)==0) as i64
50
51 // ---- RETRY: succeeds on attempt 3 within budget 5; gives up (0) when threshold unreachable in budget ----
52 let retry_win: i64 = pub_retry(3, 5, 1)
53 let retry_giveup: i64 = pub_retry(10, 5, 1)
54
55 g_w(" rolled=" as *u8); g_n(rolled); g_w(" t1_ok=" as *u8); g_n(t1_ok); g_w(" t3_untouched=" as *u8); g_n(t3_untouched); g_w("\n" as *u8)
56 g_w(" retain: live_kept=" as *u8); g_n(live_kept); g_w(" prev_kept=" as *u8); g_n(prev_kept); g_w(" tmp_gone=" as *u8); g_n(tmp_gone); g_w(" flip_gone=" as *u8); g_n(flip_gone); g_w("\n" as *u8)
57 g_w(" retry: win=" as *u8); g_n(retry_win); g_w(" giveup=" as *u8); g_n(retry_giveup); g_w("\n" as *u8)
58
59 g_row("ROLLING halts at the failing instance (rolled=1): #1 updated, #3 NEVER touched (blast-limited)" as *u8, ((rolled==1) as i64) & t1_ok & t3_untouched, pass)
60 g_row("RETAIN never-brick: transient .tmp/.flip removed, live + .prev PRESERVED" as *u8, live_kept & prev_kept & tmp_gone & flip_gone, pass)
61 g_row("RETRY succeeds within budget (attempt 3) AND is BOUNDED (gives up at 0, no infinite loop)" as *u8, ((retry_win==3) as i64) & ((retry_giveup==0) as i64), pass)
62
63 g_w("NX-PUB-REL rows=3 pass=" as *u8); g_n(pass[0])
64 if pass[0]==3 { g_w(" verdict=GREEN\n" as *u8); sys_exit(0); return 0 }
65 g_w(" verdict=RED\n" as *u8); sys_exit(1); return 1
66}