C2(hephd-self-update): impl systemd Restart=always for clean-exit respawn

Self-restart works by exiting cleanly and letting the service manager
respawn the new binary. launchd already does this (KeepAlive=true), but
the systemd user unit was Restart=on-failure, which ignores a clean
exit (code 0). Switch to Restart=always + RestartSec=1, update the unit
test, and note in run-the-daemon that existing Linux installs must
`heph daemon restart` once to regenerate the unit.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erich Blume 2026-06-04 13:44:36 -07:00
commit 544c8bba0e
2 changed files with 13 additions and 3 deletions

View file

@ -168,7 +168,8 @@ fn systemd_unit(hephd: &Path, db: &Path, socket: &Path) -> String {
\n\
[Service]\n\
ExecStart={hephd} --mode local --db {db} --socket {socket}\n\
Restart=on-failure\n\
Restart=always\n\
RestartSec=1\n\
\n\
[Install]\n\
WantedBy=default.target\n",
@ -400,7 +401,11 @@ mod tests {
--db /home/e/.local/share/heph/heph.db \
--socket /run/user/1000/heph/hephd.sock"
));
assert!(unit.contains("Restart=on-failure"));
// Restart=always (not on-failure) so a clean exit (code 0) — what
// self-update does to hand off to the new binary — is respawned too.
assert!(unit.contains("Restart=always"));
assert!(!unit.contains("Restart=on-failure"));
assert!(unit.contains("RestartSec="));
assert!(unit.contains("WantedBy=default.target"));
}

View file

@ -28,9 +28,14 @@ when it's already stopped is fine.
`~/Library/LaunchAgents/org.hephaestus.hephd.plist`, with `RunAtLoad` +
`KeepAlive` (starts at login, restarts if it crashes).
- **Linux** — a **systemd user service** (`heph.service`) at
`~/.config/systemd/user/heph.service`, with `Restart=on-failure`, enabled for
`~/.config/systemd/user/heph.service`, with `Restart=always`, enabled for
login.
> **Upgrading from an older install:** earlier units used `Restart=on-failure`,
> which does **not** respawn after a clean exit — so opt-in self-update (which
> exits cleanly to hand off to the new binary) wouldn't come back on Linux. Run
> `heph daemon restart` once (it regenerates the unit) to pick up `Restart=always`.
Either way it runs `hephd --mode local` against the default store
(`~/.local/share/heph/heph.db`) and socket, with logs at
`~/.local/share/heph/hephd.log`.