Commit graph

1549 commits

Author SHA1 Message Date
d6008ead99 improve frontend jobid display 2026-05-07 02:36:24 +00:00
3ed7ef011a fix go jobId schema bug 2026-05-03 11:45:14 +08:00
d7afd72e5b fix front end issues 2026-05-01 21:22:45 +08:00
177cf45af5 docs: mark Phase 6 complete in phase6-scheduler-integration-plan 2026-04-30 07:17:32 +00:00
9b0e9571d1 docs: mark Phase 6 complete in resreq-ast-cse-impl-plan 2026-04-30 07:06:36 +00:00
d438742f1a fix: staging_merge_complete bootstrap deadlock and missing recompact_node_ids
Two correctness fixes found during final Phase 6 code review:

F1 (CRITICAL): GC permanently disabled — staging_merge_complete bootstrapping deadlock.
sched_begin_session reset staging_merge_complete to 0 but never set it back to 1,
so sched_end_session's guard (!staging_merge_complete) always fired, preventing GC
from ever running. select-node memory leaked indefinitely across scheduling sessions.
Fix: set staging_merge_complete=1 at the end of sched_begin_session after all
staging work (sched_account_jobs etc.) completes.

F2 (HIGH): recompact_node_ids() omitted from GC protocol in sched_end_session.
The protocol in resreq.h requires gc_sweep → recompact_node_ids. Without
recompaction, sel_node_next_id grows monotonically across sessions and
select_eval_ctx_t arrays (sized by max node_id) grow without bound.
Fix: call recompact_node_ids() after gc_sweep_select_nodes.

Also adds test_staging_merge_complete_gc_guard to document the bootstrap
invariant: sched_begin_session must leave staging_merge_complete=1 so the
GC guard in sched_end_session does not fire.
2026-04-30 06:48:01 +00:00
5fcf85c494 test: scheduler integration tests for sched_meet_host_selection (6-11) 2026-04-30 06:23:28 +00:00
1eb4eb1335 fix: use _Atomic flag for sel_alloc_thread_id registration, move reg before loop, add wrong-thread guard test 2026-04-30 06:15:01 +00:00
b722e5cb3d feat: add sel_alloc_thread_id ownership check in eval_select and gc_sweep (6-10) 2026-04-30 06:04:21 +00:00
742d79ee55 fix: free live_jobs and null-sentinel on realloc failure in sched_end_session 2026-04-30 05:54:46 +00:00
fb5127ad66 fix: skip GC in sched_end_session when live_jobs allocation fails (OOM safety) 2026-04-30 05:49:49 +00:00
5267d36a84 feat: drive GC from sched_end_session — live_jobs mark, seq_cst fence, gc_sweep (6-8, 6-12) 2026-04-30 05:44:46 +00:00
8cff4ac889 fix: add bounds checks in eval_select_simple for null/empty host_eval_ctx; remove empty_ctx hack
- simple_num/simple_str: guard h->numvals/strvals NULL and idx out-of-range before array access
- eval_select_simple SEL_RESNAME: guard host->numvals NULL and idx bounds before deref
- eval_select_inner SEL_RESNAME (memoizing path): same NULL/bounds guards for numvals and strvals
- build_host_eval_ctx: return valid empty context (num_res=0, NULL arrays) instead of NULL when num_res<=0
- sched_meet_host_selection: remove empty_ctx stack hack; always call build_host_eval_ctx which now handles the zero-resource case cleanly
2026-04-30 05:20:37 +00:00
9ed38d4bad fix: address fifth-round adversarial review findings for persistence-and-ha-design
P1 fixes:
- A5-008: Change `in_catch_up` from plain `int` to `_Atomic int` with
  documented access patterns and memory ordering
- A5-002: Add missing opcodes to Part 5.10 capnp schema (heartbeat,
  steppingDown, replSnapshot, replCatchUpDone)
- A5-004: Add hook list synchronization spec for demotion (RCU-style
  removal with disabled flag and deferred memory reclamation)
- A5-005: Change xce_connect_cluster return type from int to SSL*,
  add xce_disconnect_cluster(SSL*), update xce_reconnect to SSL**
- A5-006: Add GC use-after-free mitigation section (per-operation READ
  lock hold for P0, epoch-based reclamation as P3)
