code wiki / (root) / nx_jobclaim_lib.nx

nx_jobclaim_lib.nx

buildroot/runtime/nx_jobclaim_lib.nx

21779 B472 linesdepth 2pulls 2 transitivereach 52 importersview sourcekind librarytopic jobclaim
docsdependenciesstructsconstsfunctions

about

nx_jobclaim_lib.nx -- ONE CONTRACT shared by the _jobs claim WRITER and the _jobs claim READER. WHY THIS IS A LIB AND NOT TWO ORGANS THAT EACH KNOW THE FORMAT. nx_jobclaim_reap marks a dead job claim by APPENDING a tombstone. nx_joblost_gate decides what a claim IS by looking for markers inside it. Those two are a PRODUCER and a CONSUMER of one wire, and this estate has already measured what that costs when each is written separately: a producer and a consumer each correct in isolation can still disagree on the wire. THE SPECIFIC TRAP THIS FILE MAKES IMPOSSIBLE. History here is additive (rule 13): the tombstone is APPENDED, so a reaped claim STILL CONTAINS its original `state=CLAIMED` line. The census classified by substring over the whole file and tested CLAIMED before anything else -- so a reader written on its own sees every reaped claim as still pending. The tombstone lands, the count does not move, the partition tooth breaks, and the reaper reads as a fix while being a no-op. A REAPER SHIPPED ALONE IS A NO-OP THAT LOOKS LIKE A FIX. The ORDER is therefore not each organ's private business. There is ONE classifier -- jr_state_of -- and both organs import it, so the ordering cannot be right in one and wrong in the other. WHY A TOMBSTONE AND NOT AN UNLINK. The claims store is a DIRECTORY OF FILES, not a last-wins seg-store, so the clock-plane's tombstone-row pattern does not transfer unchanged. `sys_unlinkat` exists and would work -- and it would also destroy the only record that the job was ever claimed, which is the evidence any later investigation of the loss needs. Rule 13: soft-delete, never DELETE. The precedent is nx_claims' own `reap` verb: release ONLY provably-expired claims, leave an audit note, additive-only, idempotent. This is that shape applied to a different store. license_tier: ORIGINAL

dependencies 1 imports · 11 importers

nx_syscalls.nx nx_jobclaim_lib.nx nx_job_concurrent_canonical_gate_t nx_job_reservation_canonical_gate_ nx_jobclaim_reap.nx nx_jobclaim_reap_gate.nx nx_joblost_gate.nx nx_tools_api.nx nx_tools_api_canonical_candidate_t nx_tools_api_idem_candidate_t190.n nx_tools_api_recovery_candidate_t3 nx_tools_api_recovery_candidate_v2

diagram shows first 10 each side; +0 more imports, +1 more importers in the complete lists below.

imports: nx_syscalls.nx

imported by: nx_job_concurrent_canonical_gate_t182.nxnx_job_reservation_canonical_gate_t182.nxnx_jobclaim_reap.nxnx_jobclaim_reap_gate.nxnx_joblost_gate.nxnx_tools_api.nxnx_tools_api_canonical_candidate_t182.nxnx_tools_api_idem_candidate_t190.nxnx_tools_api_recovery_candidate_t316.nxnx_tools_api_recovery_candidate_v2_t316.nxnx_tools_api_recovery_candidate_v3_t316.nx

structs

none

consts

34const JR_MARK_REAPED: *u8 = "state=REAPED" as *u8
35const JR_MARK_DONE: *u8 = "state=DONE" as *u8
36const JR_MARK_CLAIMED: *u8 = "state=CLAIMED" as *u8
37const JR_SELF: *u8 = "nx_jobclaim_reap" as *u8
38const JR_EXT_CLAIM: *u8 = ".claim" as *u8
39const JR_EXT_OUT: *u8 = ".out" as *u8
40const JR_PREFIX: *u8 = "job_" as *u8
41const JR_JOBS: *u8 = "_jobs" as *u8
42const JR_TMP: *u8 = "/tmp/" as *u8
43const JR_DOTDOT: *u8 = ".." as *u8
49const JR_ST_EMPTY: i64 = 0
50const JR_ST_REAPED: i64 = 1
51const JR_ST_DONE: i64 = 2
52const JR_ST_CLAIMED: i64 = 3
53const JR_ST_UNKNOWN: i64 = 4
57const JR_D_REAP: i64 = 0
58const JR_D_ALREADY: i64 = 1
59const JR_D_ABSENT: i64 = 2
60const JR_D_DONE: i64 = 3
61const JR_D_HAS_OUT: i64 = 4
62const JR_D_TOO_YOUNG: i64 = 5
63const JR_D_UNPARSED: i64 = 6
64const JR_D_WRITEFAIL: i64 = 7
65const JR_D_PATHLONG: i64 = 8
66const JR_D_BADID: i64 = 9
69const JR_I_STATE: i64 = 0
70const JR_I_AGE: i64 = 1
71const JR_I_HASOUT: i64 = 2
72const JR_I_BYTES: i64 = 3
73const JR_I_NEEDNL: i64 = 4
74const JR_I_SLOTS: i64 = 5
78const JR_I64_BYTES: i64 = 8
85const JR_MAXAGE_CONF: *u8 = "knowledge/status/jobclaim_maxage.conf" as *u8
86const JR_DEFAULT_MAX_AGE_SEC: i64 = 3600
88const JR_CH_NL: i64 = 10
89const JR_CH_MINUS: i64 = 45
90const JR_CH_DOT: i64 = 46
91const JR_CH_SLASH: i64 = 47
92const JR_CH_ZERO: i64 = 48
93const JR_CH_NINE: i64 = 57
94const JR_B10: i64 = 10
95const JR_SCRATCH: i64 = 16
102const JR_I64_DIGITS: i64 = 20
103const JR_TOMB_JOIN: i64 = 24
104const JR_TOMB_MAX: i64 = 128
105const JR_LINE: i64 = 256
106const JR_PATH: i64 = 1024
408const JR_ID_MAX:i64=9223372036854775807
409const JR_ERR_EXIST:i64=0-17
410const JR_ERR_INTR:i64=0-4
411const JR_ERR_INVALID:i64=0-22
412const JR_ERR_OVERFLOW:i64=0-75
413const JR_ERR_DEADLINE:i64=0-110
414const JR_ERR_PATH:i64=0-36
415const JR_ERR_IO:i64=0-5

functions

108func jr_slen(p: *u8) -> i64
116func jr_has(buf: *u8, n: i64, pat: *u8) -> i64
130func jr_prefix(s: *u8, pre: *u8) -> i64
called by 1: jr_dir_allowed calls 1: jr_slen
139func jr_streq(a: *u8, b: *u8) -> i64
called by 2: jr_dir_allowedmain calls 1: jr_slen
154func jr_state_of(buf: *u8, n: i64) -> i64
165func jr_state_of_path(path: *u8, sc: *i64) -> i64
174func jr_state_name(st: i64) -> *u8
called by 2: mainmain
183func jr_decision_name(d: i64) -> *u8
called by 2: mainmain
197func jr_decision_why(d: i64) -> *u8
called by 1: main
215func jr_num_from(buf: *u8, n: i64, seen: *i64) -> i64
called by 2: jr_maxagejl_floor
229func jr_atoi_strict(s: *u8) -> i64
called by 3: mainmainmain calls 1: jr_slen
249func jr_maxage(defaulted: *i64, scratch: *i64) -> i64
271func jr_dir_allowed(dir: *u8) -> i64
280func jr_cat(d: *u8, o: i64, s: *u8) -> i64
287func jr_catnum(d: *u8, o: i64, v: i64) -> i64
300func jr_mkpath(buf: *u8, cap: i64, dir: *u8, id: i64, ext: *u8) -> i64
327func jr_tombstone(path: *u8, now: i64, age: i64, need_nl: i64, line: *u8, lcap: i64) -> i64
353func jr_decide(state: i64, age: i64, maxage: i64, has_out: i64) -> i64
called by 1: jr_examine
364func jr_examine(dir: *u8, id: i64, now: i64, maxage: i64, info: *i64, pbuf: *u8, pcap: i64, sc: *i64) -> i64
395func jr_reap_one(dir: *u8, id: i64, now: i64, maxage: i64, dry: i64,
called by 2: mainmain calls 2: jr_examinejr_tombstone
416func jr_reserve(dir:*u8,first:i64,deadline_ms:i64,path:*u8,pathcap:i64,line:*u8,linecap:i64,out:*i64)->i64
464func jr_slot_occupied(dir:*u8,id:i64,path:*u8,cap:i64,ext:*u8)->i64
called by 1: jr_reserve calls 2: jr_mkpathsys_close