feat(service): add an opt-in supervisor backend for systemd-less hosts (#479) - #487
Merged
Conversation
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueThanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
A container whose PID 1 is tini has nothing to register autostart with, so `jaw service` could only hand back a manual recipe and every operator wrote the same loop by hand — the #479 reporter shipped an ensure-jaw.sh plus a 60s while-loop. `jaw service --backend supervisor` now generates that loop. Two details are load-bearing, and both came out of running the generated script rather than reading it: - Liveness is asked of `jaw service status`, which verifies the pidfile against the OS process start time. A pgrep-style check cannot see PID recycling, and the supervisor would then sit forever beside a dead server — the same false-healthy reading #479 is about. The supervisor branch's status therefore exits 1 when the server is down; systemd's status branch exits 0 either way, which a loop must not trust. - `setsid` is util-linux: absent on macOS and on minimal images. Running the loop showed every start failing with "command not found", so the supervisor started nothing at all. It is now probed once and `nohup` alone is used when it is missing. Verified by running the loop against a recorder stub: alive → 3 status queries and 0 starts; dead → a start every cycle with no errors logged; recovering → starts stop once liveness returns; SIGTERM → exits within one interval and logs why. detectBackend does not select this automatically. Writing a script and telling the operator where to wire it in is a different act from registering autostart, and implying otherwise would repeat the failure #479 reported. Refs #479
parkjs101
force-pushed
the
codex/479-supervisor-backend
branch
from
August 26, 2026 10:53
5208725 to
a1c97e8
Compare
parkjs101
force-pushed
the
codex/479-service-guidance
branch
from
August 26, 2026 10:53
0172cf6 to
419132d
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
jaw service --backend supervisorgenerates a keep-alive loop for hosts with no service manager (container with PID 1 = tini, no systemd). This is the layer that absorbs theensure-jaw.sh+ 60s while-loop the #479 reporter wrote by hand.Two load-bearing details, both found by running the script rather than reading it
1. Liveness must come from
jaw service status, notpgrep.service statusverifies the pidfile against the OS process start time, so a recycled PID reads as dead. A name-matching check cannot see PID recycling and would sit forever beside a dead server — the same false-healthy reading #479 is about. The supervisor branch'sstatustherefore exits 1 when the server is down; the systemd branch'sstatusexits 0 either way, which a loop must not trust.2.
setsidis util-linux — absent on macOS and minimal images.Running the loop showed every start failing with
setsid: command not found, i.e. the supervisor started nothing at all. It is now probed once, withnohupalone as the fallback.Behavioral verification
Ran the generated loop against a recorder stub:
Plus
sh -nsyntax validation (POSIX sh, not bash — minimal images ship dash).Scope note
detectBackend()does not select this automatically, and a test enforces that. Writing a script and telling the operator where to wire it in is a different act from registering autostart; implying otherwise would repeat the failure #479 reported.11 unit tests (
tests/unit/supervisor-service.test.ts),tsc --noEmitclean.Refs #479
Stack (merge bottom-up):
Review this PR's diff only; its base is the layer below.