devshard: MLNode capacity is released before streaming response consumption #2180
The standalone inference engine releases the NodeManager slot before the caller consumes the MLNode response body, so a streaming response can still be generating after its slot becomes available again
Source evidence
Checked against the v6 candidate source
executeMLRequestpasseshttpClient.Doas the callback todoWithLockedNodedoWithLockedNodecallsreleaseNodeafter that callback returns, then returns the response to its caller- Streaming response processing happens afterwards in execute.go
- The passive fallback path also releases its local capacity reservation before returning the response
For a streaming response, receiving HTTP headers is not the end of generation, so this lifecycle does not bound active streaming work by max_concurrent
Expected behaviour
Keep the execution reservation until the response body reaches its terminal state or is closed, release exactly once on success, cancellation and failure, and define how upstream work that continues after client cancellation is accounted for
Reproduction to add
Use an ML endpoint that flushes response headers and one SSE chunk, then waits before completing the body, configure one available NodeManager slot and start a second inference while the first body is still open
Check the ordering of acquire, response headers, release and body completion, the second request must not acquire the same capacity before the first execution releases it
Repeat for the passive fallback path and for response-body read failures
Verification boundary
This report is based on source inspection, the isolated reproduction above has not been executed and the contribution to any particular deployment's overload has not been quantified
The finding is separate from gateway quarantine recovery and speed-up hedging amplification
🔄 Auto-synced from Issue #2180 every hour.