pub struct StreamPolicy {
pub idle_timeout: Duration,
pub total_timeout: Duration,
pub max_bytes: usize,
}Expand description
Per-operation bounds on a streamed response body, attached to a
request as an extension and resolved by every implementation with
StreamPolicy::of_request, the way HttpPolicy is. All fields
clamp to the port maxima: a caller may only tighten.
The two timeouts divide the exchange along its one natural seam. The
head — status and headers, everything known before the first byte
of body — is bounded by HttpPolicy::timeout (at most 30 s,
unchanged), because an upstream that cannot even answer is dead in the
buffered world too. The body is bounded instead by
idle_timeout, the quiet gap between two chunks
(a model’s between-token pauses are normal; a stalled connection is
not), and by total_timeout, the whole body’s
ceiling measured from the head’s return. A body that streams steadily
for twenty minutes is legal here and impossible under the 30 s cap —
that is the feature, not a hole. Whichever bound ends the body names
itself: the HttpError::DeadlineExceeded carries the idle gap when
a quiet gap expired, and the whole-body ceiling when that is what the
exchange ran out of.
max_bytes is enforced chunk by chunk (and against
the declared Content-Length before the first chunk), the way the
buffered cap is enforced against the whole body at once.
§Cloudflare Workers
On the Workers runtime these bounds are what makes streaming survivable there at all, because the platform’s own limits shape what a streamed exchange may cost (the numbers move; the authoritative page is https://developers.cloudflare.com/workers/platform/limits/):
- There is no wall-clock limit on a request while the client stays connected, and time spent waiting on I/O does not count as CPU time — so a body that keeps arriving may legitimately run far past any CPU budget, and the port’s own idle and total ceilings are the only thing standing between a streaming caller and a connection the runtime would otherwise keep open indefinitely.
- Subrequests per invocation are capped — a few dozen on the Free plan and a great many more on paid plans when this port was written (50 / 1,000; the paid ceiling has since been raised and made configurable) — and every hop of a redirect chain counts as one. A retry loop over streamed responses spends the budget on the head, as the buffered port always has.
- At most 6 simultaneous open connections per invocation. A streamed exchange holds one of those six slots for its whole life, which under an idle-timeout-quota of minutes is a long time to hold a sixth of a request’s concurrency: the total ceiling exists to keep even a healthy stream from monopolising the pool.
Fields§
§idle_timeout: DurationLargest gap allowed between two body chunks before the body is declared stalled and abandoned.
total_timeout: DurationWhole-body ceiling, measured from the moment the head returned.
max_bytes: usizeMaximum accepted body size, enforced chunk by chunk.
Implementations§
Source§impl StreamPolicy
impl StreamPolicy
Sourcepub fn of_request<T>(request: &Request<T>) -> Self
pub fn of_request<T>(request: &Request<T>) -> Self
The effective policy for request: the attached StreamPolicy
extension if any, clamped to the port ceilings.
Sourcepub fn clamped(self) -> Self
pub fn clamped(self) -> Self
Clamps to MAX_STREAM_IDLE_TIMEOUT /
MAX_STREAM_TOTAL_TIMEOUT / MAX_STREAM_BYTES: callers may
lower a bound, never raise it.
Trait Implementations§
Source§impl Clone for StreamPolicy
impl Clone for StreamPolicy
impl Copy for StreamPolicy
Source§impl Debug for StreamPolicy
impl Debug for StreamPolicy
Source§impl Default for StreamPolicy
impl Default for StreamPolicy
impl Eq for StreamPolicy
Source§impl PartialEq for StreamPolicy
impl PartialEq for StreamPolicy
impl StructuralPartialEq for StreamPolicy
Auto Trait Implementations§
impl Freeze for StreamPolicy
impl RefUnwindSafe for StreamPolicy
impl Send for StreamPolicy
impl Sync for StreamPolicy
impl Unpin for StreamPolicy
impl UnsafeUnpin for StreamPolicy
impl UnwindSafe for StreamPolicy
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.