chore: initialize from backend template 0a6dd0e
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
# Streaming and Large Bodies
|
||||
|
||||
## Response lifecycle
|
||||
|
||||
A blocking streaming download returns `BlockingStreamingResponse`, never a bare `InputStream`.
|
||||
Closing is idempotent and always releases the connection — after a full read, a partial read, a
|
||||
decode failure, or a size rejection. The status is validated before any body byte is delivered, so a
|
||||
failed download never becomes a half-consumed stream the caller has to reason about.
|
||||
|
||||
A reactive download emits bounded `DataBuffer` values. Buffers are released on completion, error,
|
||||
and cancellation; a dropped buffer is direct memory nobody returns.
|
||||
|
||||
Wire bytes and decoded bytes are bounded independently, because a compressed payload passes a wire
|
||||
check and then expands. Limits are enforced while reading, not after buffering.
|
||||
|
||||
## The first-byte boundary
|
||||
|
||||
```text
|
||||
response headers received
|
||||
→ nothing delivered yet
|
||||
→ a read-only operation may still be retried
|
||||
→ first InputStream read or first Flux onNext
|
||||
→ transparent retry is permanently disabled
|
||||
```
|
||||
|
||||
`FirstByteDeliveryGuard` latches once and never resets. Retrying after delivery would replay a
|
||||
stream the caller has already partly consumed, producing duplicated or reordered data that no
|
||||
downstream code can detect.
|
||||
|
||||
## Request bodies
|
||||
|
||||
A reopenable body is opened once per attempt, which is what makes it replayable; reusing the
|
||||
previous stream would silently send an empty body on the retry. A one-shot stream or publisher
|
||||
instance is never retried. `ReactiveBodySource` takes a publisher *factory* rather than a publisher
|
||||
so a reactive body can honestly declare itself replayable.
|
||||
|
||||
A multipart body is exactly as replayable as its weakest part.
|
||||
|
||||
## Server-sent events
|
||||
|
||||
Three budgets stay separate:
|
||||
|
||||
- `setupDeadline` — establishing the stream
|
||||
- `streamingIdleTimeout` — silence once it is open
|
||||
- `maxStreamDuration` — optional total lifetime
|
||||
|
||||
Applying the request-shaped `total-call` timeout to an SSE subscription would terminate a perfectly
|
||||
healthy stream on schedule, so it is not applied.
|
||||
|
||||
`Last-Event-ID` is opt-in. Replaying from an id is only correct when the producer guarantees it;
|
||||
sending it blindly can skip or duplicate events. Reconnects consume the retry budget like any other
|
||||
physical attempt, and cancelling the subscription stops both the stream and any pending reconnect.
|
||||
Reference in New Issue
Block a user