Goal
Evaluate and, if it remains appropriate after the shutdown overhaul is designed, replace the manual Vec<Job> task collection in JobManager with tokio::task::JoinSet<()> so the application has explicit ownership of its background tasks and can coordinate their completion and cancellation without nested task wrappers.
Background
JobManager currently stores named, already-spawned JoinHandle<()> values and awaits them sequentially with a timeout for each job. This has two important consequences:
- A job that consumes its full timeout delays observation of every handle after it, so total shutdown time can grow to the number of jobs multiplied by the grace period.
- Dropping a timed-out
JoinHandle detaches its task rather than aborting it.
tokio::task::JoinSet provides direct ownership, completion-order joining, and explicit cancellation for a dynamic set of tasks.
Design constraint
Keeping the current push(name, JoinHandle) API would require spawning a second task merely to await each existing handle. We should not introduce that nested-task design.
A sound implementation must revisit the boundary between JobManager and the background-job launchers so tracked futures are spawned directly into the JoinSet, while preserving the launchers' asynchronous startup handshakes and failure behaviour. Breaking and updating the current API is acceptable.
Relationship to the shutdown overhaul
This issue is a proposed future subissue of #1488. The EPIC and its subissues are still being reviewed in draft PR #1993.
Implementation is intentionally deferred until that review settles:
- which component owns background tasks and the
CancellationToken;
- whether shutdown uses one global deadline, phased deadlines, or another policy;
- how cooperative cancellation escalates for unfinished tasks; and
- what API preserves server startup guarantees while giving the task registry direct ownership.
Once the EPIC review is ready, re-scope this issue against the accepted architecture and add it as a subissue of #1488.
Acceptance direction
- The task registry owns tracked tasks directly through
JoinSet or an explicitly justified alternative.
- No task is spawned solely to await an already-spawned
JoinHandle for registration.
- Human-readable job names remain available in completion, panic, timeout, and cancellation logs.
- Tasks still running after cooperative shutdown are not silently detached.
- Focused tests cover completion order, panic reporting, deadline expiry, and cancellation.
Status
Specification only. Do not implement until the shutdown architecture in #1488 and draft PR #1993 has been finalized.
Goal
Evaluate and, if it remains appropriate after the shutdown overhaul is designed, replace the manual
Vec<Job>task collection inJobManagerwithtokio::task::JoinSet<()>so the application has explicit ownership of its background tasks and can coordinate their completion and cancellation without nested task wrappers.Background
JobManagercurrently stores named, already-spawnedJoinHandle<()>values and awaits them sequentially with a timeout for each job. This has two important consequences:JoinHandledetaches its task rather than aborting it.tokio::task::JoinSetprovides direct ownership, completion-order joining, and explicit cancellation for a dynamic set of tasks.Design constraint
Keeping the current
push(name, JoinHandle)API would require spawning a second task merely to await each existing handle. We should not introduce that nested-task design.A sound implementation must revisit the boundary between
JobManagerand the background-job launchers so tracked futures are spawned directly into theJoinSet, while preserving the launchers' asynchronous startup handshakes and failure behaviour. Breaking and updating the current API is acceptable.Relationship to the shutdown overhaul
This issue is a proposed future subissue of #1488. The EPIC and its subissues are still being reviewed in draft PR #1993.
Implementation is intentionally deferred until that review settles:
CancellationToken;Once the EPIC review is ready, re-scope this issue against the accepted architecture and add it as a subissue of #1488.
Acceptance direction
JoinSetor an explicitly justified alternative.JoinHandlefor registration.Status
Specification only. Do not implement until the shutdown architecture in #1488 and draft PR #1993 has been finalized.