2.6 KiB
2.6 KiB
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>/jobsshows all jobs for that server, newest first./jobs/<job_id>shows job metadata and live/replayed logs./admin/jobsreuses the same job table markup and links every job to its detail page.POST /jobs/<job_id>/cancelcancels 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
queuedjobs in this slice. - Cancelling a queued job sets
state="cancelled",finished_at,updated_at, andexit_code=1. - Append a
stderrjob-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 -qpytest l4d2web/tests/test_job_logs.py -qpytest l4d2web/tests -q
Slice 2: Running Job Cancellation
Behavior
- Running jobs expose the same cancel action.
- Cancelling a running job marks it
cancellingwhile 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
l4d2hostlifecycle APIs,l4d2web.services.l4d2_facade, andl4d2web.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 -qpytest l4d2host/tests -qpytest l4d2web/tests/test_job_worker.py -qpytest l4d2web/tests/test_job_logs.py -qpytest l4d2web/tests -q