Repository navigation
fix: keep Push connections consistent across concurrent subscribes and credential changes - #1948
Merged
ArnabChatterjee20k merged 31 commits intoSep 29, 2026
Conversation
…cribe is connecting
…er subscriptions on a failed connect
… other subscriptions on a failed connect
…d keep other subscriptions on a failed connect
Contributor
|
This comment has been minimized.
This comment has been minimized.
…ed tab picks its own
…laced client's disconnect
…ch while connecting
…ten the Apple checks
…res its sessionStorage
The tab id was claimed once per page and shared, so two Push instances alive at the same time connected with the same MQTT client id and took over each other's broker session. Now the first live connection takes the tab's stored id (stable across reloads, for replay) and any connection alive at the same time takes a distinct locked id, released on close so a later connection can reuse it.
Open two Push instances at the same time in one page and require the broker to report different client ids for them, alongside the existing reopen-resumes-same-id and popup-differs checks. The prior test closed one instance before opening the next, so it never exercised two live at once. Also close the disconnect-error Push before this block frees its id.
…ng it A credential switch could start a second open() while the first was still awaiting its client-id claim; both passed the empty-tabId check and claimed, and the loser overwrote this.tabId with its fallback, so the stored id it had claimed was never released and later connections could not resume its replay cursor. Memoize the claim per instance so concurrent opens share one, and release a claim that resolves after close().
Capture the generation before awaiting the claim and re-check it after, so a close() during a pending claim stops the open before it connects. Key the memoized claim by generation and chain a reopen's claim after the previous one settles and releases its id, so a close+reopen while a claim is pending takes the tab's stored id back instead of a fallback, and a claim resolving after its generation ended releases its id rather than stranding it.
The generated src/services/push.ts failed the web format:check because the memoized-claim guard exceeded prettier's print width. Wrap it as prettier formats it so the Build SDK step passes.
… duplicate (temporary)
…e sees a duplicate (temporary)" This reverts commit 09ed067.
ArnabChatterjee20k
merged commit Sep 29, 2026
31e0aa8
into
feat/rn-push-cookie-session
61 checks passed
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.
Stacked on #1947. Fixes the MQTT Push issues reported on appwrite/sdk-for-console#114 in the Web SDK, and the same issues in the other SDKs that have them. React Native got these fixes in #1947.
What was wrong
Fixes
Connects
connect()under a lock.Failed connects
Credential changes
close()never retries.Web client id
<userId>-<tabId>, with the tab id kept insessionStorage. It stays stable across reloads, so replay resumes, and differs per tab. An explicitsetPushClientId()still wins.Tests
PUSH_CREDENTIAL_SWITCH_RESPONSESis added to Web, Android (16 and 5), Flutter (stable, beta, web), Unity and Apple:Not changed
Session expiry interval. Appwrite's broker does not use MQTT sessions for offline replay. It keeps a ledger and a cursor per project, user and client id, replays from the cursor on SUBSCRIBE, and purges the cursor only on clean start. So
clean: falsewith a stable client id keeps the replay window; no session expiry is needed.Cleartext credentials over
ws://ormqtt://. The push endpoint follows the API endpoint's scheme, the same way Realtime sends the session overws://for anhttp://endpoint. A plain-text endpoint is a local-development setup the app chooses explicitly.Empty default client ids. Apple, Flutter iOS/desktop/web and Unity send an empty client id and let the broker derive one. Whether two devices of one user then collide depends on how the broker derives it.