- A5-010: Add OP_steppingDown handler spec to P1-2 milestone
- A5-001: Clarify P0-3 checkpoint timer vs dedicated pthread timers
- A5-003: Clarify WAL_CRC_NONE handling in replication CRC validation
- A5-013: Add repl_remove_standby slot cleanup requirement
- A5-012: Add primary_ep lifecycle documentation (iomgr-owned borrow,
  NULL-before-free under mutex)
- A5-014: Add async hook error handling convention
- A5-015: Add aggregate memory budget analysis for concurrent snapshots
- A5-016: Fix ha_check_heartbeat plain role read to use atomic_load_explicit
- A5-017: Fix Appendix A.4 in_catch_up type consistency (_Atomic int)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 05:17:56 +00:00
40261b7e96 feat: implement sched_meet_host_selection using eval_select_simple (6-5)
Replace the always-return-1 stub with a real implementation that:
- Returns 1 immediately when s == NULL or s->root == NULL (no constraint)
- Builds a host_eval_ctx_t from w->resvals and calls eval_select_simple
- Uses a zero-resource stack context when resvals.caps == 0 so constant
  sub-expressions (SEL_TRUE, SEL_FALSE, SEL_ANY) still evaluate correctly
- On OOM (build_host_eval_ctx returns NULL), conservatively passes the host
- Maps eval_select_simple result: >0 → 1 (match), <=0 → 0 (no-match)

Add #define UNIT_TEST 1 to test.c, remove redundant #ifdef guard, and
add three new TDD tests covering NULL select, SEL_TRUE, and SEL_FALSE.
All 6 tests pass.
2026-04-30 05:04:47 +00:00
2e3469c3c5 fix: correct zarray single-pointer convention in build_host_eval_ctx; add num_res guard 2026-04-30 04:58:28 +00:00
907d8d80a3 feat: implement build_host_eval_ctx — project resvals zarray to host_eval_ctx_t (6-7) 2026-04-30 04:49:27 +00:00
acda9bb228 feat: add sched GC predicate statics; wire sel_optimize_set(1) in sched_init (6-4, 6-9) 2026-04-30 04:13:14 +00:00
72546d3a22 fix: restore libxce_deps in scheduler test deps (removed by mistake in task 3) 2026-04-30 04:08:14 +00:00
823a66e91e feat: add _Atomic gc-predicate fields to xce_scheduler_t (phase 6 task 6-3) 2026-04-30 04:03:51 +00:00
4e177047c9 fix: correct SEL_NUM bit-cast in gc test; assert n1 swept; add recompact to protocol comment 2026-04-30 03:55:15 +00:00
9a19a8f932 feat: export gc_clear_marks + gc_mark_select_tree; remove clear from gc_sweep (phase 6)
- Add gc_clear_marks(): iterates intern table and zeroes all gc_mark bits
- Rename static gc_mark_tree → public gc_mark_select_tree (no attribute((unused)))
- Remove Phase 6 guard (live_jobs != NULL early return) from gc_sweep_select_nodes
- Remove the mark-clear loop from gc_sweep_select_nodes; add (void) casts for now-unused params
- Declare gc_clear_marks and gc_mark_select_tree in resreq.h with protocol comment
- Add TDD test test_gc_clear_marks_exported verifying the exported primitives
- Prefix all existing gc_sweep_select_nodes(NULL, 0) call sites in test_select.c with gc_clear_marks()
2026-04-30 03:40:24 +00:00
bb4a95ce37 chore: phase 6 pre-audit — allocator single-threaded confirmed, stub at resource.c:127 2026-04-30 03:28:41 +00:00
c623e37b84 fix: address fourth-round adversarial review findings for persistence-and-ha-design
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-29 14:01:26 +00:00
454b4aa355 fix: address third-round adversarial review findings for persistence-and-ha-design
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-29 13:36:43 +00:00
f1641b1fbf docs: fix 9 P0 and 6 P1 issues from second adversarial review
P0 fixes (9):
- R-22: COW vstore find-slot-and-write not atomic
- R-23: vput grow path without mutex during COW
- R-24: Post-growth slot double-claimed by concurrent threads
- R-25: Missing key_snapshot field for checkpoint serialization
- R-26: malloc(0) for WAL_CHECKPOINT entries
- R-27: Fallback to older snapshot with trimmed WAL
- R-28: hdr.term > ha->term + 1 too restrictive
- R-29: _Atomic on enum type (implementation-defined)
- R-30: handle_jobsubmit() ignores hook return value
- R-31: malloc NULL check missing in standby receiver

