code wiki / (root) / nx_heartbeat_monitor.nx

nx_heartbeat_monitor.nx

buildroot/runtime/nx_heartbeat_monitor.nx

9588 B201 linesdepth 4pulls 4 transitivereach 8 importersview sourcekind tooltopic heartbeat
docsdependenciesstructsconstsfunctions

about

nx_heartbeat_monitor.nx -- WMS-M1: the LIVENESS / HEARTBEAT MONITOR. module: nishi-core.wms.heartbeat_monitor capability: CORE_COMPUTE (durable cross-stream liveness detector built ON WMS-R0) WHAT THIS CLOSES: the autonomous conductor/team-pulse loop can CRASH mid-run and nobody notices -- the work just silently stops. There was no durable detector that could span streams AND survive a crash: nx_progress_watchdog.nx is in-RAM, single-process, monotonic (its STALLED/OK state dies with the process and cannot see a sibling stream). nx_heartbeat_register.nx is capability-registry wiring, not a monitor. M1 reuses ONLY the STALLED/OK semantics of the watchdog; the durable, cross-stream substrate is the WMS-R0 atomic framed-append log (a heartbeat channel). THE MECHANISM: every active workstream BEATS an epoch -- one framed record appended (via the WMS-R0 locked single-write primitive) into a shared heartbeat channel: "HBX ws=<id> epoch=<beatsec> seq=<n> actor=<pid> END" A monitor REPLAYS the channel and, for a set of ws-ids, computes age = now - last_beat and flags STALLED iff (the stream has beaten AND age > threshold). Last-writer-by- MAX-epoch makes it robust to out-of-order append: a fresh beat ALWAYS clears a stale reading (this is what makes the TAMPER/resume lane clear correctly). REUSE / lineage (check-registries-before-building): - fa_append / fa_appendz / fa_cat / fa_catn (nx_framed_append.nx, WMS-R0b): the atomic locked single-write framing primitive -> each beat = exactly one write(). - wsl_at / wsl_field / the per-'\n' line-scan replay skeleton (nx_ws_ledger.nx, WMS-R2): token match + decimal field extract + no-silent-skip flagging. Sovereign: only nx_syscalls + nx_framed_append + nx_ws_ledger. Additive: no organ is modified -- new files only. WRITE DISCIPLINE (the torn-line bug we just killed): EVERY heartbeat record is assembled into ONE buffer (fa_cat/fa_catn) and emitted with a SINGLE fa_append locked write. NEVER a sequence of sys_write() calls. license_tier: ORIGINAL

dependencies 3 imports · 6 importers

nx_syscalls.nx nx_framed_append.nx nx_ws_ledger.nx nx_heartbeat_monitor.nx nx_boot_revive.nx nx_boot_revive_m6_gate.nx nx_conductor_live_wms_gate.nx nx_heartbeat_monitor_gate.nx nx_supervised_dispatch.nx nx_supervised_dispatch_tamper.nx

imports: nx_syscalls.nxnx_framed_append.nxnx_ws_ledger.nx

imported by: nx_boot_revive.nxnx_boot_revive_m6_gate.nxnx_conductor_live_wms_gate.nxnx_heartbeat_monitor_gate.nxnx_supervised_dispatch.nxnx_supervised_dispatch_tamper.nx

call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown

main _hbm_p sys_write sys_openat_wr sys_close hb_beat_at sys_mmap hbm_build fa_cat fa_catn sys_mmap ↻ fa_append sys_mmap ↻ sys_openat_append sys_flock fa_write_all sys_write ↻ sys_close ↻ sys_mmap ↻ hbm_scan hb_last_beat sys_mmap ↻ sys_read_file sys_openat_rd sys_lseek sys_mmap ↻ sys_read sys_close ↻ hb_wellformed wsl_field wsl_at sys_mmap ↻ wsl_parse_int sys_mmap ↻ sys_read_file ↻ hb_wellformed ↻ _hbm_n sys_mmap ↻ sys_write ↻ sys_exit

structs

none

consts

37const HB_MAGIC_2277: i64 = 2277
39const HB_RECCAP: i64 = 256 // bounded record size (matches R0/R2 RECCAP)
40const HB_ALIVE: i64 = 0 // beating within threshold
41const HB_STALLED: i64 = 1 // last beat older than threshold (the crash signal)
42const HB_UNKNOWN: i64 = 2 // never seen a beat for this stream

functions

47func hbm_build(buf: *u8, ws: i64, epoch: i64, seq: i64, actor: i64) -> i64
called by 1: hb_beat_at calls 2: fa_catfa_catn
65func hb_beat_at(path: *u8, ws: i64, epoch: i64, seq: i64, actor: i64) -> i64
73func hb_beat(path: *u8, ws: i64, seq: i64) -> i64
82func hb_wellformed(b: *u8, ls: i64, le: i64) -> i64
101func hb_last_beat(path: *u8, ws: i64) -> i64
133func hbm_scan(path: *u8, now: i64, threshold: i64, ids: *i64, nids: i64,
178func _hbm_p(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
called by 1: main calls 1: sys_write
179func _hbm_n(v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m; sys_write(1,"-\x00" as *u8,1)}; let t: *u8=sys_mmap(28); 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; while i<k{bb[i]=t[k-1-i];i=i+1}; sys_write(1,bb,k); return 0 }
called by 1: main calls 2: sys_mmapsys_write
180func main() -> i64