64 lines
2.6 KiB
Markdown
64 lines
2.6 KiB
Markdown
# L4D2 Job Pages and Cancellation Follow-Up
|
|
|
|
## Goal
|
|
|
|
Make queued and running lifecycle jobs easier to inspect and stop from the web UI.
|
|
|
|
## Scope
|
|
|
|
- Add job list navigation for server pages and admin pages.
|
|
- Add a job detail page with persisted command logs streamed through the existing SSE endpoint.
|
|
- Add cancellation for queued jobs first.
|
|
- Add best-effort cancellation for running jobs by terminating the subprocess owned by `l4d2host.process.run_command()`.
|
|
|
|
## Slice 1: Job Browsing and Queued Cancel
|
|
|
|
### Behavior
|
|
|
|
- `/servers/<server_id>` shows recent jobs for that server and links to the full job history.
|
|
- `/servers/<server_id>/jobs` shows all jobs for that server, newest first.
|
|
- `/jobs/<job_id>` shows job metadata and live/replayed logs.
|
|
- `/admin/jobs` reuses the same job table markup and links every job to its detail page.
|
|
- `POST /jobs/<job_id>/cancel` cancels queued jobs only.
|
|
- Owners can view/cancel their own jobs.
|
|
- Admins can view/cancel any job.
|
|
|
|
### Implementation Notes
|
|
|
|
- Use one reusable Jinja partial for job tables.
|
|
- Show cancel buttons only for `queued` jobs in this slice.
|
|
- Cancelling a queued job sets `state="cancelled"`, `finished_at`, `updated_at`, and `exit_code=1`.
|
|
- Append a `stderr` job-log line explaining that the job was cancelled before execution.
|
|
- Do not revert `Server.desired_state`; cancellation prevents execution but is not rollback.
|
|
|
|
### Verification
|
|
|
|
- `pytest l4d2web/tests/test_pages.py -q`
|
|
- `pytest l4d2web/tests/test_job_logs.py -q`
|
|
- `pytest l4d2web/tests -q`
|
|
|
|
## Slice 2: Running Job Cancellation
|
|
|
|
### Behavior
|
|
|
|
- Running jobs expose the same cancel action.
|
|
- Cancelling a running job marks it `cancelling` while the subprocess is being terminated.
|
|
- Once the subprocess exits because of cancellation, the job finishes as `cancelled`.
|
|
- Cancellation is best-effort and is not rollback; partial runtime state may remain.
|
|
- Server actual state is refreshed after a cancelled server job when possible.
|
|
|
|
### Implementation Notes
|
|
|
|
- Add cancellation primitives in `l4d2host.process`.
|
|
- Launch subprocesses in their own process group/session when a cancel token is supplied.
|
|
- On cancellation, send terminate, wait briefly, then force kill.
|
|
- Thread the cancel token through `l4d2host` lifecycle APIs, `l4d2web.services.l4d2_facade`, and `l4d2web.services.job_worker`.
|
|
- Keep v1 single-process assumptions; cancellation requests are DB-backed, while process handles stay process-local.
|
|
|
|
### Verification
|
|
|
|
- `pytest l4d2host/tests/test_process.py -q`
|
|
- `pytest l4d2host/tests -q`
|
|
- `pytest l4d2web/tests/test_job_worker.py -q`
|
|
- `pytest l4d2web/tests/test_job_logs.py -q`
|
|
- `pytest l4d2web/tests -q`
|