P1 fixes (5):
- R-32: No heartbeat during persist_recover() on new primary
- R-33: Catch-up from dead primary removed from promotion
- R-34: Added total_wal_bytes field to persist_t

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-29 12:55:47 +00:00
54bbfa5865 docs: fix 6 additional P0/P1 review findings for persistence-and-ha-design
P0 fixes (3):
- R-16: vstore COW growth re-check used OOB a->data[old_caps].inuse
- R-17: Standby WAL write return value unchecked before sending ACK
- R-18: Chained CRC validation absent from replication stream

P1 fixes (3):
- R-19: Replicated entry LSN handling unspecified
- R-20: seg_offset in-memory and lost on crash
- R-21: WAL segment rotation prev_crc handling at recovery

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-29 12:28:39 +00:00
bb66b9766d docs: fix remaining P0/P1 review findings for persistence-and-ha-design
- P0: Fix concurrent vstore race under READ lock during COW mode
  (add xzarray mutex serialization around grow-and-assign section)
- P0: Array job sync replication latency bound (batch mode for
  array submits to avoid O(array_size × sync_timeout_ms) blocking)
- P1: rtti library ABI break documented with two-repo dependency note
2026-04-29 12:02:53 +00:00
8bab418c61 docs: address multi-perspective review findings for persistence-and-ha-design
Fixes 15 P0/P1 issues identified by coherence, feasibility, scope, and
security reviewers:

- P0: traversalLimitInWords fixed to constant bound (not file_size / 8)
- P0: Job ID allocator reset added to recovery sequence
- P0: acked_lsn declared _Atomic uint64_t in struct definition
- P0: ha.role declared _Atomic ctrl_role_t with acquire/release semantics
- P0: hooks_registered idempotency guard added to ha_state_t
- P0: MAX_HA_CANDIDATES reduced from 16 to 4 (speculative generality)
- P0: checkpoint_mutex (pthread_mutex_t) added to persist_t
- P1: Split-brain detection condition explicitly specified
- P1: Heartbeat interval minimum standardized to 2000ms
- P1: Degraded-mode restricted state removed from scope
- P1: Config version hash in heartbeat deferred to P3
- P1: WALEntry Cap'n Proto schema clarified as replication-only
- P1: Snapshot backward compatibility path documented
- P1: Snapshot total_size validated BEFORE malloc
- P1: WAL_QUEUE_CTRL/WAL_WORKER_CTRL replay made idempotent
- P1: mTLS gate enforced before replication code (P1-1)
- P1: PENDING reason ambiguity logged at DEBUG during replay

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-29 11:54:11 +00:00
607f9519e1 docs: address 30 adversarial review findings for persistence-and-ha-design
Three rounds of adversarial review plus a regression review identified
30 findings across CRITICAL/HIGH/MODERATE/LOW severities. Key fixes:

CRITICAL/HIGH:
- C11 atomics for COW inuse fields (vget, vput, vstore scan + growth)
- kvtab_gc must run inside same write-lock section as thaw
- WAL growth safeguard during in-progress checkpoint
- pthread_mutex_t checkpoint_mutex (not mylock_t) for cond var
- atomic_store_explicit(release) for ha.role demotion write

MODERATE:
- LSN strictly-increasing check (not consecutive) for WAL_CHECKPOINT gaps
- Hook unregistration on demotion + idempotent registration guard
- CLOCK_MONOTONIC recommendation for retention time comparisons
- Cross-kvmgr freeze ordering documented (WAL replay restores consistency)
- pthread_once + rand_r() replacing unsafe rng_seed_once/rand()
- should_retain lock requirement and merge-walk iterator lock doc
- Standby catch-up receive ordering (snapshot-first, then live WAL)
- applied_lsn==0 gap validation clarification

