code wiki / _hdl_build / nx_pub_daemon.nx
nx_pub_daemon.nx source
↩ module page · 48 lines · 3640 B
1import "nx_gate_gn.nx"
2import "nx_gate_base.nx"
3// nx_pub_daemon.nx -- the DEPLOYABLE publisher daemon, BEST-PRACTICE continuous service (researched + cited:
4// knowledge/fetched/dmn_*.raw via nx_dmn_research_fetch, 13/13). Operator: "run as we add things, not start/stop".
5// The determined practice (pub_daemon_serve): SUPERVISED auto-restart (systemd/runit), CRASH-ONLY (idempotent drain,
6// safe to kill+restart), EVENT-DRIVEN via inotify (act as work ARRIVES; poll-timeout fallback), HEARTBEAT liveness
7// (a watchdog detects a hang), GRACEFUL stop (finish the drain + exit). The SUPERVISOR is the hosting workstream's
8// (launch+restart via hostop_supervise / nx_aw_hostctl) -- this daemon is supervision-COMPATIBLE by construction.
9// SAFE-BY-DEFAULT: no-arg = usage (a build-run never launches the loop / mass-ships). license_tier: ORIGINAL expect_exit: 0
10import "nx_syscalls.nx"
11import "nx_publisher.nx"
12const K_MAGIC_1000000000: i64 = 1000000000
13const K_MAGIC_2000: i64 = 2000
14
15func grow(name: *u8, ok: i64) -> i64 { if ok==1 { gw(" PASS " as *u8) } else { gw(" FAIL " as *u8) } gw(name); gw("
16" as *u8); return ok }
17func streq(a: *u8, b: *u8) -> i64 { var i: i64=0; while a[i]!=(0 as u8){ if a[i]!=b[i]{return 0} i=i+1 } if b[i]!=(0 as u8){return 0} return 1 }
18func touch(path: *u8) -> i64 { let fd: i64 = sys_openat_wr(path, 0x1a4); if fd<0 { return 0 } sys_write(fd, "1" as *u8, 1); sys_close(fd); return 1 }
19
20func main(argc: i64, argv: *i64) -> i64 {
21 if argc < 2 {
22 gw("nishi publisher daemon -- BEST-PRACTICE continuous service (researched: knowledge/fetched/dmn_*.raw)\n" as *u8)
23 gw(" run -- continuous EVENT-DRIVEN (inotify) governed drain + HEARTBEAT; runs until stopped (supervisor restarts on death)\n" as *u8)
24 gw(" stop -- request GRACEFUL stop (writes the stop flag; the loop finishes its drain then exits)\n" as *u8)
25 gw(" status -- show heartbeat age in seconds (watchdog liveness; large/-1 = hung or not running)\n" as *u8)
26 gw("(no-arg = usage; never launches/mass-ships. SUPERVISE via hostop_supervise / nx_aw_hostctl; crash-only = safe to kill+restart.)\n" as *u8)
27 return 0
28 }
29 pub_init()
30 let cmd: *u8 = argv[1] as *u8
31 let hb: *u8 = "knowledge/publish/daemon.hb" as *u8
32 let stop: *u8 = "knowledge/publish/daemon.stop" as *u8
33
34 if streq(cmd, "stop") == 1 { touch(stop); gw("graceful stop requested (flag set; the running daemon will finish its drain then exit)\n" as *u8); return 0 }
35 if streq(cmd, "status") == 1 {
36 let age: i64 = pub_daemon_hb_age(hb, sys_now_realtime_sec())
37 gw("heartbeat age (s)=" as *u8); gn(age); gw(" (-1 = no heartbeat / not running; large = hung -> supervisor should restart)\n" as *u8); return 0
38 }
39 if streq(cmd, "run") == 0 { gw("unknown arg; use: run | stop | status\n" as *u8); return 0 }
40
41 __syscall(83, "knowledge/publish/stage" as *u8 as i64, 493, 0, 0, 0, 0)
42 __syscall(83, "knowledge/publish/live" as *u8 as i64, 493, 0, 0, 0, 0)
43 __syscall(87, stop as i64, 0, 0, 0, 0, 0) // clear any stale stop flag at startup
44 gw("=== nishi publisher daemon: CONTINUOUS (event-driven + heartbeat + graceful + crash-only) ===\n" as *u8)
45 let n: i64 = pub_daemon_serve("knowledge/publish/queue.tsv" as *u8, "knowledge/publish/ledger.tsv" as *u8, "knowledge/publish/stage" as *u8, "knowledge/publish/live" as *u8, "publish:canonical" as *u8, "knowledge/publish/approvals" as *u8, "knowledge/publish" as *u8, hb, stop, K_MAGIC_1000000000, K_MAGIC_2000)
46 gw(" daemon exited (graceful stop); published this run=" as *u8); gn(n); gw("\n" as *u8)
47 return 0
48}