@@ -150,71 +150,7 @@ function disconnect(connection: Connection): void {
150150 * @param options optional configuration object
151151 */
152152function set < TKey extends OnyxKey > ( key : TKey , value : OnyxSetInput < TKey > , options ?: SetOptions ) : Promise < void > {
153- // When we use Onyx.set to set a key we want to clear the current delta changes from Onyx.merge that were queued
154- // before the value was set. If Onyx.merge is currently reading the old value from storage, it will then not apply the changes.
155- if ( OnyxUtils . hasPendingMergeForKey ( key ) ) {
156- delete OnyxUtils . getMergeQueue ( ) [ key ] ;
157- }
158-
159- const skippableCollectionMemberIDs = OnyxUtils . getSkippableCollectionMemberIDs ( ) ;
160- if ( skippableCollectionMemberIDs . size ) {
161- try {
162- const [ , collectionMemberID ] = OnyxUtils . splitCollectionMemberKey ( key ) ;
163- if ( skippableCollectionMemberIDs . has ( collectionMemberID ) ) {
164- // The key is a skippable one, so we set the new value to null.
165- // eslint-disable-next-line no-param-reassign
166- value = null ;
167- }
168- } catch ( e ) {
169- // The key is not a collection one or something went wrong during split, so we proceed with the function's logic.
170- }
171- }
172-
173- // Onyx.set will ignore `undefined` values as inputs, therefore we can return early.
174- if ( value === undefined ) {
175- return Promise . resolve ( ) ;
176- }
177-
178- const existingValue = cache . get ( key , false ) ;
179- // If the existing value as well as the new value are null, we can return early.
180- if ( existingValue === undefined && value === null ) {
181- return Promise . resolve ( ) ;
182- }
183-
184- // Check if the value is compatible with the existing value in the storage
185- const { isCompatible, existingValueType, newValueType} = utils . checkCompatibilityWithExistingValue ( value , existingValue ) ;
186- if ( ! isCompatible ) {
187- Logger . logAlert ( logMessages . incompatibleUpdateAlert ( key , 'set' , existingValueType , newValueType ) ) ;
188- return Promise . resolve ( ) ;
189- }
190-
191- // If the change is null, we can just delete the key.
192- // Therefore, we don't need to further broadcast and update the value so we can return early.
193- if ( value === null ) {
194- OnyxUtils . remove ( key ) ;
195- OnyxUtils . logKeyRemoved ( OnyxUtils . METHOD . SET , key ) ;
196- return Promise . resolve ( ) ;
197- }
198-
199- const valueWithoutNestedNullValues = utils . removeNestedNullValues ( value ) as OnyxValue < TKey > ;
200- const hasChanged = options ?. skipCacheCheck ? true : cache . hasValueChanged ( key , valueWithoutNestedNullValues ) ;
201-
202- OnyxUtils . logKeyChanged ( OnyxUtils . METHOD . SET , key , value , hasChanged ) ;
203-
204- // This approach prioritizes fast UI changes without waiting for data to be stored in device storage.
205- const updatePromise = OnyxUtils . broadcastUpdate ( key , valueWithoutNestedNullValues , hasChanged ) ;
206-
207- // If the value has not changed or the key got removed, calling Storage.setItem() would be redundant and a waste of performance, so return early instead.
208- if ( ! hasChanged ) {
209- return updatePromise ;
210- }
211-
212- return Storage . setItem ( key , valueWithoutNestedNullValues )
213- . catch ( ( error ) => OnyxUtils . evictStorageAndRetry ( error , set , key , valueWithoutNestedNullValues ) )
214- . then ( ( ) => {
215- OnyxUtils . sendActionToDevTools ( OnyxUtils . METHOD . SET , key , valueWithoutNestedNullValues ) ;
216- return updatePromise ;
217- } ) ;
153+ return OnyxUtils . setWithRetry ( { key, value, options} ) ;
218154}
219155
220156/**
@@ -225,47 +161,7 @@ function set<TKey extends OnyxKey>(key: TKey, value: OnyxSetInput<TKey>, options
225161 * @param data object keyed by ONYXKEYS and the values to set
226162 */
227163function multiSet ( data : OnyxMultiSetInput ) : Promise < void > {
228- let newData = data ;
229-
230- const skippableCollectionMemberIDs = OnyxUtils . getSkippableCollectionMemberIDs ( ) ;
231- if ( skippableCollectionMemberIDs . size ) {
232- newData = Object . keys ( newData ) . reduce ( ( result : OnyxMultiSetInput , key ) => {
233- try {
234- const [ , collectionMemberID ] = OnyxUtils . splitCollectionMemberKey ( key ) ;
235- // If the collection member key is a skippable one we set its value to null.
236- // eslint-disable-next-line no-param-reassign
237- result [ key ] = ! skippableCollectionMemberIDs . has ( collectionMemberID ) ? newData [ key ] : null ;
238- } catch {
239- // The key is not a collection one or something went wrong during split, so we assign the data to result anyway.
240- // eslint-disable-next-line no-param-reassign
241- result [ key ] = newData [ key ] ;
242- }
243-
244- return result ;
245- } , { } ) ;
246- }
247-
248- const keyValuePairsToSet = OnyxUtils . prepareKeyValuePairsForStorage ( newData , true ) ;
249-
250- const updatePromises = keyValuePairsToSet . map ( ( [ key , value ] ) => {
251- // When we use multiSet to set a key we want to clear the current delta changes from Onyx.merge that were queued
252- // before the value was set. If Onyx.merge is currently reading the old value from storage, it will then not apply the changes.
253- if ( OnyxUtils . hasPendingMergeForKey ( key ) ) {
254- delete OnyxUtils . getMergeQueue ( ) [ key ] ;
255- }
256-
257- // Update cache and optimistically inform subscribers on the next tick
258- cache . set ( key , value ) ;
259- return OnyxUtils . scheduleSubscriberUpdate ( key , value ) ;
260- } ) ;
261-
262- return Storage . multiSet ( keyValuePairsToSet )
263- . catch ( ( error ) => OnyxUtils . evictStorageAndRetry ( error , multiSet , newData ) )
264- . then ( ( ) => {
265- OnyxUtils . sendActionToDevTools ( OnyxUtils . METHOD . MULTI_SET , undefined , newData ) ;
266- return Promise . all ( updatePromises ) ;
267- } )
268- . then ( ( ) => undefined ) ;
164+ return OnyxUtils . multiSetWithRetry ( data ) ;
269165}
270166
271167/**
@@ -374,7 +270,7 @@ function merge<TKey extends OnyxKey>(key: TKey, changes: OnyxMergeInput<TKey>):
374270 * @param collection Object collection keyed by individual collection member keys and values
375271 */
376272function mergeCollection < TKey extends CollectionKeyBase > ( collectionKey : TKey , collection : OnyxMergeCollectionInput < TKey > ) : Promise < void > {
377- return OnyxUtils . mergeCollectionWithPatches ( collectionKey , collection , undefined , true ) ;
273+ return OnyxUtils . mergeCollectionWithPatches ( { collectionKey, collection, isProcessingCollectionUpdate : true } ) ;
378274}
379275
380276/**
@@ -608,16 +504,16 @@ function update(data: OnyxUpdate[]): Promise<void> {
608504
609505 if ( ! utils . isEmptyObject ( batchedCollectionUpdates . merge ) ) {
610506 promises . push ( ( ) =>
611- OnyxUtils . mergeCollectionWithPatches (
507+ OnyxUtils . mergeCollectionWithPatches ( {
612508 collectionKey,
613- batchedCollectionUpdates . merge as OnyxMergeCollectionInput < OnyxKey > ,
614- batchedCollectionUpdates . mergeReplaceNullPatches ,
615- true ,
616- ) ,
509+ collection : batchedCollectionUpdates . merge as OnyxMergeCollectionInput < OnyxKey > ,
510+ mergeReplaceNullPatches : batchedCollectionUpdates . mergeReplaceNullPatches ,
511+ isProcessingCollectionUpdate : true ,
512+ } ) ,
617513 ) ;
618514 }
619515 if ( ! utils . isEmptyObject ( batchedCollectionUpdates . set ) ) {
620- promises . push ( ( ) => OnyxUtils . partialSetCollection ( collectionKey , batchedCollectionUpdates . set as OnyxSetCollectionInput < OnyxKey > ) ) ;
516+ promises . push ( ( ) => OnyxUtils . partialSetCollection ( { collectionKey, collection : batchedCollectionUpdates . set as OnyxSetCollectionInput < OnyxKey > } ) ) ;
621517 }
622518 } ) ;
623519
@@ -655,63 +551,7 @@ function update(data: OnyxUpdate[]): Promise<void> {
655551 * @param collection Object collection keyed by individual collection member keys and values
656552 */
657553function setCollection < TKey extends CollectionKeyBase > ( collectionKey : TKey , collection : OnyxSetCollectionInput < TKey > ) : Promise < void > {
658- let resultCollection : OnyxInputKeyValueMapping = collection ;
659- let resultCollectionKeys = Object . keys ( resultCollection ) ;
660-
661- // Confirm all the collection keys belong to the same parent
662- if ( ! OnyxUtils . doAllCollectionItemsBelongToSameParent ( collectionKey , resultCollectionKeys ) ) {
663- Logger . logAlert ( `setCollection called with keys that do not belong to the same parent ${ collectionKey } . Skipping this update.` ) ;
664- return Promise . resolve ( ) ;
665- }
666-
667- const skippableCollectionMemberIDs = OnyxUtils . getSkippableCollectionMemberIDs ( ) ;
668- if ( skippableCollectionMemberIDs . size ) {
669- resultCollection = resultCollectionKeys . reduce ( ( result : OnyxInputKeyValueMapping , key ) => {
670- try {
671- const [ , collectionMemberID ] = OnyxUtils . splitCollectionMemberKey ( key , collectionKey ) ;
672- // If the collection member key is a skippable one we set its value to null.
673- // eslint-disable-next-line no-param-reassign
674- result [ key ] = ! skippableCollectionMemberIDs . has ( collectionMemberID ) ? resultCollection [ key ] : null ;
675- } catch {
676- // Something went wrong during split, so we assign the data to result anyway.
677- // eslint-disable-next-line no-param-reassign
678- result [ key ] = resultCollection [ key ] ;
679- }
680-
681- return result ;
682- } , { } ) ;
683- }
684- resultCollectionKeys = Object . keys ( resultCollection ) ;
685-
686- return OnyxUtils . getAllKeys ( ) . then ( ( persistedKeys ) => {
687- const mutableCollection : OnyxInputKeyValueMapping = { ...resultCollection } ;
688-
689- persistedKeys . forEach ( ( key ) => {
690- if ( ! key . startsWith ( collectionKey ) ) {
691- return ;
692- }
693- if ( resultCollectionKeys . includes ( key ) ) {
694- return ;
695- }
696-
697- mutableCollection [ key ] = null ;
698- } ) ;
699-
700- const keyValuePairs = OnyxUtils . prepareKeyValuePairsForStorage ( mutableCollection , true , undefined , true ) ;
701- const previousCollection = OnyxUtils . getCachedCollection ( collectionKey ) ;
702-
703- // Preserve references for unchanged items in setCollection
704- const preservedCollection = OnyxUtils . preserveCollectionReferences ( keyValuePairs ) ;
705-
706- const updatePromise = OnyxUtils . scheduleNotifyCollectionSubscribers ( collectionKey , preservedCollection , previousCollection ) ;
707-
708- return Storage . multiSet ( keyValuePairs )
709- . catch ( ( error ) => OnyxUtils . evictStorageAndRetry ( error , setCollection , collectionKey , collection ) )
710- . then ( ( ) => {
711- OnyxUtils . sendActionToDevTools ( OnyxUtils . METHOD . SET_COLLECTION , undefined , mutableCollection ) ;
712- return updatePromise ;
713- } ) ;
714- } ) ;
554+ return OnyxUtils . setCollectionWithRetry ( { collectionKey, collection} ) ;
715555}
716556
717557const Onyx = {
0 commit comments