Problem
When the network drops the response leg of a RequestMoney request (commonly when the OS suspends the App mid-stream on mobile, or any time the connection is interrupted after the request reaches the server), the App can't tell that the server actually saved the record. It assumes the request failed and retries. The retry hits the server's unique-constraint check and the server replies that the record already exists from the previous attempt.
Pre-fix, the SequentialQueue catch branch silently dropped that response: no successData or failureData was applied. The optimistic state stayed wedged with pendingAction: ADD and errors, surfacing in the UI as a "failed to upload" RBR — even though the server had actually saved the transaction. If the user then tapped "Delete expense," the existing local-only cleanup left the server-side transaction in place, which could produce duplicate expenses on the report.
Solution
When the App treats the response as already-created, the SequentialQueue catch branch now applies the request's successData + finallyData instead of silently dropping it, so optimistic state converges with server reality. A predicate-based queue-purge helper removes matching requests from the persisted queue without touching in-flight requests. cleanUpMoneyRequest gains an optional shouldEnsureServerCleanup flag that purges queued writes for the transactionID and enqueues a DELETE_MONEY_REQUEST for server-side cleanup. The receipt-discard handler passes shouldEnsureServerCleanup=true so dismissing a wedged receipt cleans up both the local queue and the server.
PR
#91601
Issue Owner
Current Issue Owner: @situchan
Upwork Automation - Do Not Edit
Problem
When the network drops the response leg of a
RequestMoneyrequest (commonly when the OS suspends the App mid-stream on mobile, or any time the connection is interrupted after the request reaches the server), the App can't tell that the server actually saved the record. It assumes the request failed and retries. The retry hits the server's unique-constraint check and the server replies that the record already exists from the previous attempt.Pre-fix, the SequentialQueue catch branch silently dropped that response: no
successDataorfailureDatawas applied. The optimistic state stayed wedged withpendingAction: ADDand errors, surfacing in the UI as a "failed to upload" RBR — even though the server had actually saved the transaction. If the user then tapped "Delete expense," the existing local-only cleanup left the server-side transaction in place, which could produce duplicate expenses on the report.Solution
When the App treats the response as already-created, the SequentialQueue catch branch now applies the request's
successData + finallyDatainstead of silently dropping it, so optimistic state converges with server reality. A predicate-based queue-purge helper removes matching requests from the persisted queue without touching in-flight requests.cleanUpMoneyRequestgains an optionalshouldEnsureServerCleanupflag that purges queued writes for thetransactionIDand enqueues aDELETE_MONEY_REQUESTfor server-side cleanup. The receipt-discard handler passesshouldEnsureServerCleanup=trueso dismissing a wedged receipt cleans up both the local queue and the server.PR
#91601
Issue Owner
Current Issue Owner: @situchanUpwork Automation - Do Not Edit