Skip to content

router: report a shed request as no_capacity after a full fleet - #2138

Merged
Krisztian F (krisztianfekete) merged 3 commits into
agent-substrate:mainfrom
JeffLuoo:fix/issue-2127-shed-request-no-capacity
Oct 7, 2026
Merged

Krisztian F (krisztianfekete) merged 3 commits into
agent-substrate:mainfrom
JeffLuoo:fix/issue-2127-shed-request-no-capacity

Conversation

@JeffLuoo

@JeffLuoo Jeff Luo (JeffLuoo) commented Oct 2, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes #2127.

The router reported a request that it shed from a full parking lot as unavailable, also when the resume failed with ResourceExhausted. Now such a request reports no_capacity on atenet.router.route.duration. A shed request with a different retry cause still reports unavailable. The response body to the client does not change.

A parked request whose budget elapsed under ResourceExhausted already reported no_capacity. This change makes a shed request agree with it.

Breaking change

On atenet.router.route.duration, requests shed from a full parking lot while ResumeActor retries on ResourceExhausted now report ate_router_outcome="no_capacity" instead of "unavailable". Use atenet.router.parking.rejected to count shed requests on their own.

Testing:

  • go test -race ./cmd/atenet/internal/router/... ./internal/ateattr/... passes.

  • TestHandleRequestHeaders_FullLotShedsParkedRequest fails without the fix (status.Code(err) = Unknown, want ResourceExhausted) and passes with it.

  • Tests pass

  • Appropriate changes to documentation are included in the PR

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, added some minor comments!

Comment thread docs/metrics/registry/metrics.yaml Resolved
Comment thread docs/request-parking.md Resolved
@JeffLuoo
Jeff Luo (JeffLuoo) force-pushed the fix/issue-2127-shed-request-no-capacity branch 2 times, most recently from 689c954 to 3dce99a Compare October 6, 2026 17:01
@JeffLuoo Jeff Luo (JeffLuoo) added area/observability kind/bug Something isn't working / bugfixes labels Oct 6, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, added a nit comment + a follow-up.

Comment thread docs/request-parking.md Outdated
full. On `atenet.router.route.duration`, a shed request reports `no_capacity`
when its resume failed with `ResourceExhausted`, and `unavailable` otherwise.
Because `no_capacity` combines fast shed requests with requests that waited
out the parking budget, use `atenet.router.parking.rejected` to count shed

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding ate.router.outcome to parking.rejected would let users split shed requests by cause and keep fast sheds out of the no_capacity latency. We can do this as a follow-up though.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in this PR. parking.rejected now has an ate.router.outcome label with the values no_capacity and unavailable. One helper, shedOutcome, picks the value for the label and for the error, so the label always agrees with the outcome.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you prefer a follow-up, I can revert and create an issue to track it.

The router sheds a request from a full parking lot only while the resume flight of its actor retries. The most frequent retry cause is ResourceExhausted, which means that no worker had room. The shed request did not keep that failure, so atenet.router.route.duration reported it as unavailable. The metric showed less capacity pressure than the actual value when the pressure was highest. A parked request whose budget elapsed under the same condition already reported no_capacity, so the two paths did not agree.

The flight now records its latest retryable failure. When that failure is ResourceExhausted, the shed request keeps it as the cause, and classifyOutcome reports no_capacity. The router drops other retry failures, because a shed request is not a lock conflict or a failed precondition. Those shed requests continue to report unavailable. The response body to the client does not change.

This changes what existing queries on atenet.router.route.duration with ate_router_outcome="no_capacity" and "unavailable" return.
A request that the router sheds from a full parking lot reports no_capacity or unavailable on atenet.router.route.duration. The parking.rejected counter had no labels, so it could not split shed requests by cause. Now it carries the same ate.router.outcome value as the route metric. A single helper, shedOutcome, picks that value for the counter and for the error, so the two always agree.

signalRetrying now takes the retry error and stores it before it closes retrying. A caller that sees retrying closed reads that error to pick its outcome. Before, the order depended on two separate calls at the call site, and no test caught a swap.
The flight stores its latest retry error for shed callers, and it does not clear it. flightResult reads a separate local copy that the retry loop clears on a non-retryable error. A NotFound that arrives after the budget elapses then reaches the client as NotFound, not as the earlier capacity error.
@JeffLuoo
Jeff Luo (JeffLuoo) force-pushed the fix/issue-2127-shed-request-no-capacity branch from 1453df7 to 9345a27 Compare October 7, 2026 14:39
@JeffLuoo

Copy link
Copy Markdown
Collaborator Author

Can you help add the change to merge queue? Thanks! Krisztian F (@krisztianfekete)

@krisztianfekete
Krisztian F (krisztianfekete) added this pull request to the merge queue Oct 7, 2026
Merged via the queue into agent-substrate:main with commit 858f354 Oct 7, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/network area/observability kind/bug Something isn't working / bugfixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The router reports a shed request as unavailable after a full fleet

3 participants