-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathcom.pi-dispatch.worker.plist
More file actions
76 lines (63 loc) · 3.5 KB
/
Copy pathcom.pi-dispatch.worker.plist
File metadata and controls
76 lines (63 loc) · 3.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<!--
UNTESTED EXAMPLE: a starting point for the macOS (launchd) worker daemon, not a shipped, verified
unit. Adapt it. The Linux/systemd equivalent is deploy/worker.service.
ProgramArguments points at deploy/worker-env-wrapper.sh; that wrapper is what loads `.env`, because
launchd has no EnvironmentFile mechanism. The wrapper's contract (issue #96; see its header): it
sources ./.env from the WorkingDirectory below (which makes that key load-bearing, not a nicety)
and then runs the REST of ProgramArguments as the command. When hand-editing this template, append
the command after the wrapper path, e.g.
<string>/usr/bin/node</string>
<string>/opt/pi-dispatch/worker/src/cli.mjs</string>
<string>worker</string>
(`pi-dispatch service render` composes exactly that argv with this host's real paths; the wrapper
refuses an empty argv rather than guessing what to run). NO secrets are inlined here: there is
deliberately no EnvironmentVariables dict, since that would commit credentials into this file. The
wrapper reads `.env` at runtime instead (note the ANTHROPIC_OAUTH_TOKEN over ANTHROPIC_API_KEY
precedence trap documented in the wrapper).
Graceful shutdown needs NO macOS-specific code: `launchctl bootout` sends SIGTERM, which the wrapper
forwards to node (a trap + kill; its former `exec` is gone, see the wrapper's own comments), and the
worker drains in-flight work on SIGTERM. ExitTimeOut 30 gives it room (at least the 5s docker-stop
grace) before launchd escalates to SIGKILL.
KeepAlive restarts on a crash (SuccessfulExit false) but NOT on a clean exit, so a deliberate stop
stays stopped. KeepAlive cannot exclude a single exit code the way systemd's
RestartPreventExitStatus=2 and nssm's `AppExit 2 Exit` do, so the wrapper converts EXIT_POLICY
(exit 2, a determinate config/budget refusal) into a clean exit 0: a policy refusal stays stopped
instead of relaunch-looping against a paid provider.
Per-host PLACEHOLDERS: replace /opt/pi-dispatch (the deployment folder, used in ProgramArguments and
WorkingDirectory; the folder that holds your `.env`) and /opt/pi-dispatch/logs (StandardOutPath,
StandardErrorPath; create the directory yourself, launchd will not) with your paths, and append the
command argv to ProgramArguments as described above.
One worker per host (DES-CONCURRENCY-3): parallelism is PI_CONCURRENCY inside the one process.
Requires the AOF-enabled Valkey from deploy/docker-compose.yml.
PI_LOGS_DIR (run-history records; default OS-temp /pi-dispatch/logs) is created and written by the
worker at boot, so it must be writable by the account the daemon runs as. Set via `.env` (the wrapper),
not a plist change; its default is distinct from the StandardOutPath worker.out.log below.
-->
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.pi-dispatch.worker</string>
<key>ProgramArguments</key>
<array>
<string>/bin/sh</string>
<string>/opt/pi-dispatch/deploy/worker-env-wrapper.sh</string>
</array>
<key>WorkingDirectory</key>
<string>/opt/pi-dispatch</string>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<dict>
<key>SuccessfulExit</key>
<false/>
</dict>
<key>ExitTimeOut</key>
<integer>30</integer>
<key>StandardOutPath</key>
<string>/opt/pi-dispatch/logs/worker.out.log</string>
<key>StandardErrorPath</key>
<string>/opt/pi-dispatch/logs/worker.err.log</string>
</dict>
</plist>