diff --git a/src/libs/Network/SequentialQueue.ts b/src/libs/Network/SequentialQueue.ts index 223966f26a6f..c1c2b0946935 100644 --- a/src/libs/Network/SequentialQueue.ts +++ b/src/libs/Network/SequentialQueue.ts @@ -128,6 +128,12 @@ function process(): Promise { return currentRequestPromise; } +/** + * @param shouldResetPromise Determines whether the isReadyPromise should be reset. + * A READ request will wait until all the WRITE requests are done, using the isReadyPromise promise. + * Resetting can cause unresolved READ requests to hang if tied to the old promise, + * so some cases (e.g., unpausing) require skipping the reset to maintain proper behavior. + */ function flush(shouldResetPromise = true) { // When the queue is paused, return early. This will keep an requests in the queue and they will get flushed again when the queue is unpaused if (isQueuePaused) { @@ -198,6 +204,11 @@ function unpause() { const numberOfPersistedRequests = PersistedRequests.getAll().length || 0; Log.info(`[SequentialQueue] Unpausing the queue and flushing ${numberOfPersistedRequests} requests`); isQueuePaused = false; + + // When the queue is paused and then unpaused, we call flush which by defaults recreates the isReadyPromise. + // After all the WRITE requests are done, the isReadyPromise is resolved, but since it's a new instance of promise, + // the pending READ request never received the resolved callback. That's why we don't want to recreate + // the promise when unpausing the queue. flush(false); } diff --git a/tests/unit/APITest.ts b/tests/unit/APITest.ts index d34a07a9b16e..7c7182059bec 100644 --- a/tests/unit/APITest.ts +++ b/tests/unit/APITest.ts @@ -581,7 +581,7 @@ describe('APITests', () => { }); }); - test('Read request should not stuck when SequentialQueue is paused an resumed', async () => { + test('Read request should not stuck when SequentialQueue is paused and resumed', async () => { // Given 2 WRITE requests and 1 READ request where the first write request pauses the SequentialQueue const xhr = jest.spyOn(HttpUtils, 'xhr').mockResolvedValueOnce({previousUpdateID: 1}); API.write('MockWriteCommandOne' as WriteCommand, {});