SDK-392 Fix Pending/Fulfill never resolving when auth retries exhausted#1056
Open
sumeruchat wants to merge 2 commits intomasterfrom
Open
SDK-392 Fix Pending/Fulfill never resolving when auth retries exhausted#1056sumeruchat wants to merge 2 commits intomasterfrom
sumeruchat wants to merge 2 commits intomasterfrom
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1056 +/- ##
==========================================
- Coverage 70.72% 70.65% -0.07%
==========================================
Files 112 112
Lines 9201 9215 +14
==========================================
+ Hits 6507 6511 +4
- Misses 2694 2704 +10 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
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.
What
Re-applies the fix from #1023 (which was reverted in #1025).
Fixes a bug where
RequestProcessorUtil.sendRequest()leaves itsresultFulfill permanently unresolved when a 401 JWT error triggers auth token retry and all retries are eventually exhausted. This causes any upstream caller chained on the Pending to hang indefinitely — including theIterableAPI.initialize2callback used by the React Native SDK.Reported by: CarGurus (SDK-392) —
Iterable.initialize()promise hangs on React Native New Architecture.Root Cause
When
sendRequest()receives a 401 JWT error, it schedules an auth token refresh viaAuthManager.scheduleAuthTokenRefreshTimerwith a callback that callsattemptSend()to retry the request. TheresultFulfill is only resolved insideattemptSend()on success or non-JWT error — it is never resolved in the 401-JWT branch itself.The retry chain eventually terminates when
AuthManager.requestNewAuthToken()detectsretryCount >= maxRetryand returns early at line 45 — but it does so without invoking theonSuccesscallback. This means:invokePendingCallbacksis never calledattemptSendcallback queued byRequestProcessorUtilis orphanedresultFulfill is never resolved (neither.resolve()nor.reject())Pendingchain upstream —fetcher.fetch()→inAppManager.start()→implementation.start()→initialize2callback — hangs foreverSimilarly,
scheduleAuthTokenRefreshTimersilently returns whenshouldSkipTokenRefreshis true (auth paused), dropping the callback without invoking it.Call chain (verified):
Changes
AuthManager.requestNewAuthToken: WhenshouldPauseRetryreturns true (retries exhausted or paused), invokeonSuccess?(nil)before returning so the caller chain is notified instead of silently abandoned.AuthManager.scheduleAuthTokenRefreshTimer: WhenshouldSkipTokenRefreshreturns true, invokesuccessCallback?(nil)before returning instead of dropping the callback.RequestProcessorUtil.sendRequest: Check the token in thescheduleAuthTokenRefreshTimercallback — ifnil(retries exhausted), callreportFailureto reject theresultFulfill instead of callingattemptSend()again.Regression Risk Analysis
Low risk
requestNewAuthTokenonly invokesonSuccess(nil)whenshouldPauseRetryis true — the happy path where a valid token is returned goes throughonAuthTokenReceived→invokePendingCallbacks(with: token)as before.RequestProcessorUtilonly callsreportFailurewhentokenis nil.reportFailureinRequestProcessorUtil.Medium risk — review carefully
shouldSkipTokenRefreshpath: WhenpauseAuthRetryis true and a non-scheduled refresh is requested, we now invoke the callback with nil. If any caller was scheduling a refresh while auth was paused and expecting it to simply be ignored (no callback), they will now receive a nil callback. Review callers ofscheduleAuthTokenRefreshTimerto confirm this is safe.scheduleAuthTokenRefreshTimercalled fromonAuthTokenReceived(nil)(line 204): When auth delegate returns nil,onAuthTokenReceivedschedules another refresh with the sameonSuccess. With this fix, if that refresh is skipped (e.g. retries paused),onSuccess(nil)is called, which propagates up toinvokePendingCallbacks(nil)→RequestProcessorUtilreports failure. Previously this would have silently stalled. Verify this matches expected behavior.Not affected
apply()method inRequestProcessorUtil(does not usescheduleAuthTokenRefreshTimer)Testing
How to test:
authDelegatethat always returns nil (simulating token retrieval failure)IterableAPI.initialize2(callback:)and verify the callback fires withfalseafter retries are exhausted (instead of hanging forever)trueEdge cases:
pauseAuthRetries(true)called during active retry cycle🤖 Generated with Claude Code