LOW:
- Demotion failure handling (fail-forward as STANDBY, no rollback)
- WAL_CRC_NONE (0xFFFFFFFF) sentinel replacing collision-prone 0
2026-04-29 10:43:02 +00:00
b38babb7d6 feat: implement Phase 4d const-fold transform for select AST
Adds sel_const_fold_pass() — a single-pass bottom-up const-fold that
runs after the Phase 4c flatten loop in parse_select():

  4d-1  EQ/NE with either operand SEL_ANY → SEL_TRUE / SEL_FALSE
        (checks both child slots — commutativity sort makes SEL_ANY
        position non-deterministic after makeSelectNode interning)
  4d-2  Identity laws: TRUE&&X→X, X&&TRUE→X, FALSE||X→X, X||FALSE→X
  4d-3  Annihilation laws: FALSE&&X→FALSE, TRUE||X→TRUE (symmetric)
  4d-4  Complement laws: !TRUE→FALSE, !FALSE→TRUE

Memory semantics:
  level==0 (API server): frees orphaned nodes via free_select_node /
    sel_free_tree; OOM from makeSelectNode returns original node safely
  level>0  (CSE/scheduler): never manually frees; annihilation folds
    return the already-interned left/right singleton directly (no
    redundant makeSelectNode call); OOM guard unconditional so CSE
    mode also degrades gracefully instead of returning NULL

9 new TDD tests added to test_select.c (RED→GREEN verified).
All 166 tests pass (157 prior + 9 Phase 4d).
2026-04-29 08:24:04 +00:00
c2ad96a5e0 docs: incorporate review feedback for resreq-ast-cse-design
- Rename grammar rules: or_expr→select_or, and_expr→select_and,
  not_expr→select_not, atom_expr→select_primary
- Eliminate SEL_BOOL_LITERAL: parse true/false directly as
  SEL_TRUE/SEL_FALSE; boolean resources used standalone (gpu,
  not gpu==true)
- Remove 'true'|'false' from value production in grammar
- Use LSF-style unquoted strings in examples (type==linux,
  not type=="linux")
- Document n-ary vs binary tree decision in §6.2
- Add §8.5 Evaluation Memoization: per-host select_eval_ctx_t
  with node_id-indexed bool_bits bitmap, num_vals, str_vals
  arrays; memoized eval_select with cache check; session lifecycle
  (pre-session capacity, per-host alloc/discard, post-session
  GC + node ID recompaction)
- Add node_id field to xce_select_node_t for eval context indexing
- Clarify §9 two-level sharing: select CSE is global, resreq
  sharing is scoped to (user, queue, project)
- Clarify §10 select vs rusage boundary: select evaluates against
  host snapshot, rusage checks host.available (total - booked)
2026-04-22 02:25:30 +00:00
19898a198a docs: address deep document-review findings for resreq-ast-cse-design
Review by adversarial, feasibility, and product-lens reviewers.
Key changes:

- Add host_eval_ctx_t struct to carry both numeric and string host
  resource values; xvec_idval_t is for job allocation, not host eval
- Fix SEL_FALSE case in eval_select (was returning -1 instead of 0)
- Add bval field to appendix xce_select_node_t struct
- Fix makeSelectNode key_add race (EEXIST now re-finds existing entry)
- Specify two-phase GC sweep to avoid iterator corruption in kvtab
- Add EDA cluster justification for CSE memory savings
- Use %.17g instead of %g for number-to-string coercion (full precision)
- Add #include "kv.h" dependency note for Phase 4
- Add runtime goroutine assertion requirement for CGO bridge safety
- Add gc_sweep_select_nodes() CGO call in Phase 6 session boundary
- Clarify job cleanup happens at session boundaries (no mid-session kill)
- Clarify sel_key_hash/sel_key_cmp must hash fields individually (padding)
2026-04-21 07:05:49 +00:00
98911a2154 docs: add controller code consistency findings to persistence design
Incorporates investigation of vtaskmgr.c, netio.c, cluster.c, job.c,
join.c, and worker.c into the persistence-and-ha-design document:

