[SDK-675] Restore offline queueing for disableDevice and registerDeviceToken - #1085
Draft
joaodordio wants to merge 2 commits into
Draft
[SDK-675] Restore offline queueing for disableDevice and registerDeviceToken#1085joaodordio wants to merge 2 commits into
joaodordio wants to merge 2 commits into
Conversation
…ceToken users/disableDevice was offline-queueable until 3.7.0, when it was removed from offlineApiSet for cross-SDK list parity. iOS later added queueing for it, Android never restored it, which left Android as the only SDK that silently drops a device disable made while the network is down. Adds both users/disableDevice and users/registerDeviceToken back to offlineApiSet. Register is queued alongside disable deliberately: the queue drains in scheduledAt order, so a logout-then-login sequence replays as disable-then-register and leaves the device enabled. Queueing the disable on its own would let a stale disable land after the new user registered and kill a live registration, because the backend merge is last-write-wins. A queued disable is also preserved across logout, via deleteAllTasksExcept, so it still reaches the user it was created for rather than being purged with the rest of the queue. Discarded tasks now settle their handlers instead of never calling back. The setEmail/setUserId completion handlers travel with the queued registerDeviceToken, so logging in as a different user used to strand them and an app dismissing a spinner in that callback would wait forever. The reset is identity-guarded so it only clears the handler pair the registration was created with, otherwise it would drop the incoming login's handlers. checkstyle: IterableApi.java sat at 1999 lines against the default 2000 cap, so any change touching it breaks the build. Suppressed for that one file rather than raising the global limit. The real split is tracked in SDK-677.
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
Restores offline queueing for
users/disableDevice, which regressed in 3.7.0, and addsusers/registerDeviceTokenalongside it so a logout-then-login replays in the right order.🎟️ Jira Ticket: SDK-675
📖 Description
users/disableDevicewas offline-queueable until 3.7.0, when it was removed fromofflineApiSetfor cross-SDK list parity. iOS later added queueing for it, Android never restored it. That left Android as the only SDK that silently drops a device disable made while the network is unavailable.This PR does four things.
Re-adds
users/disableDevicetoofflineApiSet. A disable made offline is persisted and retried instead of being dropped.Adds
users/registerDeviceTokenalongside it, deliberately. The offline queue drains inscheduledAtorder, so a logout-then-login sequence replays as disable-then-register and leaves the device enabled. Queueing the disable on its own would be worse than not queueing it at all: a stale disable could land after the new user had already registered and silently kill a live push registration, because the backend merge is last-write-wins. There is a guard test asserting the exact set membership in both directions so neither endpoint can be dropped without the test failing.One behaviour change worth calling out for reviewers: the offline queue only drains while the app is in the foreground, so a Firebase token refresh received in the background is now sent on the next foreground rather than immediately.
Preserves a queued disable across logout.
IterableTaskStorage.deleteAllTasksExcept(name)purges the queue but keeps tasks matching a resource path, andonLogoutnow uses it to keepusers/disableDevice. Without this, switching users would purge the disable before it could reach the user it was created for. The predicate isname IS NULL OR name != ?so it handles the nullablenamecolumn correctly, and it runs in a transaction so a task created between the query and the delete still gets settled.Settles the handlers of discarded tasks. A queued request that is thrown away now calls its failure handler instead of never calling back. This matters most for the completion handlers passed to
setEmailandsetUserId: they travel with the queuedusers/registerDeviceToken, so logging in as a different user used to strand them, and an app that dismisses a login spinner in that callback would wait forever. The failure reason states that the request was discarded because the user logged out.The reset is identity-guarded. It clears only the handler pair the registration was created with, because a registration outcome can arrive after the next
setEmailhas installed its own handlers. Clearing unconditionally would drop the incoming login's handlers and its callback would never fire.Checkstyle.
IterableApi.javasat at 1999 lines against the default 2000 line cap, so any change that has to touch it breaks the build. SuppressedFileLengthfor that one file rather than raising the global limit, which would make the rule meaningless everywhere else. The file needs a real split and that is tracked separately in SDK-677; the suppression should be deleted with it.🧪 How to test?
Unit tests cover all of it: 695 tests, 0 failures.
OfflineDisableDeviceQueueTestdrives the realdisablePush()path end to end: a disable made offline is queued, survives a logout, and is ordered before a subsequent register so the FIFO drain leaves the device enabled.OfflinePurgedRequestCallbackTestcovers the handler settling: a purged register fires its failure handler, a preserveddisableDevicekeeps its handlers,deleteAllTaskssettles everything, and the identity-guarded reset does not clobber a newer login's handlers.OfflineRequestProcessorTesthas the exactofflineApiSetmembership guard and the logout-preservation case.Manual check, if you want one: enable offline mode, put the device in airplane mode, call
disablePush(), then callsetEmailwith a different user. The disable should still be in the queue and should send on reconnect.🧾 Changelog
Added to
CHANGELOG.mdunder Unreleased / Fixed: three entries covering the restoreddisablePush()offline support, theregisterDeviceTokenqueueing with the foreground-drain note, and the discarded-request callback fix.📹 Loom recording if applicable
Not recorded.
🐞 Github Issues solved
None known.
📚 Docs PR if applicable
No public API change, so no docs PR. The behaviour change is that offline
disablePush()andregisterDeviceTokenare now retried rather than dropped, which restores documented 3.5.16 behaviour rather than introducing new behaviour.Note for reviewers: SDK-673, runtime project switching, is stacked on top of this branch and depends on it. Its "queued device disables survive the switch" behaviour is inert without the
offlineApiSetchange here.