Skip to content

Commit ac092b4

Browse files
arosiclairOSBotify
authored andcommitted
Merge pull request #41702 from Expensify/arosiclair-deferred-updates-loop
[CP Staging] Fix GetMissingOnyxMessages infinite loop when processing deferred updates (cherry picked from commit a2172a1)
1 parent a3035bf commit ac092b4

File tree

1 file changed

+14
-3
lines changed
  • src/libs/actions/OnyxUpdateManager/utils

1 file changed

+14
-3
lines changed

src/libs/actions/OnyxUpdateManager/utils/index.ts

+14-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import Onyx from 'react-native-onyx';
2+
import Log from '@libs/Log';
23
import * as App from '@userActions/App';
34
import type {DeferredUpdatesDictionary, DetectGapAndSplitResult} from '@userActions/OnyxUpdateManager/types';
45
import ONYXKEYS from '@src/ONYXKEYS';
@@ -76,9 +77,11 @@ function detectGapsAndSplit(updates: DeferredUpdatesDictionary, clientLastUpdate
7677

7778
// This function will check for gaps in the deferred updates and
7879
// apply the updates in order after the missing updates are fetched and applied
79-
function validateAndApplyDeferredUpdates(clientLastUpdateID?: number): Promise<void> {
80+
function validateAndApplyDeferredUpdates(clientLastUpdateID?: number, previousParams?: {newLastUpdateIDFromClient: number; latestMissingUpdateID: number}): Promise<void> {
8081
const lastUpdateIDFromClient = clientLastUpdateID ?? lastUpdateIDAppliedToClient ?? 0;
8182

83+
Log.info('[DeferredUpdates] Processing deferred updates', false, {lastUpdateIDFromClient, previousParams});
84+
8285
// We only want to apply deferred updates that are newer than the last update that was applied to the client.
8386
// At this point, the missing updates from "GetMissingOnyxUpdates" have been applied already, so we can safely filter out.
8487
const pendingDeferredUpdates = Object.entries(deferredUpdatesProxy.deferredUpdates).reduce<DeferredUpdatesDictionary>(
@@ -100,6 +103,8 @@ function validateAndApplyDeferredUpdates(clientLastUpdateID?: number): Promise<v
100103
// If we detected a gap in the deferred updates, only apply the deferred updates before the gap,
101104
// re-fetch the missing updates and then apply the remaining deferred updates after the gap
102105
if (latestMissingUpdateID) {
106+
Log.info('[DeferredUpdates] Gap detected in deferred updates', false, {lastUpdateIDFromClient, latestMissingUpdateID});
107+
103108
return new Promise((resolve, reject) => {
104109
deferredUpdatesProxy.deferredUpdates = {};
105110

@@ -115,15 +120,21 @@ function validateAndApplyDeferredUpdates(clientLastUpdateID?: number): Promise<v
115120

116121
// If lastUpdateIDAppliedToClient got updated in the meantime, we will just retrigger the validation and application of the current deferred updates.
117122
if (latestMissingUpdateID <= newLastUpdateIDFromClient) {
118-
validateAndApplyDeferredUpdates(clientLastUpdateID)
123+
validateAndApplyDeferredUpdates(undefined, {newLastUpdateIDFromClient, latestMissingUpdateID})
119124
.then(() => resolve(undefined))
120125
.catch(reject);
121126
return;
122127
}
123128

129+
// Prevent info loops of calls to GetMissingOnyxMessages
130+
if (previousParams?.newLastUpdateIDFromClient === newLastUpdateIDFromClient && previousParams?.latestMissingUpdateID === latestMissingUpdateID) {
131+
Log.info('[DeferredUpdates] Aborting call to GetMissingOnyxMessages, repeated params', false, {lastUpdateIDFromClient, latestMissingUpdateID, previousParams});
132+
return;
133+
}
134+
124135
// Then we can fetch the missing updates and apply them
125136
App.getMissingOnyxUpdates(newLastUpdateIDFromClient, latestMissingUpdateID)
126-
.then(() => validateAndApplyDeferredUpdates(clientLastUpdateID))
137+
.then(() => validateAndApplyDeferredUpdates(undefined, {newLastUpdateIDFromClient, latestMissingUpdateID}))
127138
.then(() => resolve(undefined))
128139
.catch(reject);
129140
});

0 commit comments

Comments
 (0)