Skip to content

Commit 0aa010a

Browse files
krynjuclaude
andcommitted
fix(client): stream bytes as they arrive instead of filling an 8KB buffer
The streaming read loop used `readbytes!(io, buf)` with an 8KB buffer, which blocks until the buffer is completely full (or EOF). On a low-traffic stream — e.g. a mostly-idle Kubernetes watch — an event smaller than 8KB sits unflushed until enough *more* bytes arrive or the connection closes, stalling the consumer: a watch silently misses state transitions for minutes, until the apiserver drops the connection (surfacing as "Unexpected end of input"). Replace it with `readavailable(io)`, which returns whatever is currently buffered immediately and works on both HTTP.jl 1.x and 2.x streams. This restores the prompt delivery of the pre-0.2.3 `read(io, 8192)` loop (swapped out for HTTP 2.0 compatibility) without reintroducing the `read(io, n)` call that 2.0 streams don't support. Bumps to 0.2.6. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 39c46f6 commit 0aa010a

2 files changed

Lines changed: 15 additions & 7 deletions

File tree

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ keywords = ["Swagger", "OpenAPI", "REST"]
44
license = "MIT"
55
desc = "OpenAPI server and client helper for Julia"
66
authors = ["JuliaHub Inc."]
7-
version = "0.2.5"
7+
version = "0.2.6"
88

99
[deps]
1010
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"

src/client/httplibs/juliaweb_http.jl

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -317,13 +317,21 @@ function _http_streaming_request(ctx, method, url, headers, body, timeout, bytes
317317
write(io, body)
318318
captured_response[] = http_response = startread(io)
319319
try
320-
# `read(io, n)` is unavailable on 2.0 streams; read into a reusable
321-
# buffer with `readbytes!`, which works on both 1.x and 2.x.
322-
buf = Vector{UInt8}(undef, 8192) # 8KB chunks
320+
# Forward bytes to `output` as soon as they arrive.
321+
#
322+
# Use `readavailable`, NOT `readbytes!(io, buf)`: the latter
323+
# blocks until the whole buffer is filled (or EOF), so on a
324+
# low-traffic stream — e.g. a mostly-idle Kubernetes watch — a
325+
# single event smaller than the buffer sits unflushed until
326+
# enough *more* bytes arrive or the connection closes, stalling
327+
# the consumer (a watch would miss state transitions until the
328+
# apiserver eventually drops the connection). `readavailable`
329+
# returns whatever is currently buffered immediately and works
330+
# on both HTTP.jl 1.x and 2.x streams (`read(io, n)` does not).
323331
while !eof(io)
324-
n = readbytes!(io, buf)
325-
n == 0 && break
326-
bytesread[] += write(output, view(buf, 1:n))
332+
data = readavailable(io)
333+
isempty(data) && continue
334+
bytesread[] += write(output, data)
327335
end
328336
finally
329337
close(output)

0 commit comments

Comments
 (0)