- Part 2.7: Controller connection context (workers/scheduler/API servers only)
- Part 3.8: COW lock hierarchy (kvmgr rwlock -> xzarray mutex)
- Part 3.9: Checkpoint timer uses delaymgr, not raw pthread
- Part 4.9: Endpoint deferred cleanup (close fd/SSL, defer slot cleanup)
- Part 4.10: mark_worker_unavail() already exists, only needs extending
- Part 6.5: Replication uses endpoint/iomgr/vtask SSL pipeline
- Part 8.3: Lock safety analysis for reply-after-hooks change
- P0-2a, P0-8a, P2-5a: New implementation steps
- Appendix A.3/A.4: standby_conn_t and ha_state_t use endpoint_t*
2026-04-21 04:46:20 +00:00
877741d008 docs: address document-review findings for resreq-ast-cse-design
Multi-persona review (coherence, feasibility, adversarial, product-lens)
identified 25 findings. Applied 14 fixes:

- Fix makeSelectNode key_add return code bug (rc2 → rc3)
- Resolve derefSelectNode contradiction: remove function and refcount
  field, adopt GC-only reclamation model
- Add boolean_literal grammar rule (true/false keywords) and
  SEL_BOOL_LITERAL node type + bval union member
- Clarify transform pipeline: makeSelectNode does commutativity swap
  internally; flattening/const-fold are post-parse tree walks
- Complete const-fold rules with annihilation laws
- Add SEL_NUM bit-cast semantics (±0 distinction, NaN payloads)
- Add resmgr=NULL fallback behavior spec
- Add runtime type safety assertions for debug builds
- Add GC trigger and session-based scheduler context
- Fix section numbering gap (renumber §5.6 → §5.5)
- Add gc_sweep_select_nodes/gc_mark_tree to Phase 2 declarations
- Update kill_primary_resreq instruction for GC model
- Add any keyword semantic inconsistency note (!= vs !(==))

4 open issues remain for implementation phase: string resource
interface, single-goroutine enforcement, kvtab iteration API,
CSE benefit quantification.
2026-04-21 03:29:31 +00:00
33b76d9a77 docs: add select expression AST with CSE/hash-consing design
Design document for implementing the select clause parser with:
- PEG grammar with LSF-compatible resname/string disambiguation
- Hash-consing CSE via intern table with TOCTOU-safe insertion
- Mark-and-sweep GC between scheduling sessions
- Explicit error propagation in eval_select (-1/0/1 tri-state)
- Parse-time type coercion for EQ/NE (e.g., type==5 converts 5 to "5")
- AST transform pipeline: commutativity canonicalization,
  associativity flattening, const-fold (type==any -> SEL_TRUE)
- Special keywords: any, SEL_TRUE, SEL_FALSE
- String host resource accessor (parallel res_idx->char* lookup)
- res_type_t <-> XCE_VAL_* bidirectional mapping
- Single-goroutine CGO bridge invariant
2026-04-20 09:43:07 +00:00
86a65d640a test(apiserver): add integration tests for P0+P1 backend features
Covers ~30 integration tests across 8 sections from the
apiserver-backend-integration-test-plan:

- §1: Cluster config push (store population, merge semantics, zero-preserve)
- §2: Host control (OnHostUpdated merge, validateHost, preCheck, batch ops)
- §3: Resource value push (all 7 value types, nil/unknown discriminant, overwrite)
- §4: Heartbeat keep-alive (interval update, zero-preserve)
- §5: Cross-feature (config+heartbeat, config+host, worker+config field preservation)
- §6: RBAC (cluster_admin bypass, algorithm confusion, expired tokens, hostgroup bypass)
- §7: Store thread safety (concurrent config pushes, host control+config, resource values)
- §8: Input safety (hostname length, empty lists, malformed payloads)

All tests use CGO_ENABLED=0 with //go:build !cgo build tag.
§8.1 hostname-length skipped pending P1-2b implementation.
2026-04-18 11:56:31 +00:00
0a3de8b040 fix: P1-3 address heartbeat timer leak, test drain, and store consistency
- COR-001: drain runHeartbeat goroutine via done channel before test returns,
  eliminating race against concurrent SetHeartbeatInterval tests
- COR-002: replace time.After with time.NewTimer + defer t.Stop() + t.Reset()
  to prevent timer goroutine leaks on context cancellation
- COR-005: guard HeartbeatInterval store write with > 0 check in OnClusterUpdated,
  keeping store consistent with SetHeartbeatInterval's zero-ignore semantics
