Config reload, led by the partial reload: loading some of it and reporting success is the bug
- Status
- To do
- Component
- server
- Priority
- Medium
- Blocked by
- —
- Blocks
- SAPE-12
Description
Give the daemon a reload that re-reads its configuration without a restart, in the nginx shape: validate
the whole new configuration first, apply it only if all of it is valid, and keep the running
configuration untouched otherwise. The work is led by the failure case, not the success case — the
design starts from what happens when the third of five entries is bad.
Why now
The partial reload is the reason this is in 1.0.0 rather than after it. A reload that applies what it
can and reports success leaves the server in a state that matches neither the old configuration nor the
new one, and reports that state as correct. The operator then debugs against a file that is not what is
running. Building the naive version first and hardening it later means shipping that mode, and it is the
mode that produces wrong answers rather than errors.
Measured 2026-09-20. Greenfield: a case-insensitive search for reload across every
non-test .go file under internal/ and cmd/ returns nothing. There
is no reload to fix, which is why the order of construction is the decision this ticket is really
making — the all-or-nothing rule has to be the first thing built, not a later correction.
pipelines/tasks/0071 measured the adjacent question — how an external operation runs — and
confirms this ticket's own scope note: a declared operation already reloads without any of this
mechanism, over frame 13 (internal/server/declare.go:67), operator-only, no restart and no
SIGHUP. This ticket's reload is for the daemon's configuration file only; it does
not need to, and must not, grow to cover operations or collections, which already have their own live
path.
Acceptance criteria
- A reload with a valid configuration applies it, the server keeps serving, and open connections are
not dropped — asserted by a connection held across the reload that is still usable after.
- A configuration whose third of five entries is invalid applies none of the five.
After the failed reload, each of the other four is read back and matches the old value. This
is the test the ticket exists for.
- The failed reload returns a non-zero exit status and names the entry that was rejected and why.
Asserted on the message, so the diagnosis cannot decay to "reload failed".
- A reload that fails leaves a server that still answers. Asserted by invoking an operation
successfully after the failure.
- Repeated reloads of the same valid configuration are stable: the tenth leaves the server in the
state the first did, with no accumulation. Measured by comparing the readable configuration state, and
by the connection count not drifting.
Out of scope
- Reloading anything that changes the on-disk format or the listening socket. A new listen address is
a restart; pretending otherwise is a half-applied configuration by another name.
- Watching the configuration file and reloading on change. An explicit signal or command only —
automatic reload turns a saved half-edit into a live change.
- Config file format changes. Whatever is loaded at startup is what reload re-reads.
- Reloading declared operations or collections. Those arrive over frame 13 against a running server
and never needed a restart — see the note above.