manager: show job time left and ETA from the average completed frame time (closes #27) #30

Merged
linus merged 1 commit from ash/job-eta-27 into develop 2026-10-24 07:43:11 +00:00
Collaborator

Closes #27

Why

Job 1 on the trial (1308 frames at about 1m53s each) needed someone to dig through the logs to estimate its finish. The manager now shows it.

What changed

  • internal/manager/eta.go: computeJobTiming (pure) plus loadJobTiming (reads render tasks).
    • Average per frame = completed render task run time / frames those tasks covered (range tasks count every frame).
    • Retried or failed attempts don't count: a retry resets the task's started_at/completed_at, so only the final successful attempt is measured. Queued or paused time sits outside a task's run window.
    • Time left = average × frames left ÷ runners currently running the job's tasks (at least 1). Recomputed on every request, so it updates every time a frame finishes.
    • No estimate ("Estimating...") until one frame completes. Finished jobs show no time left.
  • API: GET /api/jobs, GET /api/jobs/{id} and the batch endpoint return eta_seconds, avg_frame_seconds and elapsed_seconds (whole seconds, omitted when unknown).
  • UI: the jobs list has a "Time left" column with the ETA clock. The job page shows time left, ETA, average per frame and elapsed, and refreshes them from its existing 2.5s job poll.

Testing

  • Hand-written; goimports -w on the touched Go files.
  • New tests: hand calculation (5 frames over 550s = 110s/frame, 5 left on 2 runners = 275s), "Estimating..." before the first frame, single-runner and finished jobs, a SQLite-backed loadJobTiming check (encode tasks excluded), and template render checks for the list and job page.
  • go test -count=1 ./... on the jumpbox: 201 tests passed. The one failure is TestIntegration_Encode_EXR_H264 in internal/runner/encoding, because the jumpbox has no ffmpeg. It fails the same way on develop and isn't touched here.
  • go test -race ./internal/manager ./pkg/types: ok.

Risks / rollback

One extra task query per job on the list/get endpoints (the list is capped at 50 jobs). The ETag for a running job changes each second because elapsed time moves. To roll back, revert this commit; there are no schema changes.

Closes #27 ## Why Job 1 on the trial (1308 frames at about 1m53s each) needed someone to dig through the logs to estimate its finish. The manager now shows it. ## What changed - `internal/manager/eta.go`: `computeJobTiming` (pure) plus `loadJobTiming` (reads render tasks). - Average per frame = completed render task run time / frames those tasks covered (range tasks count every frame). - Retried or failed attempts don't count: a retry resets the task's `started_at`/`completed_at`, so only the final successful attempt is measured. Queued or paused time sits outside a task's run window. - Time left = average × frames left ÷ runners currently running the job's tasks (at least 1). Recomputed on every request, so it updates every time a frame finishes. - No estimate ("Estimating...") until one frame completes. Finished jobs show no time left. - API: `GET /api/jobs`, `GET /api/jobs/{id}` and the batch endpoint return `eta_seconds`, `avg_frame_seconds` and `elapsed_seconds` (whole seconds, omitted when unknown). - UI: the jobs list has a "Time left" column with the ETA clock. The job page shows time left, ETA, average per frame and elapsed, and refreshes them from its existing 2.5s job poll. ## Testing - Hand-written; `goimports -w` on the touched Go files. - New tests: hand calculation (5 frames over 550s = 110s/frame, 5 left on 2 runners = 275s), "Estimating..." before the first frame, single-runner and finished jobs, a SQLite-backed `loadJobTiming` check (encode tasks excluded), and template render checks for the list and job page. - `go test -count=1 ./...` on the jumpbox: **201 tests passed**. The one failure is `TestIntegration_Encode_EXR_H264` in `internal/runner/encoding`, because the jumpbox has no `ffmpeg`. It fails the same way on develop and isn't touched here. - `go test -race ./internal/manager ./pkg/types`: ok. ## Risks / rollback One extra task query per job on the list/get endpoints (the list is capped at 50 jobs). The ETag for a running job changes each second because elapsed time moves. To roll back, revert this commit; there are no schema changes.
manager: show job time left and ETA from the average completed frame time (closes #27)
All checks were successful
CI / check-and-test (pull_request) Successful in 51s
0d58cb744a
ash requested review from eva 2026-10-24 07:39:04 +00:00
eva approved these changes 2026-10-24 07:41:17 +00:00
eva left a comment

GO. This matches #27: the average comes from completed render tasks only (range tasks count every frame, encode tasks are left out), time left divides by the runners busy on the job with a floor of 1, it shows "Estimating..." until a frame finishes, and finished jobs show no time left. The API carries eta_seconds, avg_frame_seconds and elapsed_seconds, and the list and job page both show it. Head 0d58cb7 sits on the develop tip, CI is green, and there's no schema change, so the revert is clean.

Two small things, neither blocking:

  • A task that is still "failed" counts toward frames left. That's right while it waits for a retry, but if a task fails for good the job keeps a slightly high estimate until the job itself stops. Fine to leave as is.
  • The issue's done line asks for the numbers to match a hand calculation on a real job. The unit tests cover the math; once this is deployed, someone should check one live job (frames done, average, time left) against the page.

The gofmt whitespace changes in jobs.go, ui.go and types.go are formatter-only.

GO. This matches #27: the average comes from completed render tasks only (range tasks count every frame, encode tasks are left out), time left divides by the runners busy on the job with a floor of 1, it shows "Estimating..." until a frame finishes, and finished jobs show no time left. The API carries eta_seconds, avg_frame_seconds and elapsed_seconds, and the list and job page both show it. Head 0d58cb7 sits on the develop tip, CI is green, and there's no schema change, so the revert is clean. Two small things, neither blocking: - A task that is still "failed" counts toward frames left. That's right while it waits for a retry, but if a task fails for good the job keeps a slightly high estimate until the job itself stops. Fine to leave as is. - The issue's done line asks for the numbers to match a hand calculation on a real job. The unit tests cover the math; once this is deployed, someone should check one live job (frames done, average, time left) against the page. The gofmt whitespace changes in jobs.go, ui.go and types.go are formatter-only.
linus merged commit 1a3f5bde3e into develop 2026-10-24 07:43:11 +00:00
linus deleted branch ash/job-eta-27 2026-10-24 07:43:11 +00:00
Sign in to join this conversation.
No reviewers
eva
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
s1d3sw1ped/jiggablend!30
No description provided.