TypeScript SDK: route websocket errors on established connections to onDisconnect - #5707
Conversation
|
@bfops @JasonAtClockwork - Thanks for merging in my last PR. Another small but important one here. Could you please review and merge? |
JasonAtClockwork
left a comment
There was a problem hiding this comment.
Looks good overall, but it needs a small fix to ensure onDisconnect() receives the documented Error shape. It would also be good to add a small regression test for the new mid-stream error handling.
70fed09 to
3a4a906
Compare
|
I pulled the latest head
Command: pnpm --dir crates/bindings-typescript exec prettier src/sdk/db_connection_impl.ts --checkRunning Prettier changes only the |
JasonAtClockwork
left a comment
There was a problem hiding this comment.
Thanks for the update @sephirith!
…onDisconnect Fixes clockworklabs#5706. ws.onerror previously emitted connectError and disabled the send path for every websocket error, even mid-session, leaving the client silently stalled with no disconnect to trigger reconnect handling. Errors on an established connection now close the socket so the onclose path emits disconnect, with the error passed through per the documented onDisconnect contract. Pre-connect errors emit connectError as before. Also normalizes websocket errors to Error before emitting and adds a mid-stream regression test.
85f6046 to
46eeed1
Compare
|
@JasonAtClockwork - Just a reminder that this one still needs to be merged in. :) |
Created by `brew bump` --- Created with `brew bump-formula-pr`.<details> <summary>release notes</summary> <pre>## Features ### C# NativeAOT monomorphized dispatch Generated C# module exports now dispatch directly to statically-known generic entrypoints for reducers, procedures, HTTP handlers, views, and anonymous views when building with NativeAOT-LLVM. This eliminates virtual dispatch overhead at the module boundary and improves NativeAOT module performance. ([#5610](<clockworklabs/SpacetimeDB#5610>)) ### MCP support on Maincloud The SpacetimeDB MCP endpoint (`/v1/mcp`) is now available on Maincloud. You can connect AI agents and MCP-compatible tools directly to your Maincloud databases. This release also adds cluster-aware routing so that MCP requests sent to any node are automatically proxied to the leader replica, along with egress tracking for MCP tool calls. ([#5849](<clockworklabs/SpacetimeDB#5849>), [#5793](<clockworklabs/SpacetimeDB#5793>)) ## Bug Fixes ### TypeScript SDK: route mid-session websocket errors to onDisconnect The TypeScript SDK's `ws.onerror` handler previously treated every websocket error as a connection failure, even on established connections. This fired `onConnectError` instead of `onDisconnect`, silently disabled the outbound send path, and left the client in a stalled state with no reconnect. Mid-session errors now close the socket and fire `onDisconnect` with the error, allowing existing reconnect handling to take over. ([#5707](<clockworklabs/SpacetimeDB#5707>)) ### Fix C++ auto-increment macro symbol collisions C++ auto-increment field macros previously used `__LINE__` to generate symbols, causing collisions when two table definitions in separate files had an auto-increment field on the same line number. Macros now use table and field names to guarantee unique symbols. ([#5836](<clockworklabs/SpacetimeDB#5836>)) ### Fix `spacetime dev` C# complaint on macOS The `spacetime dev` command no longer incorrectly warns about C# on macOS when C# is not in use. ([#5867](<clockworklabs/SpacetimeDB#5867>)) ## What's Changed - Allow monomorphization for C# NativeAOT reducers, procedures, HTTP handlers, and views in [#5610](<clockworklabs/SpacetimeDB#5610>) - Add MCP request routing to leader replica in [#5849](<clockworklabs/SpacetimeDB#5849>) - Add egress tracking for MCP requests in [#5793](<clockworklabs/SpacetimeDB#5793>) - Route TypeScript SDK mid-session websocket errors to onDisconnect in [#5707](<clockworklabs/SpacetimeDB#5707>) - Fix C++ auto-increment macro symbol collisions in [#5836](<clockworklabs/SpacetimeDB#5836>) - Fix `spacetime dev` C# warning on macOS in [#5867](<clockworklabs/SpacetimeDB#5867>) **Full Changelog**: [v2.9.0...v2.10.0](<https://github.com/clockworklabs/SpacetimeDB/compare/v2.9.0...release/candidate/v2.10.0>)</pre> <p>View the full release notes at <a href="https://github.com/clockworklabs/SpacetimeDB/releases/tag/v2.10.0">https://github.com/clockworklabs/SpacetimeDB/releases/tag/v2.10.0</a>.</p> </details> <hr> --------- Co-authored-by: Anka <runner@sjc22-bm210-84d28139-e2f6-4b7c-92ee-6c21afdf23c2-32D5D422D197.local> Co-authored-by: jonahsnider[bot] <287348350+jonahsnider[bot]@users.noreply.github.com>
Description of Changes
Fixes #5706.
The TypeScript SDK's
ws.onerrorhandler treats every websocket error as a connect failure: it setsisActive = falseand emitsconnectError, even when the connection was already established. On an established connection this firesonConnectError(documented as a connect-time failure callback and commonly wired to boot-time auth recovery), silently disables the outbound send path while the socket may still beOPEN(reducer and procedure calls queue with no disconnect to trigger reconnect logic), and loses the error entirely ifoncloseeventually arrives, since thedisconnectemit carried no error argument.This change tracks whether the initial connection succeeded (
InitialConnectionreceived,onConnectinvoked). A websocket error after that point no longer emitsconnectError; instead the error is recorded and the socket is closed, so the existingonclosepath emitsdisconnectand every consumer's existing reconnect handling takes over. The recorded error is passed through to thedisconnectemit, which honors the documentedonDisconnectcontract ("If the connection ended because of an error, the error is passed to the callback"). Errors before the initial connection succeeds emitconnectErrorexactly as before.API and ABI breaking changes
None.
onDisconnectcallbacks already accept an optional error argument (error?: Error | undefined); passing the error is additive and matches the documented behavior. Pre-connectconnectErrorbehavior is unchanged.Expected complexity level and risk
1 - two private fields and a gate in one method. The only behavioral change is on a code path that previously produced a silently stalled connection routed to the wrong callback; it now produces a socket close, which flows through the disconnect handling every consumer already has.
Testing
npm testincrates/bindings-typescriptpasses (289 tests, 29 files).prettier --checkpasses on the changed file.spacetimedb@2.7.1): a mid-session websocket error previously fired ouronConnectErrorlogin-recovery path while reducer calls silently queued and no reconnect ran; with this routing the socket closes,onDisconnectfires with the error, and the client reconnects normally.