Repository navigation
[sgl-router] Fail fast and cancel decode when prefill fails - #41612
Merged
Merged
Conversation
This was referenced Sep 29, 2026
sherlockwu
added this pull request to stack #41614
September 29, 2026 01:49
sherlockwu
force-pushed
the
codex/pd-c-prefill-failfast
branch
from
September 29, 2026 04:32
3fa6702 to
3c5813d
Compare
sherlockwu
force-pushed
the
codex/pd-c-prefill-failfast
branch
from
September 29, 2026 05:00
3c5813d to
abdf910
Compare
sherlockwu
force-pushed
the
codex/pd-c-prefill-failfast
branch
from
September 29, 2026 05:37
abdf910 to
73149d7
Compare
sherlockwu
force-pushed
the
codex/pd-c-prefill-failfast
branch
from
October 1, 2026 02:11
9263d71 to
4c17013
Compare
ShangmingCai
force-pushed
the
codex/pd-c-prefill-failfast
branch
from
October 1, 2026 06:32
4c17013 to
82af055
Compare
…il-fast Charge a prefill 4xx/5xx/transport failure to the prefill worker's metrics instead of the cancelled decode, log the prefill URL for every failure, and drop the helper enum from forward_pd. Tests share one PD context helper and replace the closed-port trick with a truncated body. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A decode 429/5xx arrives as a response, not an error, so try_join! kept waiting on a prefill whose KV transfer can no longer complete, then replaced the decode status with 502. Treat any unsuccessful decode response as final, and name the PD outcome instead of nesting results in a tuple. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A router-initiated abort ends the stream as `aborted`: it counts as neither a client disconnect nor a breaker success, and leaves the engine abort armed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Decode's response is returned as soon as decode answers. A prefill failure before then is returned instead; one after aborts decode's stream until its first token. Router errors from prefill pass through unchanged, and prefill client errors and backpressure are forwarded verbatim; only a prefill fault becomes prefill_failed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The prefill task records its outcome on success and failure. The dispatch record stays on decode, except that a failure blamed on prefill is logged against prefill without charging decode. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A streaming prefill reports a failure after its 200 as a data: {"error"...}
event, which previously counted as success.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…g test setup Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ShangmingCai
force-pushed
the
codex/pd-c-prefill-failfast
branch
from
October 1, 2026 10:30
82af055 to
161da2f
Compare
When prefill is blamed, `record_dispatch_result` skipped `record_worker_request` entirely to avoid double-counting prefill, whose task books its own outcome. That also dropped decode, which had already reached the wire: `prefill_failure_aborts_decode_before_its_first_token` waits on decode's captured body before releasing the failure, and the request is then aborted on the engine by rid. So a dispatch that happened left no trace in `sgl_router_worker_requests_total`. That contradicts the metric's documented contract -- per-worker dispatches, "recorded after dispatch; blind to pre-dispatch drops" -- for a *post*-dispatch drop, and nothing else covers it: `stream_outcome_total` counts committed 2xx streams only, and before decode's headers there is no stream. Decode's dispatch counts therefore shrank during exactly the prefill incident an operator reads them to understand. Record the abandoned dispatch as `cancelled`, the outcome that already means "the router ended this itself, not the worker's fault". Carry the decision in `Blame` so it stays keyed to whether decode's future was ever polled: if prefill fails before that, nothing reached the worker and the drop stays uncounted, as the contract requires. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ShangmingCai
approved these changes
Oct 1, 2026
ShangmingCai
added a commit
that referenced
this pull request
Oct 1, 2026
Resolves ten conflicts left by #41610, #41611 and #41612 landing on main while this branch still carried their pre-squash commits. Two needed judgement rather than a side: - `readyz`: main gained the peer-bootstrap seed gate (#40699) while this branch rewrote the pool check for version groups. The hunks overlap, and taking either side whole drops the other, so the resolution keeps this branch's group-aware `pool_ready` *and* main's `&& ctx.kv_bootstrap_admit_ready()`. - `chat/forward.rs`: this branch carries #41612's pre-fix copy; main has the post-fix one. The version-group feature does not touch this file at all, so it takes main's version, keeping the `cancelled` outcome #41612 records for a decode dispatch that prefill's failure abandoned. - `pd_bootstrap_injection/reliability.rs` (add/add): keeps this branch's `..Default::default()` spec and main's two #41612 assertions. The rest are the mechanical `..Default::default()` churn this branch introduced meeting fields main spells out, plus a `readiness_rejects_portless_prefill` body git aligned against its own merged copy; resolved so each test and helper is defined once. Verified on the merge result: 1017 lib + 129 component + 157 proxy tests pass, clippy -D warnings and rustfmt clean. The two fixes a careless resolution would have reverted are covered by tests that still pass -- the five `pd_bootstrap_injection::reliability` cases and the four seed-gate `readyz` cases. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
15 of 40 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A failed prefill cannot supply KV to decode, but the router previously ignored the prefill failure and left the client waiting for decode's bootstrap timeout.
Modifications
errorevent) becomes 502prefill_failed.stream_outcome_total{outcome="aborted"}. Prefill is never aborted. Caller-supplied IDs and sample fan-out keep their existing opt-out from prefix-based abort.CI States
Latest PR Test (Base): ✅ Run #36851779946
Latest PR Test (Extra): ❌ Run #36851779649
Latest PR Test (AMD ROCm 10): ➖ No AMD PR run found for this commit.