fix: [SDK-4874] single-flight UpdateSubscription to stop in-flight PATCH races#1689
Merged
Conversation
…TCH races Gate concurrent updates per subscription model, drain pending after completion, and clear sentToClient on retryable failure so the gate does not stick. Co-authored-by: Cursor <cursoragent@cursor.com>
Collaborator
|
The single-flight fix looks good overall. A few concerns:
Could we address or add coverage for these cases? |
Keep RYW token updates on the executor queue ahead of single-flight drain so chained PATCHes don't let an older token overwrite a newer one. Co-authored-by: Cursor <cursoragent@cursor.com>
Hold check and enqueue share one lock, and releaseHeldResponses clears the hold flag so in-flight test callbacks cannot be stranded. Co-authored-by: Cursor <cursoragent@cursor.com>
Contributor
Author
On retryable failure the new code only clears
RYW ordering is a nit, IAM only needs a “we have a subscription-update token for this onesignalId” to unblock, any successful PATCH’s token is enough. We can still clean it up for clarity.
This is valid, so we will fix it underr one lock: check flag + enqueue Pushed 2 commits to address (2) and (3) |
fadi-george
approved these changes
Jul 20, 2026
Merged
This was referenced Jul 21, 2026
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.
Description
One Line Summary
Serialize UpdateSubscription PATCHes per subscription so an in-flight stale
-19cannot race a later grant and leave users Never Subscribed.Details
Motivation
#1687 fixed the pending stale UpdateSubscription case by refreshing the PATCH body from the live model before send and coalescing unsent updates. A residual window remains: if a pre-permission update (
enabled: false,notification_types: -19) is already on the wire when the user accepts, a concurrent post-grant PATCH can reorder on the server and stick the subscription in Never Subscribed.This follow-up closes that window for the escalating SDK-4874 customer symptom. Related: SDK-4874.
Scope
OSRequestUpdateSubscriptionper subscription model; later updates stay queued (existing coalesce) and are drained after success or non-retryable failure.sentToClientso the single-flight gate does not block the model until app restart.MockOneSignalClientcan hold responses mid-flight.-19. Broader OperationRepo queue-safety refactor tracked separately in SDK-4892.Testing
Unit testing
Extended
SubscriptionUpdateRaceTests:-19blocks the grant follow-up until the first response completes, then sends live subscribed state.Ran
OneSignalUserTests/SubscriptionUpdateRaceTestslocally (all pass).Manual testing
Covered by unit tests with held mock responses. Full CI pending on this PR.
Affected code checklist
Checklist
Overview
Testing
SubscriptionUpdateRaceTestspass; full CI pending on this PR.Final pass
Made with Cursor