Fix stale subscription client after auth mode change#956
Open
pistachiobaby wants to merge 1 commit intomainfrom
Open
Fix stale subscription client after auth mode change#956pistachiobaby wants to merge 1 commit intomainfrom
pistachiobaby wants to merge 1 commit intomainfrom
Conversation
resetClients() and close() disposed the baseSubscriptionClient without clearing the reference, so getBaseSubscriptionClient() would return the disposed client instead of creating a fresh one. This caused live queries to use a broken WebSocket client after any enableSessionMode() call, leading to unauthenticated or silently failing live subscriptions. Also adds test coverage for auth credentials in subscription connectionParams (API key, browser session, internal, custom, anonymous) which previously had zero coverage.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
resetClients()andclose()inGadgetConnectiondisposed the WebSocket subscription client without clearing thebaseSubscriptionClientreference. This causedgetBaseSubscriptionClient()to return a disposedgraphql-wsclient on subsequent calls instead of creating a fresh one — meaning live queries silently broke after anyenableSessionMode()call (auth refresh, switching to browser session auth, etc.).Also adds the first-ever test coverage for auth credentials in WebSocket
connectionParams, which previously had zero tests across all five auth modes.Architecture
Regular queries and live queries take completely different transport paths through
GadgetConnection:baseSubscriptionClientis lazily initialized —getBaseSubscriptionClient()creates it on first live query, then reuses it:The Bug: Dispose Without Clear
enableSessionMode()callsresetClients()to rebuild the urql pipeline with new auth. Before the fix:After reset,
getBaseSubscriptionClient()runs:The
graphql-wslibrary setsdisposed = trueinternally ondispose(). A disposed client:subscribe()still tries to open a WebSocket)if (disposed) return falsein retry logic)So live queries appear to work initially but silently die on the first network hiccup, with no reconnection.
Concrete Scenarios
1. Happy path (with fix) — Auth refresh re-establishes live queries
2. Failure mode (without fix) — Live queries go stale after auth change
3. Edge case —
close()had the same leakChanges
Bug fix:
packages/api-client-core/src/GadgetConnection.ts— ClearbaseSubscriptionClientreference after disposing in bothresetClients()andclose()Test coverage (previously zero for subscription auth):
packages/api-client-core/spec/GadgetConnection-suite.ts— 8 new tests:connectionParamstests (API key, browser session, internal, custom, anonymous)resetClientsclears reference, new client gets updated auth,close()clears reference)Test Plan
connectionParamstests pass (verify all 5 auth modes send correct credentials)GadgetConnectiontests pass (3 suites: browser, node, remote-ui)api-client-coretests passliveQueryExchangetests pass (7 tests)🤖 Generated with Claude Code