Skip to content

shuffle: detect and fail a Session deadlocked on disk back-pressure - #3497

Open
williamhbaker wants to merge 5 commits into
masterfrom
wb/shuffle-disk-detector
Open

williamhbaker wants to merge 5 commits into
masterfrom
wb/shuffle-disk-detector

Conversation

@williamhbaker

@williamhbaker williamhbaker commented Sep 15, 2026

Copy link
Copy Markdown
Member

Description:

Disk back-pressure can deadlock a shuffle topology. A Log stops draining Appends once its sealed segments reach the disk limit. That space is reclaimed by Load scans, which shards run only after the coordinator takes a checkpoint, and a checkpoint needs a flush cycle the parked Log may never complete. The task then hangs until someone notices.

A known source of this deadlock condition is sealed segments that are pinned as remainders due to a dangling producer CONTINUE_TXN message that was never acknowledged. A large number of these segments can fill the buffer.

This adds a detector which fails the Session instead, so that shards restart from their last checkpoint and read the backlog down. Three new messages carry the state the Session cannot otherwise see: a Log reports its back-pressure flag to each Slice, a Slice reports whether it has any progress left to report, and the coordinator reports that its outstanding checkpoint is the only thing it waits on. The Session fails once all of these hold together for five minutes, which is long enough to cover the Log's reclaim poll of up to sixty seconds.

Agentic Q/A completed on a local stack, testing various shard configurations under deadlock scenarios.

Closes #3498

Workflow steps:

(How does one use this feature, and how has it changed)

Documentation links affected:

(list any documentation links that you created, or existing ones that you've identified as needing updates, along with a brief description)

Notes for reviewers:

(anything that might help someone review this PR)

@williamhbaker
williamhbaker force-pushed the wb/shuffle-disk-detector branch from 297851e to 9c8a00e Compare September 15, 2026 19:49
A Log stops draining Appends once its sealed segments reach the disk
limit. That space is reclaimed by `Load` scans, which shards run only
after the coordinator takes a checkpoint, and a checkpoint needs a flush
cycle the parked Log may never complete. Nothing then advances.

These messages let the Session observe that state. No actor sends or
handles them yet.
`BackPressureState` must also record the flag last sent to each Slice,
which is why the `serve` locals move into it.

`DiskBackPressure` carries the current flag rather than the transition,
so a Slice never sees a stale value, and a flag which engages and
releases between two drains sends nothing at all. A Slice records what it
is told and makes no use of it yet.
@williamhbaker
williamhbaker force-pushed the wb/shuffle-disk-detector branch from 9c8a00e to 3f8153d Compare September 15, 2026 20:11
Each condition of the detector is ordinary on its own. Together they mean
no shard will read, scan, or flush again, so the Log's disk backlog is
never reclaimed. Failing the Session restarts the shards from their last
checkpoint, which is the only way out.

`on_blocked` resets the count as the response arrives rather than at the
next tick, because a Slice can block and unblock within one tick
interval. `would_emit` repeats the emission test of `take_ready` and must
keep matching it.

Nothing sends `Blocked` or `CaughtUp` yet, so the detector cannot fire.
A Slice holding flushed progress is never blocked, because the Session
can still take a frontier from it. `try_slice_response_tx` therefore
recomputes `blocked` after it sends `Progressed`: taking the flushed
frontier is itself what can leave the Slice with nothing to report.

`is_blocked` needs the index of the Log which parked the request stream,
which is why the `Err` returns of the send helpers now carry it beside
the sender. That part is mechanical.
`Head::Idle` is where a leader parks between transactions: it holds no
ready frontier, waits on its checkpoint and nothing else, and no shard
will reclaim Log disk space until the Session answers. Every other head
state is driving IO of its own, so a leader in one hasn't yet exhausted
its own work.

A `CaughtUp` can cross its own frontier in flight, and the Session drops
one which names a request it has already answered. Capture leaders hold
no shuffle Session. This is the last input the detector needs.
@williamhbaker
williamhbaker force-pushed the wb/shuffle-disk-detector branch from 3f8153d to 6c34848 Compare September 15, 2026 20:25
@williamhbaker
williamhbaker requested a review from a team September 15, 2026 21:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

shuffle disk buffer deadlock detection

1 participant