Who owns this task, and what happens when nobody wants the answer?

Structured Concurrency & Cancellation

Child tasks with a clear lifetime, cancellation as a first-class concern rather than an afterthought, propagation to children, timeouts against deadlines, and the orphaned background task nobody is waiting for and nobody stops.

Structured Concurrency▶ lab

Child tasks belong to a scope, and the scope does not exit until every child has completed or been cancelled. The alternative — tasks that outlive the thing that started them — is how a request handler returns while three of its tasks are still writing to a response that is already closed.

Q · Who owns this task, and what is guaranteed to have happened to it by the time the function that started it returns?

Cancellation▶ lab

The user closed the tab. Should the database query still run? The HTTP call to the payment provider? The 40-second report generation? Cancellation is a first-class design question, and the uncomfortable answer is that in most runtimes a task that never checks is not cancelled — it is merely marked.

Q · When nobody wants this result any more, what should stop — and what actually will?

Cancellation Propagation▶ lab

Cancel the parent, cancel the children, clean up on the way out. The tree is easy to draw and hard to keep intact, because every layer that does not forward the signal is a subtree that keeps running — and because cancellation is cooperative, an arriving cancel is a request, not an event.

Q · When the root operation is cancelled, which of the twelve tasks it transitively started actually stop — and in what order does cleanup run?

Timeouts▶ lab

Start, wait, deadline exceeded, give up. The part almost everyone misses: a timeout without cancellation just stops waiting — the work keeps running, keeps its connection, and keeps its share of the CPU, while the caller has already retried.

Q · When this operation takes too long, what exactly happens — to the caller, and to the operation?

Deadlines vs Timeouts▶ lab

A timeout is a duration from now; a deadline is an instant. The difference only matters once there is a chain — and then it matters enormously, because a propagated deadline is how the fourth service in a call chain knows there are 40 milliseconds left rather than starting a fresh 2-second budget.

Q · Does each hop get its own fresh budget, or do they all share one that is already partly spent?

Orphaned Tasks

Fire-and-forget with no owner: nobody awaits it, nobody cancels it, and its exception is swallowed. The task runs, fails, and the only trace is a warning on a stream nobody reads — which is why this bug survives for months in code that looks completely ordinary.

Q · This task has no one waiting for it. Who stops it, who bounds it, and where does its exception go?