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