2026-04-17 14:20:02 +00:00
ffc5b20cdb feat: P1-3 add heartbeat keep-alive goroutine
- add heartbeat.go with heartbeatIntervalSecs var, SetHeartbeatInterval, runHeartbeat (no build tag, CGO-free)
- add heartbeat_test.go with 5 tests covering interval validation and goroutine lifecycle
- add StartHeartbeat to clib.go (CGO impl calling xcecli_heartbeat)
- remove SetHeartbeatInterval stub from stub.go (now real code in heartbeat.go)
- remove TestSetHeartbeatInterval_StubNoOp from stub_funcs_test.go
- call SetHeartbeatInterval in OnClusterUpdated to track backend-pushed interval
- call backend.StartHeartbeat in cmd/main.go after backend registration
2026-04-17 14:12:40 +00:00
bc3103a6d5 feat: P1-1 handle resource value push via OPCode_notify
Add OPCode_notify handler in go_push_handler top-level switch
(not inside handlePush) to receive resource value updates from
the controller via xce_notify_data_t/schedUpdateResvals.

- Add 8 CGO union accessors for xce_val_t (which, i32, i64,
  u32, u64, fval, str, bool) since CGO cannot access union fields
- Add handleNotifyData() dispatching NotifyData_data_schedUpdateResvals
  events, iterating xce_resval_list_t and calling cResvalToDistribution
- Add cResvalToDistribution in convert.go with 7 separate switch
  cases for Value_u_* union discriminants (no combining i32/i64)
- Add rawResvalData + rawResvalToDistribution pure-Go version
  in convert_pure.go for testability without CGO
- Add 10 TDD tests covering all 7 value types, nil val guard,
  unknown discriminant, and boolean false
- All 42 backend tests passing
2026-04-17 13:54:03 +00:00
dc029a6d14 feat: P0-2d add no-CGO stubs for heartbeat, select, cleanup
Add four function stubs to backend/stub.go for the !cgo build path:
- StartHeartbeat(ctx context.Context) — no-op (heartbeat not available)
- SetHeartbeatInterval(secs int) — no-op (interval update not available)
- EvalSelectForHost(hostname, selectExpr string) error — returns errNoCGO
- Cleanup() — no-op (no C resources to release without CGO)

