Expand description
How long one request may take, and how many may be in flight at once (D71).
One middleware, bound, enforcing two limits. It is attached per route,
never to the merged app, and that is the whole of the streaming exemption:
GET /mcp and the API events route are registered on routers this layer is
not applied to.
So what is bounded follows from which sub-router a route is registered on,
not from a list of paths — but that is a weaker guarantee than “everything
new is bounded”, and worth stating exactly. The exempt routers are the outer
one in crate::router, which also carries /healthz and /readyz, and
the API’s streaming router. Adding a route beside the probes leaves it
unbounded, which is why router::bounded_routes pins the outer router’s
contents rather than trusting review to notice. A router’s fallback is not
covered either, route_layer not applying to one, so an unmatched path is
answered outside the cap: it bounds concurrent matched requests.
§What the limits measure
Both end when the inner service produces its response head, which is
the span crate::metrics times, for the same reason: a download that
takes minutes to transfer is the network’s time, not the server’s, and a
bound on the body would cut it short. The work worth bounding — a search’s
embedder call, a PROPFIND walk, a PATCH rewrite — all happens before the
head. How long a body may take to transfer is the proxy’s business.
§Why the cap refuses instead of queueing
A request that waits for a permit is still holding a connection and a task,
which is the resource the cap exists to protect. So it takes a permit or is
answered at once, with the same 503 and Retry-After every other capacity
refusal on this server gives (D38).
Structs§
- Request
Bounds - The two limits one route is held to.
Functions§
- bound
- Take a permit and run the request within its timeout, or refuse it.