Skip to content

fix(client): abort-on-close watcher busy-spins while events are pending#101

Merged
tanmaykm merged 1 commit into
mainfrom
kr/streaming-read-available
Jul 3, 2026
Merged

fix(client): abort-on-close watcher busy-spins while events are pending#101
tanmaykm merged 1 commit into
mainfrom
kr/streaming-read-available

Conversation

@krynju

@krynju krynju commented Jul 3, 2026

Copy link
Copy Markdown
Member

Repurposed — the original readbytes!readavailable change is dropped: on a real HTTP.Stream, readbytes! returns per-chunk (verified empirically), so the original premise was wrong.

Problem

The abort-on-close watcher introduced in #98:

while isopen(stream_to)
    wait(stream_to)
    yield()
end

wait(::Channel) returns as soon as data is available, not when the channel closes. So whenever an event has been put! but not yet consumed — e.g. the consumer is busy converting the previous event — this loop spins hot. Measured live on a k8s watch stream: 100% of a core in system time (wchan=0, running thread, 400 stime ticks per 4s) for as long as any event sat in the buffered channel.

Fix

Poll isopen with a 250ms sleep. The watcher exists only to abort the blocked read when the consumer closes the channel; 250ms of extra abort latency is irrelevant, and the loop now costs nothing while idle.

Found while diagnosing deaf k8s watches in JuliaHub's JobLoops (root cause was in Kuber.jl — see JuliaComputing/Kuber.jl#67 — but this spin was compounding it by starving the same thread pool).

Bumps to 0.2.6.

🤖 Generated with Claude Code

Comment thread src/client/httplibs/juliaweb_http.jl Outdated
Comment thread src/client/httplibs/juliaweb_http.jl Outdated
@krynju krynju marked this pull request as draft July 3, 2026 14:07
The watcher added in #98 waited with `wait(stream_to); yield()` in a loop.
`wait(::Channel)` returns as soon as data is *available*, so whenever an
event sits in the channel before the consumer takes it, the loop spins hot
— measured at 100% of a core in system time on a k8s watch stream. Poll
`isopen` with a 250ms sleep instead; the watcher only exists to abort the
read when the consumer walks away, so the added abort latency is irrelevant.

Bumps to 0.2.6.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@krynju krynju force-pushed the kr/streaming-read-available branch from 0aa010a to 013624c Compare July 3, 2026 14:45
@krynju krynju changed the title fix(client): stream watch bytes as they arrive instead of filling an 8KB buffer fix(client): abort-on-close watcher busy-spins while events are pending Jul 3, 2026
@krynju krynju marked this pull request as ready for review July 3, 2026 15:17
@krynju krynju requested a review from tanmaykm July 3, 2026 15:17
@tanmaykm tanmaykm merged commit 0270461 into main Jul 3, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants