code wiki / _hdl_build / nx_pub_recover_pulsed.nx
nx_pub_recover_pulsed.nx source
↩ module page · 50 lines · 3059 B
1// nx_pub_recover_pulsed.nx -- the Publisher self-healing pulse as a CADENCE DAEMON (the runnable service form).
2// Each cycle: optionally refresh the metrics by running the collector (nx_apm_sweep), then run one pulse_pass
3// (decide + execute, with the kill-storm cooldown). Decoupled: if no collector path is given, it heals from
4// whatever metrics the collector wrote on its own schedule (clean collector/healer separation, New-Relic-style).
5// pulsed_run(interval_sec, max_cycles[0=forever], collector_elf_or_empty) -> cycles run
6// argv: nx_pub_recover_pulsed [interval_sec=60] [max_cycles=0] [collector_elf]
7// The Publisher (its supervision rung) keeps THIS daemon alive; THIS daemon keeps the site daemons healthy.
8// license_tier: ORIGINAL
9import "nx_syscalls.nx"
10import "nx_pub_recover_pulse.nx" // pulse_pass + PP_* defaults + pr_*
11const PD_MAGIC_5000: i64 = 5000
12
13const PD_METRICS: *u8 = "knowledge/status/apm_metrics.tsv"
14const PD_QUEUE: *u8 = "knowledge/publish/recovery_queue.tsv"
15const PD_LEDGER: *u8 = "knowledge/publish/recovery_ledger.tsv"
16const PD_MAP: *u8 = "knowledge/publish/recover_map.tsv"
17
18func pulsed_run(interval_sec: i64, max_cycles: i64, collector_elf: *u8, metrics: *u8, queue: *u8, ledger: *u8, map: *u8) -> i64 {
19 var cycle: i64 = 0; var go: i64 = 1
20 while go == 1 {
21 // refresh metrics via the collector if one is provided (else heal from externally-written metrics)
22 if collector_elf[0] != (0 as u8) {
23 let pid: i64 = sys_fork()
24 if pid == 0 {
25 let av: *i64 = sys_mmap(16) as *i64; av[0]=collector_elf as i64; av[1]=0
26 let ev: *i64 = sys_mmap(8) as *i64; ev[0]=0
27 sys_execve(collector_elf, av, ev); sys_exit(127)
28 }
29 let st: *i64 = sys_mmap(16) as *i64; sys_wait4(pid, st, 0)
30 }
31 pulse_pass(metrics, queue, ledger, map, PD_MAGIC_5000)
32 cycle = cycle + 1
33 if max_cycles != 0 { if cycle >= max_cycles { go = 0 } }
34 if go == 1 { let ts: *i64 = sys_mmap(16) as *i64; ts[0]=interval_sec; ts[1]=0; __syscall(35, ts as i64, 0,0,0,0,0) }
35 }
36 return cycle
37}
38
39func pd_atoi(s: *u8) -> i64 { var v: i64=0; var i: i64=0; while s[i]!=(0 as u8){ let c: i64=s[i] as i64; if c>=48 { if c<=57 { v=v*10+(c-48) } } i=i+1 } return v }
40func pd_uw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
41func main(argc: i64, argv: *i64) -> i64 {
42 var interval: i64 = 60; var cycles: i64 = 0; let empty: *u8 = "" as *u8; var collector: *u8 = empty
43 if argc >= 2 { let v: i64 = pd_atoi(argv[1] as *u8); if v > 0 { interval = v } }
44 if argc >= 3 { cycles = pd_atoi(argv[2] as *u8) }
45 if argc >= 4 { collector = argv[3] as *u8 }
46 pd_uw("=== nishi-publisher self-healing daemon (cadence) ===\n" as *u8)
47 let c: i64 = pulsed_run(interval, cycles, collector, PD_METRICS, PD_QUEUE, PD_LEDGER, PD_MAP)
48 pd_uw("cycles run: " as *u8); let nb: *u8=sys_mmap(24); let e: i64=pr_n(nb,0,c); sys_write(1,nb,e); pd_uw("\n" as *u8)
49 return 0
50}