fix(lib): anchor Slurm grace period to job start, not submission - #503
Conversation
`Service.refresh` measured the grace period from `self.created_at`, i.e. service submission time. On a busy cluster a job can sit `PENDING` well past the grace period and be marked `UNHEALTHY` before the container has begun loading. Queue time is unbounded, so no default is generous enough. Fetch the job's actual start time from Slurm accounting: `sacct` is already invoked on every refresh, so requesting `-o State,Start` instead of `-o State` adds no round-trips. Prefix with `TZ=UTC` so Slurm emits `Start` in UTC and we don't have to detect the cluster timezone. Store the parsed timestamp on the transient `SlurmJob.started_at`; fall back to `created_at` when `sacct` reports `Unknown` or fails to parse (this preserves prior behavior on the fallback path). The `PENDING` branch already avoids the grace period entirely, so this change is confined to the `RUNNING`/no-ping path. Local (Docker/Apptainer) path unchanged. Docker exposes an equivalent `State.StartedAt` via `docker inspect`; leaving that as a follow-up since there is no queue locally and the bug is far less acute. Closes #472
Review: fix(lib): anchor Slurm grace period to job start, not submissionNice fix for the underlying problem -- measuring the grace period from queue-submission time really was going to bite on any busy cluster, and anchoring to One correctness concern and a coverage gap worth addressing before merge: 1. Clock skew between the Slurm host and the Blackfish server can now trigger a false-immediate
|
…h tests - Compare grace period against `dt.total_seconds()` at both refresh sites so a service that has been running >24h isn't silently reset by `timedelta.seconds` wrapping (folds in the fix from #473). - `RemoteCommandError` strips the `env TZ=UTC` prefix when reporting the program name, so sacct failures surface as `'sacct' exited N` instead of `'env' exited N`. - New unit tests for `Service.refresh` covering STARTING->STARTING under grace and STARTING->UNHEALTHY over grace, using `job.started_at`.
Summary
Service.refreshmeasured the Slurm grace period fromself.created_at(service submission), so queue time counted against startup. A busy cluster could mark a serviceUNHEALTHYbefore the container had begun loading.SlurmJob.updatenow requests-o State,Start(prefixed withTZ=UTC) and stores the parsed timestamp onSlurmJob.started_at.Service.refreshmeasures the grace period fromjob.started_atwhen available, falling back tocreated_atonUnknown/parse failure. ThePENDINGbranch already skipped the grace period, so the change is confined to theRUNNING/no-ping path.docker inspect .State.StartedAtis a natural follow-up.Test plan
uv run just lintuv run just test(971 pass, 7 skipped — +9 new)PENDING/STARTINGfor the full model-load window rather than flipping toUNHEALTHYafter queue+grace.Follow-ups
docker inspect --format '{{.State.StartedAt}}'to populateLocalJob.started_at(analogous but separate mechanism).dt.seconds→dt.total_seconds()).Closes #472