Skip to content

router: report no_capacity only for a ResourceExhausted cause - #1929

Merged
Jeff Luo (JeffLuoo) merged 3 commits into
agent-substrate:mainfrom
ericcurtin:router-outcome-no-capacity
Oct 2, 2026
Merged

Jeff Luo (JeffLuoo) merged 3 commits into
agent-substrate:mainfrom
ericcurtin:router-outcome-no-capacity

Conversation

@ericcurtin

@ericcurtin Eric Curtin (ericcurtin) commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

Part of #1896.

Only report no_capacity for a wrapped ResourceExhausted cause. Other 503s are unavailable.

  • Tests pass
  • Appropriate changes to documentation are included in the PR

classifyOutcome sent every 503 with no gRPC cause to no_capacity,
so a full parking lot, a denied egress request, and a failed
policy or credential lookup all counted as fleet saturation. Only
report no_capacity when the cause actually carries
codes.ResourceExhausted; everything else falls back to
unavailable, matching what the registry already says the value
means.

Also move the outcome strings into named constants in ateattr,
next to the existing RouterResume ones, instead of scattering
literals across the switch.
Comment thread internal/ateattr/ateattr.go Outdated
// capacity problem, not a defect. Everything else that denies a request
// without a matching gRPC code, such as a full parking lot, a denied
// request, or a failed dependency lookup, is RouterOutcomeUnavailable or one
// of the other values below, never no_capacity.

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.

This comment says "the fleet having no free worker". A worker can now hold more than one actor, so "free worker" is not correct any more. #1895 removes this wording from the registry. Can you use the same words as the no_capacity brief?

Suggestion -

// Values for RouterOutcomeKey. RouterOutcomeNoCapacity means that no worker
// that meets the constraints of the actor had room. scheduling.ErrNoCapacity
// reports the same condition. It is a capacity signal, not a defect. A 503
// without a gRPC cause, such as a full parking lot, a denied egress request,
// or a failed policy lookup, is RouterOutcomeUnavailable.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done, thanks. Used your wording.

Match the no_capacity brief.
@ericcurtin

Copy link
Copy Markdown
Contributor Author

Jeff Luo (@JeffLuoo) Tim Bai (@baizhenyu) PTAL when you get a chance. Thank you!

@JeffLuoo Jeff Luo (JeffLuoo) left a comment

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 for the fix! Two requests:

  1. Please update the unavailable brief in https://github.com/agent-substrate/substrate/blob/main/docs/metrics/registry/metrics.yaml#L475. It now covers more than "a dependency was not available".
  2. #1896 also asks to change the "free worker" text in scheduling.go and workflow_resume. If that text and the parking lot change go in a follow-up, please change "Fixes #1896" to "Part of #1896".

Comment on lines +105 to +110
// The switch above already reports no_capacity for a wrapped
// ResourceExhausted cause, since status.Code unwraps through
// ReqError.Cause. A 503 that reaches here has no such cause: a
// full parking lot, a denied egress request, or a failed policy
// or credential lookup. None of these mean the fleet is full.
return ateattr.RouterOutcomeUnavailable

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.

A request that the router sheds because the parking lot is full now always reports unavailable. But the router sheds a request only after its resume failed, often with ResourceExhausted (a full fleet). I think that request report no_capacity.

parkingFullErr needs to keep the resume error as its Cause. That change is in the ingress code, outside this PR, so I am OK with a follow-up PR. unavailable is a safer default than no_capacity until then.

I will update the parent issue for reflect it and can you please change "Fixes #1896" to "Part of #1896" in your PR description?

It also covers a 503 without a gRPC cause.
@ericcurtin

Copy link
Copy Markdown
Contributor Author

Thanks Jeff Luo (@JeffLuoo). Updated the unavailable brief and set the description to Part of #1896. PTAL when you get a chance.

@JeffLuoo Jeff Luo (JeffLuoo) changed the title router: only report no_capacity for a full fleet router: report no_capacity only for a ResourceExhausted cause Oct 2, 2026
@JeffLuoo

Copy link
Copy Markdown
Collaborator

Thanks! I updated the title to make it clear on what we are changing in this PR.

@JeffLuoo
Jeff Luo (JeffLuoo) added this pull request to the merge queue Oct 2, 2026
Merged via the queue into agent-substrate:main with commit 1aa4b9b Oct 2, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants