Skip to main content

Module bounds

Module bounds 

Source
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§

RequestBounds
The two limits one route is held to.

Functions§

bound
Take a permit and run the request within its timeout, or refuse it.