TDD: four tests in stub_funcs_test.go verify stubs behave correctly
(no-op functions don't panic, error stubs return errNoCGO). All backend
tests passing.
2026-04-17 10:02:11 +00:00
f354a5ec78 feat: P0-2c register routes + RBAC for host control/select
Routes and RBAC entries already existed from prior P0-2a/2b work. This
adds three TDD tests that lock down the RBAC invariants:

- TestRBAC_HostControl_ClusterAdminOnly: cluster_admin has host:control
  with domain=all; basic_user must NOT have host:control
- TestRBAC_HostView_BasicUserHasAccess: basic_user has host:view with
  domain=all; queue_admin must NOT have host:view
- TestRBAC_HostControl_DomainTypeIsAll: cluster_admin host:control
  domain type must be "all" (not hostgroup)

All apiserver tests passing.
2026-04-17 09:32:21 +00:00
5807a05cbb fix: address P0-2b review issues - build tag and actionType guard
1. Add //go:build !cgo to control_host_test.go so the stub-testing
   tests only run in non-CGO builds, matching the stub.go build
   constraint. Clean up dead nil check in SignatureCompiles test.

2. Replace two independent if-statements for actionType mapping in
   ControlHost with a map lookup + explicit guard, consistent with
   ControlQueue's ActionMap pattern. Prevents silent zero-value
   actionType if SupportedHostActions expands later.
2026-04-17 08:25:05 +00:00
8124cda83e feat: P0-2b implement ControlHost via xcecli_hostctrl + fix allFlag race
- backend/clib.go: Replace ControlHost stub with real implementation
  using xcecli_hostctrl, following the same pattern as ControlQueue
- controllers/hosts.go: Remove package-level allFlag variable;
  preCheckHostControlRequest now returns (bool, error) so the allFlag
  is a local value in the caller, eliminating the data race
- controllers/queues.go: Same fix for preCheckQueueControlRequest
- Add unit tests for both preCheck functions verifying return values,
  error cases, and concurrent safety
- Add compile-time verification test for ControlHost stub signature
2026-04-17 08:17:56 +00:00
ff940223ec docs: mark P0-2a complete, unblock P0-2b
Update task tracker: P0-2a is done (15 files, 8 TDD tests, 116/116
pass). P0-2b (Go-side ControlHost + allFlag race fix) is now unblocked.
Also fixed pre-existing goto-clean bug in worker_ctrl that leaked
write lock + reference count on HOST_OPEN/HOST_CLOSE no-op paths.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 07:47:30 +00:00
dcb1b4fe25 feat: P0-2a C-side plumbing for host control
Add the full call chain for host control operations from the Go API
server through the C library to the controller:

- schema/controller.capnp: HostControl struct + hostctrlmsg @21
  in Request.body union
- include/typemap.h: xce_hostctrl_t* hostctrlmsg in body union
  (placed after @20 clrpreasonmsg, matching capnp ordinal)
- include/client.h, xceapi.h, request.h: declarations for
  xcecli_hostctrl, xce_hostctrl, xce_hostctrl_req
- lib/client.c: xcecli_hostctrl (validate + delegate to xce_hostctrl)
- lib/xceapi.c: xce_hostctrl (validate ctx state + send + wait reply)
- lib/request.c: xce_hostctrl_req (validate hostname/empty/nil,
  accept only HOST_OPEN/HOST_CLOSE, reject HOST_TAG/UNTAG)
- lib/helper.c: Request_body_hostctrlmsg cases in
  xce_request_body() and xce_request_msg_name()
- controller/cluster.c: OPCode_hostcontrol dispatch
- controller/include/cluster.h: do_hostcontrol_op declaration
- controller/worker.c: do_hostcontrol_op + fix pre-existing
  goto-clean bug in worker_ctrl that leaked write lock and
  reference on HOST_OPEN/HOST_CLOSE no-op paths

TDD: 8 xce_hostctrl_req validation tests (null ep, null ctrl,
null/empty hostname, HOST_DO_NONE no-op, HOST_TAG/UNTAG reject,
negative action reject, HOST_OPEN/CLOSE accept via xce_request).

116/116 xcelib tests pass. CGO_ENABLED=0 Go backend tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 07:46:41 +00:00
ac7ac99ced refactor: make merge semantics explicit in OnHostConfigUpdated/OnClusterUpdated
Start from existing entry and apply this-source's fields, rather than
starting from incoming and restoring the other-source's fields. The new
pattern makes it immediately clear which fields each push type WRITES,
without having to reason about which fields are being "restored".

OnHostUpdated keeps the merged := *incoming + if ok guard because the
worker push also populates HostModel/HostType from attrs; config-sourced
values must only win when a prior config push has already set them.

All 37 backend unit tests pass.
2026-04-17 06:48:25 +00:00
893812e7aa feat: P0-1e expand handleConfigPush with host config and cluster dispatch
Wires the remaining cluster_config_t data into the notification pipeline:
- dispatchConfigPush() extracted as a pure-Go helper (CGO-free, testable)
  that drives OnQueueUpdated, OnResourceUpdated, OnHostConfigUpdated, and
  OnClusterUpdated from a single config push event
- handleConfigPush() delegates to dispatchConfigPush via the new helper,
  eliminating the previous inline loops
- OnHostConfigUpdated and OnClusterUpdated added to NotificationHandler
  interface and implemented with partial-merge semantics in DefaultHandler
- rawHostConfigData/rawHostConfigToModel and rawClusterData/rawClusterToModel
  added to convert_pure.go with their CGO extraction counterparts in convert.go

Safety fixes from code review:
- OnHostUpdated, OnHostConfigUpdated, OnClusterUpdated now copy *incoming to
  a local merged value before mutation, closing the TOCTOU window between
  store.Get and store.Put under concurrent pushes
- cClusterConfQueues and cClusterConfResources gain nil-pointer guards
  matching the existing guard in cClusterConfHostConfigs
- handleConfigPush gains an explicit gHandler nil check
- cClusterConfToClusterInfo returns nil on empty clustername (prevents phantom
  empty-key write to store.Clusters); handleConfigPush logs a warning when nil
- 36 unit tests passing (CGO_ENABLED=0)
2026-04-16 11:25:03 +00:00
00c4472d6c Add HostConfig + Cluster fields to models and update docs 2026-04-16 09:24:22 +00:00
960ef62342 fix job array display issue 2026-04-14 18:23:49 +08:00