Hand a replaced resource over to the process that replaces it (hq issue 213) #86

Merged
mesh-admin merged 1 commits from fix/issue-213-the-controller-is-a-process into main 2026-10-03 23:13:52 +00:00
Contributor

novox/hq issue 213: the controller moves from a container to a process on its one machine. Today every orphan is removed before anything is applied, so the container would go first and nothing would answer the mesh-controller seat while the process is fetched, unpacked and started — and nothing at all if it never starts.

Rebased onto main after #85. #85's oneshot unit for a run-once process is kept as it is; this PR adds only what #85 doesn't cover.

Changes

  • process.replaces. A process can name resources the declaration no longer declares. Such an orphan is not removed in the first pass. It is removed only after the replacing process applied and stayed up: active/running at two checks 10 s apart, with the same MainPID and no restart in between. This is stricter than ADR 0184's second check, which counts a crash-looping unit in activating/auto-restart as running.
  • When the replacement isn't up. If it failed, was skipped behind its module's step, or isn't up, the orphan keeps running and stays recorded. It is reported as kept, the apply fails and names it, and the next apply hands it over.
  • Refused: replacing something still declared, replacing itself, an empty id, one id named by two processes, and replaces on a step or a schedule.
  • Beyond #85:
    • A step written ./name runs its own bundle's binary, and is started, never enabled.
    • A failed run-once process now gates its module, as a run-once container already did.
    • An unchanged run-once process is no longer re-run on every apply.
    • An unchanged scheduled process is now kept up by its timer; before, every apply started its service.

Tests. New: internal/apply/handover_test.go and internal/declaration/replaces_test.go; they fail without the change. #85's process_step_test.go still passes, and go test ./... passes. The controller's composed declaration from mesh-controller #253 parses here (MESH_EMITTED).

Order. This must be live on the controller's machine before mesh-controller #253 is registered. A host without it refuses the whole declaration (unknown field replaces); that fails safe, since the container keeps running.

Genesis. internal/bootstrap step 9 is not changed here. See #253 for why that is not in this PR.

novox/hq issue 213: the controller moves from a container to a process on its one machine. Today every orphan is removed before anything is applied, so the container would go first and nothing would answer the mesh-controller seat while the process is fetched, unpacked and started — and nothing at all if it never starts. Rebased onto main after #85. #85's oneshot unit for a run-once process is kept as it is; this PR adds only what #85 doesn't cover. **Changes** - **`process.replaces`.** A process can name resources the declaration no longer declares. Such an orphan is not removed in the first pass. It is removed only after the replacing process applied and stayed up: `active/running` at two checks 10 s apart, with the same MainPID and no restart in between. This is stricter than ADR 0184's second check, which counts a crash-looping unit in `activating/auto-restart` as running. - **When the replacement isn't up.** If it failed, was skipped behind its module's step, or isn't up, the orphan keeps running and stays recorded. It is reported as `kept`, the apply fails and names it, and the next apply hands it over. - **Refused:** replacing something still declared, replacing itself, an empty id, one id named by two processes, and `replaces` on a step or a schedule. - **Beyond #85:** - A step written `./name` runs its own bundle's binary, and is started, never enabled. - A failed run-once process now gates its module, as a run-once container already did. - An unchanged run-once process is no longer re-run on every apply. - An unchanged scheduled process is now kept up by its timer; before, every apply started its service. **Tests.** New: `internal/apply/handover_test.go` and `internal/declaration/replaces_test.go`; they fail without the change. #85's `process_step_test.go` still passes, and `go test ./...` passes. The controller's composed declaration from mesh-controller #253 parses here (`MESH_EMITTED`). **Order.** This must be live on the controller's machine before mesh-controller #253 is registered. A host without it refuses the whole declaration (unknown field `replaces`); that fails safe, since the container keeps running. **Genesis.** `internal/bootstrap` step 9 is not changed here. See #253 for why that is not in this PR.
jschoubben added 1 commit 2026-10-03 23:01:55 +00:00
The controller moves from a container to a process on the one machine
that runs it (novox/hq issue 213). Every orphan is removed before anything
is applied, so the container would go first and nothing would answer the
mesh's verbs while the process was fetched, unpacked and started — and
never again, if it did not start.

- a process may say what it `replaces`: resources the declaration no
  longer declares. Such an orphan is kept through the up-front sweep and
  removed right after the process applied and is up: active and running
  at two looks ten seconds apart, the same main process, no restart in
  between (stricter than ADR 0184's second look, which reads a unit
  waiting to restart as running). If the process failed, was skipped
  behind its module's step, or is not running, the orphan stays running
  and recorded, reported kept, and the next apply hands it over.
  Refused: naming something still declared, itself, an empty id, one
  thing named by two processes, and `replaces` on a step or a schedule.
- beyond #85's oneshot unit for a step: a step written ./name runs its
  own bundle's binary (tested), and is started, never enabled.
- a run-once process that fails gates its module, as a run-once
  container already did, so a version whose preparation failed is not
  started.
- an unchanged run-once process is not run again, and an unchanged
  scheduled one is kept up by its timer: both were "a daemon that had
  stopped" and were started on every apply.
jschoubben force-pushed fix/issue-213-the-controller-is-a-process from 161ac1ff01 to 2ff3b50a84 2026-10-03 23:01:55 +00:00 Compare
mesh-admin merged commit 99ad145bec into main 2026-10-03 23:13:52 +00:00
mesh-admin deleted branch fix/issue-213-the-controller-is-a-process 2026-10-03 23:13:52 +00:00
Sign in to join this conversation.
No Reviewers
No labels
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: novox/mesh-host#86