nx_deploy_leash.nx source
↩ module page · 270 lines · 10774 B
1// nx_deploy_leash.nx -- DEPLOYMENTS ON A LEASH (operator 2026-07-16: "owners take accountability...
2// models loaded into resources and the owner walks away... someone should have our deployments on a
3// leash, not just let them wander loose -- part of the RACI"). Every long-lived deployment (model
4// seat, serve daemon, heavy holder) REGISTERS: accountable owner + purpose + pid + renewal TTL + its
5// own STOP-PATH (a declared graceful kill-switch -- reclaim is never a blind kill). The leash is
6// RENEWAL-BASED liveness of the OWNER'S USE (nx_watch beats on every use), NOT process liveness --
7// a seat daemon stays alive forever, so pid-checks can never catch walk-away. SOTA norm this matches:
8// K8s lease renewal / SLURM walltime / Ray actor liveness -- resources held AGAINST RENEWAL.
9// register <name> <owner> <purpose> <pid> <renew_ttl_ms> <stop_path> (also starts the leash clock)
10// beat = nx_watch beat leash <name> (consumers beat on every USE; no new plumbing)
11// walk supervisor's rounds: HEALTHY / ABANDONED(alive+stale-beat -> touch stop_path, mark
12// RECLAIMED) / DEAD(pid gone). Exit = worst seen (0 none/healthy, 2 dead, 3 abandoned).
13// status same scan, print-only (no reclaim actions).
14// Store: knowledge/store/leash key d:<name> = "name|owner|purpose|pid|ttl_ms|stop_path|reg_us"
15// (latest-wins), d:ids index under flock. Beat clock: knowledge/store/watch_leash via nx_watch.
16// RACI: supervisor R (walks the leash) · pm A (owns the box) · conductor C · every workstream I.
17// license_tier: ORIGINAL
18import "nx_watch.nx"
19import "nx_model_lane_core.nx"
20const DL_MAGIC_262144: i64 = 262144
21const DL_MAGIC_262143: i64 = 262143
22const DL_MAGIC_999999999: i64 = 999999999
23
24const DL_STORE: *u8 = "knowledge/store/leash"
25const DL_LOCK: *u8 = "knowledge/status/leash.lock"
26const DL_HEALTHY: i64 = 0
27const DL_DEAD: i64 = 2
28const DL_ABANDONED: i64 = 3
29
30// PURE leash verdict: dead pid trumps; else stale beat = abandoned; else healthy. gate-core.
31func dl_verdict(pid_alive: i64, beat_age_ms: i64, renew_ttl_ms: i64) -> i64 {
32 if pid_alive == 0 { return DL_DEAD }
33 if beat_age_ms > renew_ttl_ms { return DL_ABANDONED }
34 return DL_HEALTHY
35}
36
37// "d:<name>" key (NUL-term).
38func dl_key(name: *u8, out: *u8) -> i64 {
39 out[0] = 100 as u8
40 out[1] = 58 as u8
41 var i: i64 = 0
42 while name[i] != (0 as u8) { out[2 + i] = name[i]; i = i + 1 }
43 out[2 + i] = 0 as u8
44 return 2 + i
45}
46
47// ensure name in d:ids under flock (same proven pattern as the swarm queue index).
48func dl_add_id(name: *u8) -> i64 {
49 let lf: i64 = sys_openat_append(DL_LOCK, 0x1a4)
50 if lf >= 0 { sys_flock(lf, SYS_LOCK_EX) }
51 let ids: *u8 = sys_mmap(DL_MAGIC_262144) as *u8
52 let idn: i64 = sov_get_copy(DL_STORE, "d:ids" as *u8, ids, DL_MAGIC_262143)
53 var nl: i64 = 0
54 while name[nl] != (0 as u8) { nl = nl + 1 }
55 var have: i64 = 0
56 if idn > 0 {
57 var i: i64 = 0
58 while i < idn {
59 var e: i64 = i
60 var sc: i64 = 1
61 while sc == 1 {
62 if e >= idn { sc = 0 }
63 if sc == 1 { if ids[e] == (10 as u8) { sc = 0 } else { e = e + 1 } }
64 }
65 if e - i == nl {
66 var m: i64 = 0
67 var eq: i64 = 1
68 while m < nl { if ids[i + m] != name[m] { eq = 0; m = nl } else { m = m + 1 } }
69 if eq == 1 { have = 1 }
70 }
71 i = e + 1
72 }
73 }
74 if have == 0 {
75 var o: i64 = idn
76 if o < 0 { o = 0 }
77 var m: i64 = 0
78 while m < nl { ids[o] = name[m]; o = o + 1; m = m + 1 }
79 ids[o] = 10 as u8
80 o = o + 1
81 sov_put(DL_STORE, "d:ids" as *u8, ids, o)
82 }
83 if lf >= 0 { sys_flock(lf, SYS_LOCK_UN); sys_close(lf) }
84 return 0
85}
86
87// row = "name|owner|purpose|pid|ttl_ms|stop_path|reg_us"
88func dl_register(name: *u8, owner: *u8, purpose: *u8, pid: i64, ttl_ms: i64, stop_path: *u8) -> i64 {
89 let row: *u8 = sys_mmap(512) as *u8
90 var o: i64 = 0
91 var i: i64 = 0
92 while name[i] != (0 as u8) { row[o] = name[i]; o = o + 1; i = i + 1 }
93 row[o] = 124 as u8; o = o + 1
94 i = 0
95 while owner[i] != (0 as u8) { row[o] = owner[i]; o = o + 1; i = i + 1 }
96 row[o] = 124 as u8; o = o + 1
97 i = 0
98 while purpose[i] != (0 as u8) { row[o] = purpose[i]; o = o + 1; i = i + 1 }
99 row[o] = 124 as u8; o = o + 1
100 o = o + std_itoa(pid, row + o)
101 row[o] = 124 as u8; o = o + 1
102 o = o + std_itoa(ttl_ms, row + o)
103 row[o] = 124 as u8; o = o + 1
104 i = 0
105 while stop_path[i] != (0 as u8) { row[o] = stop_path[i]; o = o + 1; i = i + 1 }
106 row[o] = 124 as u8; o = o + 1
107 o = o + std_itoa(sys_now_us(), row + o)
108 row[o] = 0 as u8
109 let key: *u8 = sys_mmap(96) as *u8
110 dl_key(name, key)
111 sov_put(DL_STORE, key, row, o)
112 dl_add_id(name)
113 // start the leash clock: REGISTERED is a live custom state in nx_watch (never-beaten age = since now)
114 nw_mark("leash" as *u8, name, "REGISTERED" as *u8)
115 return 0
116}
117
118// copy |-field k of row[0..n) into out (NUL-term); returns len or -1.
119func dl_field(row: *u8, n: i64, k: i64, out: *u8, cap: i64) -> i64 {
120 var field: i64 = 0
121 var o: i64 = 0
122 var i: i64 = 0
123 while i < n {
124 let c: i64 = row[i] as i64
125 if c == 124 { field = field + 1; if field > k { i = n } }
126 if c != 124 { if field == k { if o < cap - 1 { out[o] = row[i]; o = o + 1 } } }
127 if i < n { i = i + 1 }
128 }
129 out[o] = 0 as u8
130 if field < k { return 0 - 1 }
131 return o
132}
133
134// walk (act=1) or status (act=0): scan every registered deployment, verdict each, reclaim ABANDONED
135// when act=1 (touch its declared stop_path + mark RECLAIMED). Returns worst verdict.
136func dl_walk(act: i64) -> i64 {
137 let ids: *u8 = sys_mmap(DL_MAGIC_262144) as *u8
138 let idn: i64 = sov_get_copy(DL_STORE, "d:ids" as *u8, ids, DL_MAGIC_262143)
139 if idn <= 0 { std_putln("LEASH no deployments registered" as *u8) return 0 }
140 let key: *u8 = sys_mmap(96) as *u8
141 let row: *u8 = sys_mmap(512) as *u8
142 let fb: *u8 = sys_mmap(256) as *u8
143 let name: *u8 = sys_mmap(96) as *u8
144 let word: *u8 = sys_mmap(64) as *u8
145 let age: *i64 = sys_mmap(8) as *i64
146 var worst: i64 = 0
147 var total: i64 = 0
148 var healthy: i64 = 0
149 var abandoned: i64 = 0
150 var dead: i64 = 0
151 var i: i64 = 0
152 while i < idn {
153 var e: i64 = i
154 var sc: i64 = 1
155 while sc == 1 {
156 if e >= idn { sc = 0 }
157 if sc == 1 { if ids[e] == (10 as u8) { sc = 0 } else { e = e + 1 } }
158 }
159 let nl: i64 = e - i
160 if nl > 0 && nl < 90 {
161 var m: i64 = 0
162 while m < nl { name[m] = ids[i + m]; m = m + 1 }
163 name[nl] = 0 as u8
164 dl_key(name, key)
165 let vn: i64 = sov_get_copy(DL_STORE, key, row, 511)
166 if vn > 0 {
167 row[vn] = 0 as u8
168 total = total + 1
169 let pid: i64 = sq_field_int(row, vn, 3)
170 let ttl: i64 = sq_field_int(row, vn, 4)
171 let alive: i64 = ml_pid_alive(pid)
172 var bage: i64 = DL_MAGIC_999999999
173 let cls: i64 = nw_read("leash" as *u8, name, word, age)
174 if cls >= 0 { bage = age[0] }
175 let v: i64 = dl_verdict(alive, bage, ttl)
176 std_puts("LEASH " as *u8)
177 std_puts(name)
178 std_puts(" owner=" as *u8)
179 dl_field(row, vn, 1, fb, 255)
180 std_puts(fb)
181 std_puts(" pid=" as *u8)
182 std_pdec(pid)
183 std_puts(" beat_age_ms=" as *u8)
184 std_pdec(bage)
185 std_puts(" -> " as *u8)
186 if v == DL_HEALTHY { healthy = healthy + 1; std_putln("HEALTHY" as *u8) }
187 if v == DL_DEAD { dead = dead + 1; std_putln("DEAD (pid gone; row stays for history)" as *u8) }
188 if v == DL_ABANDONED {
189 abandoned = abandoned + 1
190 if act == 1 {
191 dl_field(row, vn, 5, fb, 255)
192 let sf: i64 = sys_openat_wr(fb, 0x1a4)
193 if sf >= 0 { sys_close(sf) }
194 nw_mark("leash" as *u8, name, "RECLAIMED" as *u8)
195 std_puts("ABANDONED -> RECLAIMED (owner walked away; stop-file " as *u8)
196 std_puts(fb)
197 std_putln(" touched)" as *u8)
198 }
199 if act != 1 { std_putln("ABANDONED (walk would reclaim)" as *u8) }
200 }
201 if v > worst { worst = v }
202 }
203 }
204 i = e + 1
205 }
206 std_puts("LEASH walked total=" as *u8)
207 std_pdec(total)
208 std_puts(" healthy=" as *u8)
209 std_pdec(healthy)
210 std_puts(" abandoned=" as *u8)
211 std_pdec(abandoned)
212 std_puts(" dead=" as *u8)
213 std_pdec(dead)
214 std_puts("\n" as *u8)
215 return worst
216}
217
218// integer |-field k (digits only) -- local sibling of the queue's parser to stay import-light.
219func sq_field_int(row: *u8, n: i64, k: i64) -> i64 {
220 var field: i64 = 0
221 var v: i64 = 0
222 var seen: i64 = 0
223 var i: i64 = 0
224 while i < n {
225 let c: i64 = row[i] as i64
226 if c == 124 { field = field + 1; if field > k { i = n } }
227 if c != 124 { if field == k { if c >= 48 && c <= 57 { v = v * 10 + (c - 48); seen = 1 } } }
228 if i < n { i = i + 1 }
229 }
230 if seen == 0 { return 0 - 1 }
231 return v
232}
233
234func main(argc: i64, argv: *i64) -> i64 {
235 if argc < 2 {
236 std_putln("usage: nx_deploy_leash register <name> <owner> <purpose> <pid> <renew_ttl_ms> <stop_path> | walk | status" as *u8)
237 sys_exit(4)
238 return 4
239 }
240 let a1: i64 = argv[1]
241 let verb: *u8 = a1 as *u8
242 if std_streq(verb, "register" as *u8) == 1 {
243 if argc < 8 { std_putln("register needs <name> <owner> <purpose> <pid> <renew_ttl_ms> <stop_path>" as *u8); sys_exit(4); return 4 }
244 let b2: i64 = argv[2]
245 let b3: i64 = argv[3]
246 let b4: i64 = argv[4]
247 let b5: i64 = argv[5]
248 let b6: i64 = argv[6]
249 let b7: i64 = argv[7]
250 let p5: *u8 = b5 as *u8
251 let p6: *u8 = b6 as *u8
252 dl_register(b2 as *u8, b3 as *u8, b4 as *u8, std_atoi(p5), std_atoi(p6), b7 as *u8)
253 std_putln("LEASH registered (clock started; consumers: nx_watch beat leash <name> on every use)" as *u8)
254 sys_exit(0)
255 return 0
256 }
257 if std_streq(verb, "walk" as *u8) == 1 {
258 let w: i64 = dl_walk(1)
259 sys_exit(w)
260 return w
261 }
262 if std_streq(verb, "status" as *u8) == 1 {
263 let s: i64 = dl_walk(0)
264 sys_exit(s)
265 return s
266 }
267 std_putln("unknown verb (register|walk|status)" as *u8)
268 sys_exit(4)
269 return 4
270}