myxce/src/docs/apiserver-backend-tasks.md
2026-08-10 17:51:51 +08:00

9.9 KiB

API Server Backend Enhancement — Task Tracker

Status Legend

  • Completed
  • Pending
  • [>] In Progress (blocked)

P0-1: Handle Cluster Config Push

  • #1 P0-1a: Add HostConfig + Cluster fields to models

    • models/clusters.go — Added HeartbeatInterval, Vcpus, InactiveHeartbeatCount to ClusterInfo
    • models/hosts.go — This task changed HostStateStr(0) from "OK" to "UNKNOWN"; commit d7afd72e ("fix front end issues") later reverted that branch, so HostStateStr(0) currently returns "OK" again
    • models/clusters_test.go — New: verifies new fields serialize + existing fields unchanged
    • models/hosts_test.go — New: verifies HostStateStr for zero, flags, non-flag, combined
    • All 15 tests passing
  • #2 P0-1b: Add pure Go conversion functions + TDD tests

    • backend/convert_pure.go — Added rawHostConfigData + rawHostConfigToModel(), rawClusterData + rawClusterToModel()
    • backend/convert_test.go — 8 new table-driven tests: zero-value ints, empty strings, normal values, worker/config-sourced field isolation
    • TODO(dispatchwindow) comment added per plan spec
    • DisptWindow guard test added to catch accidental future CGO layer changes
    • All 26 backend tests passing
  • #3 P0-1c: Add CGO conversion layer in convert.go

    • backend/convert.go — Added cHostConfigToModel(), cClusterConfHostConfigs(), cClusterConfToClusterInfo()
    • cResdefToModel intentionally skipped — xce_resdef_t doesn't exist in C codebase and ResourceInfo has no store/consumer (YAGNI); existing cResourceToModel → ResourceDefinitionInfo already handles config push
    • cClusterConfResources already existed — no change needed
    • CGO compilation verified passing
    • All unit tests still passing
  • #4 P0-1d: Implement handlers with partial merge + TDD

    • backend/notification.go — Added OnClusterUpdated(cluster *models.ClusterInfo) and OnHostConfigUpdated(host *models.HostInfo) to NotificationHandler interface
    • backend/handler.go — Implemented partial-merge OnClusterUpdated (preserves Version, Status, ControllerName, NumServers, Resources, HostTypes, HostModels, ClusterAdmins), OnHostConfigUpdated (preserves HostStatus, CPUFactor, NumCPUs, NumCores, NumThreads, MaxMem, MaxSwap, MaxTmp, NumDisk, NumRun, NumSSusp, NumUSusp, NumDone, Topology, SchedStop), fixed OnHostUpdated (preserves HostModel, HostType, MaxSlot, DisptWindow via two-value Get())
    • backend/handler_test.go — 6 new tests: new host, partial merge for each of OnHostConfigUpdated, OnClusterUpdated, OnHostUpdated
    • All backend tests passing (32 total)
  • #5 P0-1e: Expand handleConfigPush (unblocked)

    • backend/clib.go — Expand handleConfigPush() to call cClusterConfHostConfigs() and cClusterConfToClusterInfo()
    • Call gHandler.OnHostConfigUpdated() per host config, gHandler.OnClusterUpdated() for cluster settings

