Cancellation: an event, not a clock — gRPC Context cancellation and RST_STREAM
A deadline fires from a clock ('time's up') while cancellation fires from an event ('never mind'); gRPC bundles both in one Context object so aborting a parent call propagates 'stop now' down the very same chain a deadline would.
The shrinking budget bar stopped zombie work when the clock ran out — but when the user closes the tab at 200ms no clock has expired, so we need a second trigger that says 'stop now' and rides the exact same propagation path.
Scene 06a
Cancellation: an event, not a clock
- Watch
- Try it
- Predict
- Capture
The chain is running greet("Ada") with a 10-second deadline — nearly all of it still on the clock. Earlier we learned a deadline propagates the remaining time so a slow downstream stops wasting effort once time runs out. But time hasn't run out here. Instead, the client decides to quit — imagine the user closing the tab. That decision is not a clock reading; it's a one-off event. gRPC reuses the RST_STREAM frame from the transport layer to signal it: the first thing the chain learns is that the caller said 'never mind'. We call this stop-now signal cancellation — a trigger that fires from an event rather than from elapsed time. Watch the cancel at 200ms ripple down A→B→C, flipping every hop from active to cancelled so all three servers abort their work mid-computation.
Highlighted lines are the ones running in the diagram right now.
def cancel(call):# fired by an EVENT (tab closed), not by elapsed timecall.stream.send(RST_STREAM) # HTTP/2 cancel framecall.ctx.cancel(reason = CANCELLED)
def handle(req, ctx):for step in work(req):if ctx.cancelled: # observed, not polled-on-a-clockreturn # abort mid-flight; nothing to replypartial = compute(step)# the downstream call inherits THIS ctxchild = stub.call(req, ctx = ctx)return assemble(partial)
def cancel(self, reason):self.cancelled = True# same path a deadline-expiry would walkfor child in self.children:child.cancel(reason) # propagate down A->B->C
Where this sits in Build a gRPC-style RPC framework
Scene 06a of 14, in the Reliability act — Deadlines, cancellation, retries, and the interceptor onion.. A deadline fires from a clock; cancellation fires from an event. Both ride one Context object down the chain, so aborting a parent stops all the doomed downstream work.
Up next. Stopping doomed work is half the reliability story; the other half is re-trying work that failed — but blind retries against a struggling service are how one slow backend becomes a self-sustaining outage.
All 14 scenes in Build a gRPC-style RPC framework · Every curriculum