fix: address review findings for self-update (#15)

This commit is contained in:
2026-10-13 12:06:49 +02:00
parent fe4aca2883
commit aec21d23d9
25 changed files with 365 additions and 126 deletions
@@ -229,7 +229,7 @@ Online/offline is held in memory only.
| Master restarts mid-job | Jobs in `running` are reconciled when the agent reconnects; jobs the agent does not know are marked `failed` ("lost"). |
| New trigger while a job for the same service is queued or running | No new job; only `available_*` is updated. Two jobs never race on one service. |
| Job exceeds `UPDATE_TIMEOUT` | The agent cancels it, as today. |
| Agent updates itself | The old agent runs `up -d` in a helper container and waits. When the helper recreates the agent, the old agent is stopped and records nothing. The new agent finds the helper by its labels before it connects, so its hello lists the job; it reports the helper's outcome as the job's result. If the helper fails or the new agent never starts, the job stays `running` until the agent reconnects without it ("lost") or `UPDATE_TIMEOUT` ends the wait. |
| Agent updates itself | The old agent runs `up -d` in a helper container and waits. If the helper exits while the old agent still runs, the old agent reports the outcome. If the helper stops the old agent, the old agent records nothing; the new agent finds the helper by its labels before it connects, so its hello lists the job, and it reports the helper's outcome. If no new agent resumes the job, it is marked lost when the agent reconnects without it. If `UPDATE_TIMEOUT` passes first, the old agent reports a timeout and leaves the helper running; a later success is then not recorded. |
| Polling fails for one image | Error stored in `last_poll_error` and shown; other images continue. |
### Self-update
@@ -258,11 +258,17 @@ update itself").
- **Stopping.** When the agent is stopped (SIGTERM) while a job runs, the runner drops the
job and records no result, so a "context canceled" result cannot overtake the new
agent's.
- **Order.** `job.start` carries `self`; the agent runs a self job only when no other job
is queued (the master's job on a shared host has to finish first). Whether to use a
helper is decided by the agent from its own container ID, not from the flag.
- **Protocol 4.** The master routes a self job only to an agent speaking protocol 4
(`agent too old to update itself`).
- **Order.** `job.start` carries `self`; the agent runs a job for its own service only
when no other job is queued (the master's job on a shared host has to finish first).
The master starts such jobs after the other jobs of the same poll cycle or webhook
request; messages to one agent arrive in order, so the others are queued first. A job
that reaches an agent while it replaces itself is marked lost when the new agent
connects without it. Whether to use a helper is decided by the agent from its own
container ID, not from the flag.
- **Protocol 4.** The master routes a job for an agent's own service, and any job for a
service with the `AGENT_IMAGE` repo (an older agent does not report itself), only to an
agent speaking protocol 4 (`agent too old to update itself`). The helper runs on the
default network, so `DOCKER_HOST` must be a `docker.sock` bind mount.
## Registry polling