P0-2: Host Control via Backend

  • #6 P0-2a: C-side plumbing for host control

    • schema/controller.capnp — Added HostControl struct + hostctrlmsg @21
    • include/typemap.h — Added xce_hostctrl_t* hostctrlmsg; to body union (after @20 clrpreasonmsg, matching capnp ordinal)
    • include/client.h — Added xcecli_hostctrl() declaration
    • include/xceapi.h — Added xce_hostctrl() declaration
    • include/request.h — Added xce_hostctrl_req() declaration
    • lib/client.c — Implemented xcecli_hostctrl()
    • lib/xceapi.c — Implemented xce_hostctrl() with cbuf_get() wait (a later, unrelated repo-wide change converted this to cbuf_timedget() with a 10s deadline)
    • lib/request.c — Implemented xce_hostctrl_req() (validates HOST_OPEN/HOST_CLOSE only, rejects HOST_TAG/UNTAG)
    • lib/helper.c — Added Request_body_hostctrlmsg case to xce_request_body() + xce_request_msg_name()
    • controller/cluster.c — Added OPCode_hostcontrol case → do_hostcontrol_op()
    • controller/worker.c — Implemented do_hostcontrol_op() calling worker_ctrl(); fixed pre-existing goto clean bug that leaked write lock + reference count
    • controller/include/cluster.h — Declared do_hostcontrol_op()
    • lib/testsuite/test_request.c — 8 TDD validation tests (null ep/ctrl/hostname, empty hostname, HOST_DO_NONE no-op, HOST_TAG/UNTAG reject, negative action)
    • Regenerated capnp via ninja -C build
  • #7 P0-2b: Implement Go-side ControlHost + fix allFlag race

    • backend/clib.go — Replaced ControlHost() stub with real xcecli_hostctrl() call; follows ControlQueue pattern exactly
    • backend/control_host_test.go — New: stub signature + errNoCGO test (guarded //go:build !cgo)
    • controllers/hosts.go — Removed var allFlag bool from package scope; preCheckHostControlRequest now returns (bool, error); ControlHost uses hostActionMap with explicit !exists guard (mirrors ControlQueue pattern)
    • controllers/queues.go — preCheckQueueControlRequest now returns (bool, error); ControlQueue receives allFlag locally
    • controllers/host_control_test.go — 5 new tests: allFlag true/false, concurrent no-race (50 goroutines), invalid action, comment-too-long
    • controllers/queue_control_test.go — 5 new tests: same coverage for queues
    • All tests passing (make test)
  • #8 P0-2c: Register routes + RBAC for host control/select

    • router/routers.go — POST /xce/v1/hosts/control → RBAC host:control (cluster_admin)
    • router/routers.go — POST /xce/v1/hosts/select → RBAC host:view (all authenticated)
    • config/rbac.yaml — host:control and host:view action entries already present
    • controllers/rbac_check_test.go — 3 new TDD tests: TestRBAC_HostControl_ClusterAdminOnly, TestRBAC_HostView_BasicUserHasAccess, TestRBAC_HostControl_DomainTypeIsAll
    • All tests passing (controllers package)
  • #9 P0-2d: Update stub.go with new function stubs

    • backend/stub.go — Added StartHeartbeat(_ context.Context){}, SetHeartbeatInterval(_ int){}, EvalSelectForHost(_, _ string) error (returns errNoCGO), Cleanup(){}, added "context" to imports (SetHeartbeatInterval was later pulled out of stub.go/clib.go entirely into the shared, no-build-tag backend/heartbeat.go)
    • backend/stub_funcs_test.go — 4 TDD tests: TestStartHeartbeat_StubNoOp, TestSetHeartbeatInterval_StubNoOp (3 edge values), TestEvalSelectForHost_StubErrNoCGO, TestCleanup_StubNoOp
    • All backend tests passing

P1-1: Handle Resource Value Push

  • #10 P1-1: Handle resource value push (OPCode_notify)
    • backend/clib.go — Added 8 CGO val union helpers (xce_val_which, xce_val_i32, i64, u32, u64, fval, str, bool)
    • backend/clib.go — Added OPCode_notify case at top-level switch in go_push_handler() (NOT inside handlePush())
    • backend/clib.go — Added handleNotifyData() for NotifyData_data_schedUpdateResvals
    • backend/convert.go — Added cResvalToDistribution() — switches on Value_u_* constants, all 7 cases separate
    • backend/convert_pure.go — Added rawResvalData struct + rawResvalToDistribution() pure-Go version
    • backend/convert_test.go — 10 TDD tests covering all 7 value types, nil val, unknown discriminant, boolean false
    • All 42 backend tests passing (CGO_ENABLED=0 go test ./backend/ -v)

P1-2: Host Resource Requirement Select

Moved to src/docs/p1-2-host-select.md for deeper investigation. Open questions: PEG tooling availability, eval_select input contract, CGO error propagation.


P1-3: Heartbeat Keep-Alive

  • #13 P1-3: Heartbeat keep-alive implementation
    • backend/clib.go — Added heartbeatIntervalSecs int32 (default 30), SetHeartbeatInterval(), StartHeartbeat(ctx context.Context) goroutine with ticker (within the same P1-3 commits, heartbeatIntervalSecs/SetHeartbeatInterval()/the tick loop were extracted into the shared, no-build-tag backend/heartbeat.go for CGO-free testability; clib.go now passes an inline closure to runHeartbeat rather than a named heartbeatFn var)
    • backend/handler.go — OnClusterUpdated calls SetHeartbeatInterval(cluster.HeartbeatInterval) after store update (zero-preserve: skips if interval==0)
    • cmd/main.go — Calls backend.StartHeartbeat(ctx) after backend.RegisterToBackend(...)
    • backend/handler_test.go — Tests for heartbeat interval update, zero-preserve, timer leak, test drain, store consistency
    • Commits: ffc5b20 (goroutine), 0a3de8b (leak/drain/consistency fixes)

Final

  • #14 Build and test verification

    • make test in src/frontend/ passes — all backend, controllers, store, utils, xcecli tests green
    • ninja -C build for C components passes — required meson reconfigure + CGO val_helpers.h fix
    • RBAC verification — host:control (cluster_admin) and host:view (all authenticated) confirmed in routes + rbac.yaml
    • Input safety — comment limit 512 chars; select expression limit 4094 chars (1024 reduction deferred to P1-2b)
    • CGO fix applied: extracted static val helpers from clib.go preamble into val_helpers.h shared header; convert.go now includes it; added explicit float64() cast for C.double return
  • #15 Integration test suite — plan doc apiserver-backend-integration-test-plan.md was later removed from src/docs/ in an unrelated cleanup commit; see the test files below for current coverage

    • backend/integration_test.go — §1 (config push), §3 (resource values), §4 (heartbeat), §5 (cross-feature): 17 tests
    • controllers/integration_test.go — §2 (host control), §6 (RBAC), §8 (input safety): 17 tests + 1 skip (§8.1 pending P1-2b)
    • store/concurrency_test.go — §7 (thread safety): 3 concurrent-access tests
    • All use //go:build !cgo; run with CGO_ENABLED=0 go test ./backend/... ./controllers/... ./store/...
    • Commit: 86a65d6