Skip to content

Bind WS handlers via local closure instead of ivars - #9

Merged
khasinski merged 1 commit into
khasinski:mainfrom
lucas-domeij:fix/ws-handler-context
May 26, 2026
Merged

khasinski merged 1 commit into
khasinski:mainfrom
lucas-domeij:fix/ws-handler-context

Conversation

@lucas-domeij

Copy link
Copy Markdown
Contributor

The on(:message), on(:close), and on(:error) blocks reference @mutex, @message_queue, and @connected. websocket-client-simple invokes these blocks with instance_exec, so those ivars resolve to fields on the underlying Client (all nil), not the gem's wrapper.

Effect: every incoming frame is silently dropped. #call hangs forever on queue.pop with no error, no log line, nothing.

Fix: capture self as a local owner so the handlers can call back into the wrapper, and move the close/message logic into small private helpers.

The mock MockWSClient in the spec was calling handlers with plain block.call, which is why the existing tests passed. Updated it to use instance_exec to match the real lib's behavior — that makes future regressions of this kind fail loudly.

Verified end-to-end against the live endpoint: streaming works, gpt-4.1-mini answers in about 1.2s, gpt-5 in about 4.4s.

websocket-client-simple invokes on() blocks with instance_exec, so when the
handlers reference @Mutex / @message_queue / @connected those resolve to ivars
on the underlying Client (which are nil) instead of the wrapper. Result: every
incoming frame is silently dropped and #call hangs forever on queue.pop with
no error.

Capture self as a local 'owner' and route close/message through small private
helpers so the handler bodies don't depend on what self is.

The mock client in the spec was calling handlers with plain block.call, which
hid the issue. Changed it to instance_exec to match the real lib.
@khasinski
khasinski merged commit 64fc6ea into khasinski:main May 26, 2026
4 of 5 checks passed
@khasinski

Copy link
Copy Markdown
Owner

Thank you @lucas-domeij for the careful diagnosis and the spec update that pins the contract. Merged in 64fc6ea.

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