react-native-onyx 3.0.11 → 3.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Onyx.js +11 -143
- package/dist/OnyxUtils.d.ts +57 -14
- package/dist/OnyxUtils.js +234 -18
- package/dist/types.d.ts +17 -1
- package/package.json +1 -1
package/dist/Onyx.js
CHANGED
|
@@ -145,62 +145,7 @@ function disconnect(connection) {
|
|
|
145
145
|
* @param options optional configuration object
|
|
146
146
|
*/
|
|
147
147
|
function set(key, value, options) {
|
|
148
|
-
|
|
149
|
-
// before the value was set. If Onyx.merge is currently reading the old value from storage, it will then not apply the changes.
|
|
150
|
-
if (OnyxUtils_1.default.hasPendingMergeForKey(key)) {
|
|
151
|
-
delete OnyxUtils_1.default.getMergeQueue()[key];
|
|
152
|
-
}
|
|
153
|
-
const skippableCollectionMemberIDs = OnyxUtils_1.default.getSkippableCollectionMemberIDs();
|
|
154
|
-
if (skippableCollectionMemberIDs.size) {
|
|
155
|
-
try {
|
|
156
|
-
const [, collectionMemberID] = OnyxUtils_1.default.splitCollectionMemberKey(key);
|
|
157
|
-
if (skippableCollectionMemberIDs.has(collectionMemberID)) {
|
|
158
|
-
// The key is a skippable one, so we set the new value to null.
|
|
159
|
-
// eslint-disable-next-line no-param-reassign
|
|
160
|
-
value = null;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
catch (e) {
|
|
164
|
-
// The key is not a collection one or something went wrong during split, so we proceed with the function's logic.
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
// Onyx.set will ignore `undefined` values as inputs, therefore we can return early.
|
|
168
|
-
if (value === undefined) {
|
|
169
|
-
return Promise.resolve();
|
|
170
|
-
}
|
|
171
|
-
const existingValue = OnyxCache_1.default.get(key, false);
|
|
172
|
-
// If the existing value as well as the new value are null, we can return early.
|
|
173
|
-
if (existingValue === undefined && value === null) {
|
|
174
|
-
return Promise.resolve();
|
|
175
|
-
}
|
|
176
|
-
// Check if the value is compatible with the existing value in the storage
|
|
177
|
-
const { isCompatible, existingValueType, newValueType } = utils_1.default.checkCompatibilityWithExistingValue(value, existingValue);
|
|
178
|
-
if (!isCompatible) {
|
|
179
|
-
Logger.logAlert(logMessages_1.default.incompatibleUpdateAlert(key, 'set', existingValueType, newValueType));
|
|
180
|
-
return Promise.resolve();
|
|
181
|
-
}
|
|
182
|
-
// If the change is null, we can just delete the key.
|
|
183
|
-
// Therefore, we don't need to further broadcast and update the value so we can return early.
|
|
184
|
-
if (value === null) {
|
|
185
|
-
OnyxUtils_1.default.remove(key);
|
|
186
|
-
OnyxUtils_1.default.logKeyRemoved(OnyxUtils_1.default.METHOD.SET, key);
|
|
187
|
-
return Promise.resolve();
|
|
188
|
-
}
|
|
189
|
-
const valueWithoutNestedNullValues = utils_1.default.removeNestedNullValues(value);
|
|
190
|
-
const hasChanged = (options === null || options === void 0 ? void 0 : options.skipCacheCheck) ? true : OnyxCache_1.default.hasValueChanged(key, valueWithoutNestedNullValues);
|
|
191
|
-
OnyxUtils_1.default.logKeyChanged(OnyxUtils_1.default.METHOD.SET, key, value, hasChanged);
|
|
192
|
-
// This approach prioritizes fast UI changes without waiting for data to be stored in device storage.
|
|
193
|
-
const updatePromise = OnyxUtils_1.default.broadcastUpdate(key, valueWithoutNestedNullValues, hasChanged);
|
|
194
|
-
// 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.
|
|
195
|
-
if (!hasChanged) {
|
|
196
|
-
return updatePromise;
|
|
197
|
-
}
|
|
198
|
-
return storage_1.default.setItem(key, valueWithoutNestedNullValues)
|
|
199
|
-
.catch((error) => OnyxUtils_1.default.evictStorageAndRetry(error, set, key, valueWithoutNestedNullValues))
|
|
200
|
-
.then(() => {
|
|
201
|
-
OnyxUtils_1.default.sendActionToDevTools(OnyxUtils_1.default.METHOD.SET, key, valueWithoutNestedNullValues);
|
|
202
|
-
return updatePromise;
|
|
203
|
-
});
|
|
148
|
+
return OnyxUtils_1.default.setWithRetry({ key, value, options });
|
|
204
149
|
}
|
|
205
150
|
/**
|
|
206
151
|
* Sets multiple keys and values
|
|
@@ -210,42 +155,7 @@ function set(key, value, options) {
|
|
|
210
155
|
* @param data object keyed by ONYXKEYS and the values to set
|
|
211
156
|
*/
|
|
212
157
|
function multiSet(data) {
|
|
213
|
-
|
|
214
|
-
const skippableCollectionMemberIDs = OnyxUtils_1.default.getSkippableCollectionMemberIDs();
|
|
215
|
-
if (skippableCollectionMemberIDs.size) {
|
|
216
|
-
newData = Object.keys(newData).reduce((result, key) => {
|
|
217
|
-
try {
|
|
218
|
-
const [, collectionMemberID] = OnyxUtils_1.default.splitCollectionMemberKey(key);
|
|
219
|
-
// If the collection member key is a skippable one we set its value to null.
|
|
220
|
-
// eslint-disable-next-line no-param-reassign
|
|
221
|
-
result[key] = !skippableCollectionMemberIDs.has(collectionMemberID) ? newData[key] : null;
|
|
222
|
-
}
|
|
223
|
-
catch (_a) {
|
|
224
|
-
// The key is not a collection one or something went wrong during split, so we assign the data to result anyway.
|
|
225
|
-
// eslint-disable-next-line no-param-reassign
|
|
226
|
-
result[key] = newData[key];
|
|
227
|
-
}
|
|
228
|
-
return result;
|
|
229
|
-
}, {});
|
|
230
|
-
}
|
|
231
|
-
const keyValuePairsToSet = OnyxUtils_1.default.prepareKeyValuePairsForStorage(newData, true);
|
|
232
|
-
const updatePromises = keyValuePairsToSet.map(([key, value]) => {
|
|
233
|
-
// When we use multiSet to set a key we want to clear the current delta changes from Onyx.merge that were queued
|
|
234
|
-
// before the value was set. If Onyx.merge is currently reading the old value from storage, it will then not apply the changes.
|
|
235
|
-
if (OnyxUtils_1.default.hasPendingMergeForKey(key)) {
|
|
236
|
-
delete OnyxUtils_1.default.getMergeQueue()[key];
|
|
237
|
-
}
|
|
238
|
-
// Update cache and optimistically inform subscribers on the next tick
|
|
239
|
-
OnyxCache_1.default.set(key, value);
|
|
240
|
-
return OnyxUtils_1.default.scheduleSubscriberUpdate(key, value);
|
|
241
|
-
});
|
|
242
|
-
return storage_1.default.multiSet(keyValuePairsToSet)
|
|
243
|
-
.catch((error) => OnyxUtils_1.default.evictStorageAndRetry(error, multiSet, newData))
|
|
244
|
-
.then(() => {
|
|
245
|
-
OnyxUtils_1.default.sendActionToDevTools(OnyxUtils_1.default.METHOD.MULTI_SET, undefined, newData);
|
|
246
|
-
return Promise.all(updatePromises);
|
|
247
|
-
})
|
|
248
|
-
.then(() => undefined);
|
|
158
|
+
return OnyxUtils_1.default.multiSetWithRetry(data);
|
|
249
159
|
}
|
|
250
160
|
/**
|
|
251
161
|
* Merge a new value into an existing value at a key.
|
|
@@ -344,7 +254,7 @@ function merge(key, changes) {
|
|
|
344
254
|
* @param collection Object collection keyed by individual collection member keys and values
|
|
345
255
|
*/
|
|
346
256
|
function mergeCollection(collectionKey, collection) {
|
|
347
|
-
return OnyxUtils_1.default.mergeCollectionWithPatches(collectionKey, collection,
|
|
257
|
+
return OnyxUtils_1.default.mergeCollectionWithPatches({ collectionKey, collection, isProcessingCollectionUpdate: true });
|
|
348
258
|
}
|
|
349
259
|
/**
|
|
350
260
|
* Clear out all the data in the store
|
|
@@ -553,10 +463,15 @@ function update(data) {
|
|
|
553
463
|
set: {},
|
|
554
464
|
});
|
|
555
465
|
if (!utils_1.default.isEmptyObject(batchedCollectionUpdates.merge)) {
|
|
556
|
-
promises.push(() => OnyxUtils_1.default.mergeCollectionWithPatches(
|
|
466
|
+
promises.push(() => OnyxUtils_1.default.mergeCollectionWithPatches({
|
|
467
|
+
collectionKey,
|
|
468
|
+
collection: batchedCollectionUpdates.merge,
|
|
469
|
+
mergeReplaceNullPatches: batchedCollectionUpdates.mergeReplaceNullPatches,
|
|
470
|
+
isProcessingCollectionUpdate: true,
|
|
471
|
+
}));
|
|
557
472
|
}
|
|
558
473
|
if (!utils_1.default.isEmptyObject(batchedCollectionUpdates.set)) {
|
|
559
|
-
promises.push(() => OnyxUtils_1.default.partialSetCollection(collectionKey, batchedCollectionUpdates.set));
|
|
474
|
+
promises.push(() => OnyxUtils_1.default.partialSetCollection({ collectionKey, collection: batchedCollectionUpdates.set }));
|
|
560
475
|
}
|
|
561
476
|
});
|
|
562
477
|
Object.entries(updateQueue).forEach(([key, operations]) => {
|
|
@@ -588,54 +503,7 @@ function update(data) {
|
|
|
588
503
|
* @param collection Object collection keyed by individual collection member keys and values
|
|
589
504
|
*/
|
|
590
505
|
function setCollection(collectionKey, collection) {
|
|
591
|
-
|
|
592
|
-
let resultCollectionKeys = Object.keys(resultCollection);
|
|
593
|
-
// Confirm all the collection keys belong to the same parent
|
|
594
|
-
if (!OnyxUtils_1.default.doAllCollectionItemsBelongToSameParent(collectionKey, resultCollectionKeys)) {
|
|
595
|
-
Logger.logAlert(`setCollection called with keys that do not belong to the same parent ${collectionKey}. Skipping this update.`);
|
|
596
|
-
return Promise.resolve();
|
|
597
|
-
}
|
|
598
|
-
const skippableCollectionMemberIDs = OnyxUtils_1.default.getSkippableCollectionMemberIDs();
|
|
599
|
-
if (skippableCollectionMemberIDs.size) {
|
|
600
|
-
resultCollection = resultCollectionKeys.reduce((result, key) => {
|
|
601
|
-
try {
|
|
602
|
-
const [, collectionMemberID] = OnyxUtils_1.default.splitCollectionMemberKey(key, collectionKey);
|
|
603
|
-
// If the collection member key is a skippable one we set its value to null.
|
|
604
|
-
// eslint-disable-next-line no-param-reassign
|
|
605
|
-
result[key] = !skippableCollectionMemberIDs.has(collectionMemberID) ? resultCollection[key] : null;
|
|
606
|
-
}
|
|
607
|
-
catch (_a) {
|
|
608
|
-
// Something went wrong during split, so we assign the data to result anyway.
|
|
609
|
-
// eslint-disable-next-line no-param-reassign
|
|
610
|
-
result[key] = resultCollection[key];
|
|
611
|
-
}
|
|
612
|
-
return result;
|
|
613
|
-
}, {});
|
|
614
|
-
}
|
|
615
|
-
resultCollectionKeys = Object.keys(resultCollection);
|
|
616
|
-
return OnyxUtils_1.default.getAllKeys().then((persistedKeys) => {
|
|
617
|
-
const mutableCollection = Object.assign({}, resultCollection);
|
|
618
|
-
persistedKeys.forEach((key) => {
|
|
619
|
-
if (!key.startsWith(collectionKey)) {
|
|
620
|
-
return;
|
|
621
|
-
}
|
|
622
|
-
if (resultCollectionKeys.includes(key)) {
|
|
623
|
-
return;
|
|
624
|
-
}
|
|
625
|
-
mutableCollection[key] = null;
|
|
626
|
-
});
|
|
627
|
-
const keyValuePairs = OnyxUtils_1.default.prepareKeyValuePairsForStorage(mutableCollection, true, undefined, true);
|
|
628
|
-
const previousCollection = OnyxUtils_1.default.getCachedCollection(collectionKey);
|
|
629
|
-
// Preserve references for unchanged items in setCollection
|
|
630
|
-
const preservedCollection = OnyxUtils_1.default.preserveCollectionReferences(keyValuePairs);
|
|
631
|
-
const updatePromise = OnyxUtils_1.default.scheduleNotifyCollectionSubscribers(collectionKey, preservedCollection, previousCollection);
|
|
632
|
-
return storage_1.default.multiSet(keyValuePairs)
|
|
633
|
-
.catch((error) => OnyxUtils_1.default.evictStorageAndRetry(error, setCollection, collectionKey, collection))
|
|
634
|
-
.then(() => {
|
|
635
|
-
OnyxUtils_1.default.sendActionToDevTools(OnyxUtils_1.default.METHOD.SET_COLLECTION, undefined, mutableCollection);
|
|
636
|
-
return updatePromise;
|
|
637
|
-
});
|
|
638
|
-
});
|
|
506
|
+
return OnyxUtils_1.default.setCollectionWithRetry({ collectionKey, collection });
|
|
639
507
|
}
|
|
640
508
|
const Onyx = {
|
|
641
509
|
METHOD: OnyxUtils_1.default.METHOD,
|
package/dist/OnyxUtils.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ValueOf } from 'type-fest';
|
|
2
2
|
import type Onyx from './Onyx';
|
|
3
|
-
import type { CollectionKey, CollectionKeyBase, ConnectOptions, DeepRecord, KeyValueMapping, CallbackToStateMapping, MultiMergeReplaceNullPatches, OnyxCollection, OnyxEntry, OnyxInput, OnyxInputKeyValueMapping, OnyxKey, OnyxMergeCollectionInput, OnyxUpdate, OnyxValue, Selector,
|
|
3
|
+
import type { CollectionKey, CollectionKeyBase, ConnectOptions, DeepRecord, KeyValueMapping, CallbackToStateMapping, MultiMergeReplaceNullPatches, OnyxCollection, OnyxEntry, OnyxInput, OnyxInputKeyValueMapping, OnyxKey, OnyxMergeCollectionInput, OnyxUpdate, OnyxValue, Selector, MergeCollectionWithPatchesParams, SetCollectionParams, SetParams, OnyxMultiSetInput, RetriableOnyxOperation } from './types';
|
|
4
4
|
import type { FastMergeResult } from './utils';
|
|
5
5
|
import type { DeferredTask } from './createDeferredTask';
|
|
6
6
|
import type { StorageKeyValuePair } from './storage/providers/types';
|
|
@@ -194,11 +194,12 @@ declare function scheduleNotifyCollectionSubscribers<TKey extends OnyxKey>(key:
|
|
|
194
194
|
declare function remove<TKey extends OnyxKey>(key: TKey, isProcessingCollectionUpdate?: boolean): Promise<void>;
|
|
195
195
|
declare function reportStorageQuota(): Promise<void>;
|
|
196
196
|
/**
|
|
197
|
-
*
|
|
198
|
-
*
|
|
199
|
-
*
|
|
197
|
+
* Handles storage operation failures based on the error type:
|
|
198
|
+
* - Storage capacity errors: evicts data and retries the operation
|
|
199
|
+
* - Invalid data errors: logs an alert and throws an error
|
|
200
|
+
* - Other errors: retries the operation
|
|
200
201
|
*/
|
|
201
|
-
declare function
|
|
202
|
+
declare function retryOperation<TMethod extends RetriableOnyxOperation>(error: Error, onyxMethod: TMethod, defaultParams: Parameters<TMethod>[0], retryAttempt: number | undefined): Promise<void>;
|
|
202
203
|
/**
|
|
203
204
|
* Notifies subscribers and writes current value to cache
|
|
204
205
|
*/
|
|
@@ -253,25 +254,64 @@ declare function subscribeToKey<TKey extends OnyxKey>(connectOptions: ConnectOpt
|
|
|
253
254
|
*/
|
|
254
255
|
declare function unsubscribeFromKey(subscriptionID: number): void;
|
|
255
256
|
declare function updateSnapshots(data: OnyxUpdate[], mergeFn: typeof Onyx.merge): Array<() => Promise<void>>;
|
|
257
|
+
/**
|
|
258
|
+
* Writes a value to our store with the given key.
|
|
259
|
+
* Serves as core implementation for `Onyx.set()` public function, the difference being
|
|
260
|
+
* that this internal function allows passing an additional `retryAttempt` parameter to retry on failure.
|
|
261
|
+
*
|
|
262
|
+
* @param params - set parameters
|
|
263
|
+
* @param params.key ONYXKEY to set
|
|
264
|
+
* @param params.value value to store
|
|
265
|
+
* @param params.options optional configuration object
|
|
266
|
+
* @param retryAttempt retry attempt
|
|
267
|
+
*/
|
|
268
|
+
declare function setWithRetry<TKey extends OnyxKey>({ key, value, options }: SetParams<TKey>, retryAttempt?: number): Promise<void>;
|
|
269
|
+
/**
|
|
270
|
+
* Sets multiple keys and values.
|
|
271
|
+
* Serves as core implementation for `Onyx.multiSet()` public function, the difference being
|
|
272
|
+
* that this internal function allows passing an additional `retryAttempt` parameter to retry on failure.
|
|
273
|
+
*
|
|
274
|
+
* @param data object keyed by ONYXKEYS and the values to set
|
|
275
|
+
* @param retryAttempt retry attempt
|
|
276
|
+
*/
|
|
277
|
+
declare function multiSetWithRetry(data: OnyxMultiSetInput, retryAttempt?: number): Promise<void>;
|
|
278
|
+
/**
|
|
279
|
+
* Sets a collection by replacing all existing collection members with new values.
|
|
280
|
+
* Any existing collection members not included in the new data will be removed.
|
|
281
|
+
* Serves as core implementation for `Onyx.setCollection()` public function, the difference being
|
|
282
|
+
* that this internal function allows passing an additional `retryAttempt` parameter to retry on failure.
|
|
283
|
+
*
|
|
284
|
+
* @param params - collection parameters
|
|
285
|
+
* @param params.collectionKey e.g. `ONYXKEYS.COLLECTION.REPORT`
|
|
286
|
+
* @param params.collection Object collection keyed by individual collection member keys and values
|
|
287
|
+
* @param retryAttempt retry attempt
|
|
288
|
+
*/
|
|
289
|
+
declare function setCollectionWithRetry<TKey extends CollectionKeyBase>({ collectionKey, collection }: SetCollectionParams<TKey>, retryAttempt?: number): Promise<void>;
|
|
256
290
|
/**
|
|
257
291
|
* Merges a collection based on their keys.
|
|
258
292
|
* Serves as core implementation for `Onyx.mergeCollection()` public function, the difference being
|
|
259
|
-
* that this internal function allows passing an additional `mergeReplaceNullPatches` parameter.
|
|
293
|
+
* that this internal function allows passing an additional `mergeReplaceNullPatches` parameter and retries on failure.
|
|
260
294
|
*
|
|
261
|
-
* @param
|
|
262
|
-
* @param
|
|
263
|
-
* @param
|
|
295
|
+
* @param params - mergeCollection parameters
|
|
296
|
+
* @param params.collectionKey e.g. `ONYXKEYS.COLLECTION.REPORT`
|
|
297
|
+
* @param params.collection Object collection keyed by individual collection member keys and values
|
|
298
|
+
* @param params.mergeReplaceNullPatches Record where the key is a collection member key and the value is a list of
|
|
264
299
|
* tuples that we'll use to replace the nested objects of that collection member record with something else.
|
|
300
|
+
* @param params.isProcessingCollectionUpdate whether this is part of a collection update operation.
|
|
301
|
+
* @param retryAttempt retry attempt
|
|
265
302
|
*/
|
|
266
|
-
declare function mergeCollectionWithPatches<TKey extends CollectionKeyBase>(collectionKey
|
|
303
|
+
declare function mergeCollectionWithPatches<TKey extends CollectionKeyBase>({ collectionKey, collection, mergeReplaceNullPatches, isProcessingCollectionUpdate }: MergeCollectionWithPatchesParams<TKey>, retryAttempt?: number): Promise<void>;
|
|
267
304
|
/**
|
|
268
305
|
* Sets keys in a collection by replacing all targeted collection members with new values.
|
|
269
306
|
* Any existing collection members not included in the new data will not be removed.
|
|
307
|
+
* Retries on failure.
|
|
270
308
|
*
|
|
271
|
-
* @param
|
|
272
|
-
* @param
|
|
309
|
+
* @param params - collection parameters
|
|
310
|
+
* @param params.collectionKey e.g. `ONYXKEYS.COLLECTION.REPORT`
|
|
311
|
+
* @param params.collection Object collection keyed by individual collection member keys and values
|
|
312
|
+
* @param retryAttempt retry attempt
|
|
273
313
|
*/
|
|
274
|
-
declare function partialSetCollection<TKey extends CollectionKeyBase>(collectionKey
|
|
314
|
+
declare function partialSetCollection<TKey extends CollectionKeyBase>({ collectionKey, collection }: SetCollectionParams<TKey>, retryAttempt?: number): Promise<void>;
|
|
275
315
|
declare function logKeyChanged(onyxMethod: Extract<OnyxMethod, 'set' | 'merge'>, key: OnyxKey, value: unknown, hasChanged: boolean): void;
|
|
276
316
|
declare function logKeyRemoved(onyxMethod: Extract<OnyxMethod, 'set' | 'merge'>, key: OnyxKey): void;
|
|
277
317
|
/**
|
|
@@ -313,7 +353,7 @@ declare const OnyxUtils: {
|
|
|
313
353
|
scheduleNotifyCollectionSubscribers: typeof scheduleNotifyCollectionSubscribers;
|
|
314
354
|
remove: typeof remove;
|
|
315
355
|
reportStorageQuota: typeof reportStorageQuota;
|
|
316
|
-
|
|
356
|
+
retryOperation: typeof retryOperation;
|
|
317
357
|
broadcastUpdate: typeof broadcastUpdate;
|
|
318
358
|
hasPendingMergeForKey: typeof hasPendingMergeForKey;
|
|
319
359
|
prepareKeyValuePairsForStorage: typeof prepareKeyValuePairsForStorage;
|
|
@@ -340,6 +380,9 @@ declare const OnyxUtils: {
|
|
|
340
380
|
preserveCollectionReferencesAfterMerge: typeof preserveCollectionReferencesAfterMerge;
|
|
341
381
|
logKeyChanged: typeof logKeyChanged;
|
|
342
382
|
logKeyRemoved: typeof logKeyRemoved;
|
|
383
|
+
setWithRetry: typeof setWithRetry;
|
|
384
|
+
multiSetWithRetry: typeof multiSetWithRetry;
|
|
385
|
+
setCollectionWithRetry: typeof setCollectionWithRetry;
|
|
343
386
|
};
|
|
344
387
|
export type { OnyxMethod };
|
|
345
388
|
export default OnyxUtils;
|
package/dist/OnyxUtils.js
CHANGED
|
@@ -61,6 +61,19 @@ const METHOD = {
|
|
|
61
61
|
MULTI_SET: 'multiset',
|
|
62
62
|
CLEAR: 'clear',
|
|
63
63
|
};
|
|
64
|
+
// IndexedDB errors that indicate storage capacity issues where eviction can help
|
|
65
|
+
const IDB_STORAGE_ERRORS = [
|
|
66
|
+
'quotaexceedederror', // Browser storage quota exceeded
|
|
67
|
+
];
|
|
68
|
+
// SQLite errors that indicate storage capacity issues where eviction can help
|
|
69
|
+
const SQLITE_STORAGE_ERRORS = [
|
|
70
|
+
'database or disk is full', // Device storage is full
|
|
71
|
+
'disk I/O error', // File system I/O failure, often due to insufficient space or corrupted storage
|
|
72
|
+
'out of memory', // Insufficient RAM or storage space to complete the operation
|
|
73
|
+
];
|
|
74
|
+
const STORAGE_ERRORS = [...IDB_STORAGE_ERRORS, ...SQLITE_STORAGE_ERRORS];
|
|
75
|
+
// Max number of retries for failed storage operations
|
|
76
|
+
const MAX_STORAGE_OPERATION_RETRY_ATTEMPTS = 5;
|
|
64
77
|
// Key/value store of Onyx key and arrays of values to merge
|
|
65
78
|
let mergeQueue = {};
|
|
66
79
|
let mergeQueuePromise = {};
|
|
@@ -757,16 +770,31 @@ function reportStorageQuota() {
|
|
|
757
770
|
});
|
|
758
771
|
}
|
|
759
772
|
/**
|
|
760
|
-
*
|
|
761
|
-
*
|
|
762
|
-
*
|
|
773
|
+
* Handles storage operation failures based on the error type:
|
|
774
|
+
* - Storage capacity errors: evicts data and retries the operation
|
|
775
|
+
* - Invalid data errors: logs an alert and throws an error
|
|
776
|
+
* - Other errors: retries the operation
|
|
763
777
|
*/
|
|
764
|
-
function
|
|
765
|
-
|
|
778
|
+
function retryOperation(error, onyxMethod, defaultParams, retryAttempt) {
|
|
779
|
+
var _a, _b, _c, _d;
|
|
780
|
+
const currentRetryAttempt = retryAttempt !== null && retryAttempt !== void 0 ? retryAttempt : 0;
|
|
781
|
+
const nextRetryAttempt = currentRetryAttempt + 1;
|
|
782
|
+
Logger.logInfo(`Failed to save to storage. Error: ${error}. onyxMethod: ${onyxMethod.name}. retryAttempt: ${currentRetryAttempt}/${MAX_STORAGE_OPERATION_RETRY_ATTEMPTS}`);
|
|
766
783
|
if (error && Str.startsWith(error.message, "Failed to execute 'put' on 'IDBObjectStore'")) {
|
|
767
784
|
Logger.logAlert('Attempted to set invalid data set in Onyx. Please ensure all data is serializable.');
|
|
768
785
|
throw error;
|
|
769
786
|
}
|
|
787
|
+
const errorMessage = (_b = (_a = error === null || error === void 0 ? void 0 : error.message) === null || _a === void 0 ? void 0 : _a.toLowerCase) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
788
|
+
const errorName = (_d = (_c = error === null || error === void 0 ? void 0 : error.name) === null || _c === void 0 ? void 0 : _c.toLowerCase) === null || _d === void 0 ? void 0 : _d.call(_c);
|
|
789
|
+
const isStorageCapacityError = STORAGE_ERRORS.some((storageError) => (errorName === null || errorName === void 0 ? void 0 : errorName.includes(storageError)) || (errorMessage === null || errorMessage === void 0 ? void 0 : errorMessage.includes(storageError)));
|
|
790
|
+
if (nextRetryAttempt > MAX_STORAGE_OPERATION_RETRY_ATTEMPTS) {
|
|
791
|
+
Logger.logAlert(`Storage operation failed after 5 retries. Error: ${error}. onyxMethod: ${onyxMethod.name}.`);
|
|
792
|
+
return Promise.resolve();
|
|
793
|
+
}
|
|
794
|
+
if (!isStorageCapacityError) {
|
|
795
|
+
// @ts-expect-error No overload matches this call.
|
|
796
|
+
return onyxMethod(defaultParams, nextRetryAttempt);
|
|
797
|
+
}
|
|
770
798
|
// Find the first key that we can remove that has no subscribers in our blocklist
|
|
771
799
|
const keyForRemoval = OnyxCache_1.default.getKeyForEviction();
|
|
772
800
|
if (!keyForRemoval) {
|
|
@@ -780,7 +808,7 @@ function evictStorageAndRetry(error, onyxMethod, ...args) {
|
|
|
780
808
|
Logger.logInfo(`Out of storage. Evicting least recently accessed key (${keyForRemoval}) and retrying.`);
|
|
781
809
|
reportStorageQuota();
|
|
782
810
|
// @ts-expect-error No overload matches this call.
|
|
783
|
-
return remove(keyForRemoval).then(() => onyxMethod(
|
|
811
|
+
return remove(keyForRemoval).then(() => onyxMethod(defaultParams, nextRetryAttempt));
|
|
784
812
|
}
|
|
785
813
|
/**
|
|
786
814
|
* Notifies subscribers and writes current value to cache
|
|
@@ -1050,17 +1078,193 @@ function updateSnapshots(data, mergeFn) {
|
|
|
1050
1078
|
});
|
|
1051
1079
|
return promises;
|
|
1052
1080
|
}
|
|
1081
|
+
/**
|
|
1082
|
+
* Writes a value to our store with the given key.
|
|
1083
|
+
* Serves as core implementation for `Onyx.set()` public function, the difference being
|
|
1084
|
+
* that this internal function allows passing an additional `retryAttempt` parameter to retry on failure.
|
|
1085
|
+
*
|
|
1086
|
+
* @param params - set parameters
|
|
1087
|
+
* @param params.key ONYXKEY to set
|
|
1088
|
+
* @param params.value value to store
|
|
1089
|
+
* @param params.options optional configuration object
|
|
1090
|
+
* @param retryAttempt retry attempt
|
|
1091
|
+
*/
|
|
1092
|
+
function setWithRetry({ key, value, options }, retryAttempt) {
|
|
1093
|
+
// When we use Onyx.set to set a key we want to clear the current delta changes from Onyx.merge that were queued
|
|
1094
|
+
// before the value was set. If Onyx.merge is currently reading the old value from storage, it will then not apply the changes.
|
|
1095
|
+
if (OnyxUtils.hasPendingMergeForKey(key)) {
|
|
1096
|
+
delete OnyxUtils.getMergeQueue()[key];
|
|
1097
|
+
}
|
|
1098
|
+
if (skippableCollectionMemberIDs.size) {
|
|
1099
|
+
try {
|
|
1100
|
+
const [, collectionMemberID] = OnyxUtils.splitCollectionMemberKey(key);
|
|
1101
|
+
if (skippableCollectionMemberIDs.has(collectionMemberID)) {
|
|
1102
|
+
// The key is a skippable one, so we set the new value to null.
|
|
1103
|
+
// eslint-disable-next-line no-param-reassign
|
|
1104
|
+
value = null;
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
catch (e) {
|
|
1108
|
+
// The key is not a collection one or something went wrong during split, so we proceed with the function's logic.
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
// Onyx.set will ignore `undefined` values as inputs, therefore we can return early.
|
|
1112
|
+
if (value === undefined) {
|
|
1113
|
+
return Promise.resolve();
|
|
1114
|
+
}
|
|
1115
|
+
const existingValue = OnyxCache_1.default.get(key, false);
|
|
1116
|
+
// If the existing value as well as the new value are null, we can return early.
|
|
1117
|
+
if (existingValue === undefined && value === null) {
|
|
1118
|
+
return Promise.resolve();
|
|
1119
|
+
}
|
|
1120
|
+
// Check if the value is compatible with the existing value in the storage
|
|
1121
|
+
const { isCompatible, existingValueType, newValueType } = utils_1.default.checkCompatibilityWithExistingValue(value, existingValue);
|
|
1122
|
+
if (!isCompatible) {
|
|
1123
|
+
Logger.logAlert(logMessages_1.default.incompatibleUpdateAlert(key, 'set', existingValueType, newValueType));
|
|
1124
|
+
return Promise.resolve();
|
|
1125
|
+
}
|
|
1126
|
+
// If the change is null, we can just delete the key.
|
|
1127
|
+
// Therefore, we don't need to further broadcast and update the value so we can return early.
|
|
1128
|
+
if (value === null) {
|
|
1129
|
+
OnyxUtils.remove(key);
|
|
1130
|
+
OnyxUtils.logKeyRemoved(OnyxUtils.METHOD.SET, key);
|
|
1131
|
+
return Promise.resolve();
|
|
1132
|
+
}
|
|
1133
|
+
const valueWithoutNestedNullValues = utils_1.default.removeNestedNullValues(value);
|
|
1134
|
+
const hasChanged = (options === null || options === void 0 ? void 0 : options.skipCacheCheck) ? true : OnyxCache_1.default.hasValueChanged(key, valueWithoutNestedNullValues);
|
|
1135
|
+
OnyxUtils.logKeyChanged(OnyxUtils.METHOD.SET, key, value, hasChanged);
|
|
1136
|
+
// This approach prioritizes fast UI changes without waiting for data to be stored in device storage.
|
|
1137
|
+
const updatePromise = OnyxUtils.broadcastUpdate(key, valueWithoutNestedNullValues, hasChanged);
|
|
1138
|
+
// If the value has not changed and this isn't a retry attempt, calling Storage.setItem() would be redundant and a waste of performance, so return early instead.
|
|
1139
|
+
if (!hasChanged && !retryAttempt) {
|
|
1140
|
+
return updatePromise;
|
|
1141
|
+
}
|
|
1142
|
+
return storage_1.default.setItem(key, valueWithoutNestedNullValues)
|
|
1143
|
+
.catch((error) => OnyxUtils.retryOperation(error, setWithRetry, { key, value: valueWithoutNestedNullValues, options }, retryAttempt))
|
|
1144
|
+
.then(() => {
|
|
1145
|
+
OnyxUtils.sendActionToDevTools(OnyxUtils.METHOD.SET, key, valueWithoutNestedNullValues);
|
|
1146
|
+
return updatePromise;
|
|
1147
|
+
});
|
|
1148
|
+
}
|
|
1149
|
+
/**
|
|
1150
|
+
* Sets multiple keys and values.
|
|
1151
|
+
* Serves as core implementation for `Onyx.multiSet()` public function, the difference being
|
|
1152
|
+
* that this internal function allows passing an additional `retryAttempt` parameter to retry on failure.
|
|
1153
|
+
*
|
|
1154
|
+
* @param data object keyed by ONYXKEYS and the values to set
|
|
1155
|
+
* @param retryAttempt retry attempt
|
|
1156
|
+
*/
|
|
1157
|
+
function multiSetWithRetry(data, retryAttempt) {
|
|
1158
|
+
let newData = data;
|
|
1159
|
+
if (skippableCollectionMemberIDs.size) {
|
|
1160
|
+
newData = Object.keys(newData).reduce((result, key) => {
|
|
1161
|
+
try {
|
|
1162
|
+
const [, collectionMemberID] = OnyxUtils.splitCollectionMemberKey(key);
|
|
1163
|
+
// If the collection member key is a skippable one we set its value to null.
|
|
1164
|
+
// eslint-disable-next-line no-param-reassign
|
|
1165
|
+
result[key] = !skippableCollectionMemberIDs.has(collectionMemberID) ? newData[key] : null;
|
|
1166
|
+
}
|
|
1167
|
+
catch (_a) {
|
|
1168
|
+
// The key is not a collection one or something went wrong during split, so we assign the data to result anyway.
|
|
1169
|
+
// eslint-disable-next-line no-param-reassign
|
|
1170
|
+
result[key] = newData[key];
|
|
1171
|
+
}
|
|
1172
|
+
return result;
|
|
1173
|
+
}, {});
|
|
1174
|
+
}
|
|
1175
|
+
const keyValuePairsToSet = OnyxUtils.prepareKeyValuePairsForStorage(newData, true);
|
|
1176
|
+
const updatePromises = keyValuePairsToSet.map(([key, value]) => {
|
|
1177
|
+
// When we use multiSet to set a key we want to clear the current delta changes from Onyx.merge that were queued
|
|
1178
|
+
// before the value was set. If Onyx.merge is currently reading the old value from storage, it will then not apply the changes.
|
|
1179
|
+
if (OnyxUtils.hasPendingMergeForKey(key)) {
|
|
1180
|
+
delete OnyxUtils.getMergeQueue()[key];
|
|
1181
|
+
}
|
|
1182
|
+
// Update cache and optimistically inform subscribers on the next tick
|
|
1183
|
+
OnyxCache_1.default.set(key, value);
|
|
1184
|
+
return OnyxUtils.scheduleSubscriberUpdate(key, value);
|
|
1185
|
+
});
|
|
1186
|
+
return storage_1.default.multiSet(keyValuePairsToSet)
|
|
1187
|
+
.catch((error) => OnyxUtils.retryOperation(error, multiSetWithRetry, newData, retryAttempt))
|
|
1188
|
+
.then(() => {
|
|
1189
|
+
OnyxUtils.sendActionToDevTools(OnyxUtils.METHOD.MULTI_SET, undefined, newData);
|
|
1190
|
+
return Promise.all(updatePromises);
|
|
1191
|
+
})
|
|
1192
|
+
.then(() => undefined);
|
|
1193
|
+
}
|
|
1194
|
+
/**
|
|
1195
|
+
* Sets a collection by replacing all existing collection members with new values.
|
|
1196
|
+
* Any existing collection members not included in the new data will be removed.
|
|
1197
|
+
* Serves as core implementation for `Onyx.setCollection()` public function, the difference being
|
|
1198
|
+
* that this internal function allows passing an additional `retryAttempt` parameter to retry on failure.
|
|
1199
|
+
*
|
|
1200
|
+
* @param params - collection parameters
|
|
1201
|
+
* @param params.collectionKey e.g. `ONYXKEYS.COLLECTION.REPORT`
|
|
1202
|
+
* @param params.collection Object collection keyed by individual collection member keys and values
|
|
1203
|
+
* @param retryAttempt retry attempt
|
|
1204
|
+
*/
|
|
1205
|
+
function setCollectionWithRetry({ collectionKey, collection }, retryAttempt) {
|
|
1206
|
+
let resultCollection = collection;
|
|
1207
|
+
let resultCollectionKeys = Object.keys(resultCollection);
|
|
1208
|
+
// Confirm all the collection keys belong to the same parent
|
|
1209
|
+
if (!OnyxUtils.doAllCollectionItemsBelongToSameParent(collectionKey, resultCollectionKeys)) {
|
|
1210
|
+
Logger.logAlert(`setCollection called with keys that do not belong to the same parent ${collectionKey}. Skipping this update.`);
|
|
1211
|
+
return Promise.resolve();
|
|
1212
|
+
}
|
|
1213
|
+
if (skippableCollectionMemberIDs.size) {
|
|
1214
|
+
resultCollection = resultCollectionKeys.reduce((result, key) => {
|
|
1215
|
+
try {
|
|
1216
|
+
const [, collectionMemberID] = OnyxUtils.splitCollectionMemberKey(key, collectionKey);
|
|
1217
|
+
// If the collection member key is a skippable one we set its value to null.
|
|
1218
|
+
// eslint-disable-next-line no-param-reassign
|
|
1219
|
+
result[key] = !skippableCollectionMemberIDs.has(collectionMemberID) ? resultCollection[key] : null;
|
|
1220
|
+
}
|
|
1221
|
+
catch (_a) {
|
|
1222
|
+
// Something went wrong during split, so we assign the data to result anyway.
|
|
1223
|
+
// eslint-disable-next-line no-param-reassign
|
|
1224
|
+
result[key] = resultCollection[key];
|
|
1225
|
+
}
|
|
1226
|
+
return result;
|
|
1227
|
+
}, {});
|
|
1228
|
+
}
|
|
1229
|
+
resultCollectionKeys = Object.keys(resultCollection);
|
|
1230
|
+
return OnyxUtils.getAllKeys().then((persistedKeys) => {
|
|
1231
|
+
const mutableCollection = Object.assign({}, resultCollection);
|
|
1232
|
+
persistedKeys.forEach((key) => {
|
|
1233
|
+
if (!key.startsWith(collectionKey)) {
|
|
1234
|
+
return;
|
|
1235
|
+
}
|
|
1236
|
+
if (resultCollectionKeys.includes(key)) {
|
|
1237
|
+
return;
|
|
1238
|
+
}
|
|
1239
|
+
mutableCollection[key] = null;
|
|
1240
|
+
});
|
|
1241
|
+
const keyValuePairs = OnyxUtils.prepareKeyValuePairsForStorage(mutableCollection, true, undefined, true);
|
|
1242
|
+
const previousCollection = OnyxUtils.getCachedCollection(collectionKey);
|
|
1243
|
+
// Preserve references for unchanged items in setCollection
|
|
1244
|
+
const preservedCollection = OnyxUtils.preserveCollectionReferences(keyValuePairs);
|
|
1245
|
+
const updatePromise = OnyxUtils.scheduleNotifyCollectionSubscribers(collectionKey, preservedCollection, previousCollection);
|
|
1246
|
+
return storage_1.default.multiSet(keyValuePairs)
|
|
1247
|
+
.catch((error) => OnyxUtils.retryOperation(error, setCollectionWithRetry, { collectionKey, collection }, retryAttempt))
|
|
1248
|
+
.then(() => {
|
|
1249
|
+
OnyxUtils.sendActionToDevTools(OnyxUtils.METHOD.SET_COLLECTION, undefined, mutableCollection);
|
|
1250
|
+
return updatePromise;
|
|
1251
|
+
});
|
|
1252
|
+
});
|
|
1253
|
+
}
|
|
1053
1254
|
/**
|
|
1054
1255
|
* Merges a collection based on their keys.
|
|
1055
1256
|
* Serves as core implementation for `Onyx.mergeCollection()` public function, the difference being
|
|
1056
|
-
* that this internal function allows passing an additional `mergeReplaceNullPatches` parameter.
|
|
1257
|
+
* that this internal function allows passing an additional `mergeReplaceNullPatches` parameter and retries on failure.
|
|
1057
1258
|
*
|
|
1058
|
-
* @param
|
|
1059
|
-
* @param
|
|
1060
|
-
* @param
|
|
1259
|
+
* @param params - mergeCollection parameters
|
|
1260
|
+
* @param params.collectionKey e.g. `ONYXKEYS.COLLECTION.REPORT`
|
|
1261
|
+
* @param params.collection Object collection keyed by individual collection member keys and values
|
|
1262
|
+
* @param params.mergeReplaceNullPatches Record where the key is a collection member key and the value is a list of
|
|
1061
1263
|
* tuples that we'll use to replace the nested objects of that collection member record with something else.
|
|
1264
|
+
* @param params.isProcessingCollectionUpdate whether this is part of a collection update operation.
|
|
1265
|
+
* @param retryAttempt retry attempt
|
|
1062
1266
|
*/
|
|
1063
|
-
function mergeCollectionWithPatches(collectionKey, collection, mergeReplaceNullPatches, isProcessingCollectionUpdate = false) {
|
|
1267
|
+
function mergeCollectionWithPatches({ collectionKey, collection, mergeReplaceNullPatches, isProcessingCollectionUpdate = false }, retryAttempt) {
|
|
1064
1268
|
if (!isValidNonEmptyCollectionForMerge(collection)) {
|
|
1065
1269
|
Logger.logInfo('mergeCollection() called with invalid or empty value. Skipping this update.');
|
|
1066
1270
|
return Promise.resolve();
|
|
@@ -1153,7 +1357,7 @@ function mergeCollectionWithPatches(collectionKey, collection, mergeReplaceNullP
|
|
|
1153
1357
|
return scheduleNotifyCollectionSubscribers(collectionKey, preservedCollection, previousCollection);
|
|
1154
1358
|
});
|
|
1155
1359
|
return Promise.all(promises)
|
|
1156
|
-
.catch((error) =>
|
|
1360
|
+
.catch((error) => retryOperation(error, mergeCollectionWithPatches, { collectionKey, collection: resultCollection, mergeReplaceNullPatches, isProcessingCollectionUpdate }, retryAttempt))
|
|
1157
1361
|
.then(() => {
|
|
1158
1362
|
sendActionToDevTools(METHOD.MERGE_COLLECTION, undefined, resultCollection);
|
|
1159
1363
|
return promiseUpdate;
|
|
@@ -1164,11 +1368,14 @@ function mergeCollectionWithPatches(collectionKey, collection, mergeReplaceNullP
|
|
|
1164
1368
|
/**
|
|
1165
1369
|
* Sets keys in a collection by replacing all targeted collection members with new values.
|
|
1166
1370
|
* Any existing collection members not included in the new data will not be removed.
|
|
1371
|
+
* Retries on failure.
|
|
1167
1372
|
*
|
|
1168
|
-
* @param
|
|
1169
|
-
* @param
|
|
1373
|
+
* @param params - collection parameters
|
|
1374
|
+
* @param params.collectionKey e.g. `ONYXKEYS.COLLECTION.REPORT`
|
|
1375
|
+
* @param params.collection Object collection keyed by individual collection member keys and values
|
|
1376
|
+
* @param retryAttempt retry attempt
|
|
1170
1377
|
*/
|
|
1171
|
-
function partialSetCollection(collectionKey, collection) {
|
|
1378
|
+
function partialSetCollection({ collectionKey, collection }, retryAttempt) {
|
|
1172
1379
|
let resultCollection = collection;
|
|
1173
1380
|
let resultCollectionKeys = Object.keys(resultCollection);
|
|
1174
1381
|
// Confirm all the collection keys belong to the same parent
|
|
@@ -1202,7 +1409,7 @@ function partialSetCollection(collectionKey, collection) {
|
|
|
1202
1409
|
const preservedCollection = preserveCollectionReferences(keyValuePairs);
|
|
1203
1410
|
const updatePromise = scheduleNotifyCollectionSubscribers(collectionKey, preservedCollection, previousCollection);
|
|
1204
1411
|
return storage_1.default.multiSet(keyValuePairs)
|
|
1205
|
-
.catch((error) =>
|
|
1412
|
+
.catch((error) => retryOperation(error, partialSetCollection, { collectionKey, collection }, retryAttempt))
|
|
1206
1413
|
.then(() => {
|
|
1207
1414
|
sendActionToDevTools(METHOD.SET_COLLECTION, undefined, mutableCollection);
|
|
1208
1415
|
return updatePromise;
|
|
@@ -1254,7 +1461,7 @@ const OnyxUtils = {
|
|
|
1254
1461
|
scheduleNotifyCollectionSubscribers,
|
|
1255
1462
|
remove,
|
|
1256
1463
|
reportStorageQuota,
|
|
1257
|
-
|
|
1464
|
+
retryOperation,
|
|
1258
1465
|
broadcastUpdate,
|
|
1259
1466
|
hasPendingMergeForKey,
|
|
1260
1467
|
prepareKeyValuePairsForStorage,
|
|
@@ -1281,6 +1488,9 @@ const OnyxUtils = {
|
|
|
1281
1488
|
preserveCollectionReferencesAfterMerge,
|
|
1282
1489
|
logKeyChanged,
|
|
1283
1490
|
logKeyRemoved,
|
|
1491
|
+
setWithRetry,
|
|
1492
|
+
multiSetWithRetry,
|
|
1493
|
+
setCollectionWithRetry,
|
|
1284
1494
|
};
|
|
1285
1495
|
GlobalSettings.addGlobalSettingsChangeListener(({ enablePerformanceMetrics }) => {
|
|
1286
1496
|
if (!enablePerformanceMetrics) {
|
|
@@ -1314,7 +1524,7 @@ GlobalSettings.addGlobalSettingsChangeListener(({ enablePerformanceMetrics }) =>
|
|
|
1314
1524
|
// @ts-expect-error Reassign
|
|
1315
1525
|
reportStorageQuota = (0, metrics_1.default)(reportStorageQuota, 'OnyxUtils.reportStorageQuota');
|
|
1316
1526
|
// @ts-expect-error Complex type signature
|
|
1317
|
-
|
|
1527
|
+
retryOperation = (0, metrics_1.default)(retryOperation, 'OnyxUtils.retryOperation');
|
|
1318
1528
|
// @ts-expect-error Reassign
|
|
1319
1529
|
broadcastUpdate = (0, metrics_1.default)(broadcastUpdate, 'OnyxUtils.broadcastUpdate');
|
|
1320
1530
|
// @ts-expect-error Reassign
|
|
@@ -1325,5 +1535,11 @@ GlobalSettings.addGlobalSettingsChangeListener(({ enablePerformanceMetrics }) =>
|
|
|
1325
1535
|
tupleGet = (0, metrics_1.default)(tupleGet, 'OnyxUtils.tupleGet');
|
|
1326
1536
|
// @ts-expect-error Reassign
|
|
1327
1537
|
subscribeToKey = (0, metrics_1.default)(subscribeToKey, 'OnyxUtils.subscribeToKey');
|
|
1538
|
+
// @ts-expect-error Reassign
|
|
1539
|
+
setWithRetry = (0, metrics_1.default)(setWithRetry, 'OnyxUtils.setWithRetry');
|
|
1540
|
+
// @ts-expect-error Reassign
|
|
1541
|
+
multiSetWithRetry = (0, metrics_1.default)(multiSetWithRetry, 'OnyxUtils.multiSetWithRetry');
|
|
1542
|
+
// @ts-expect-error Reassign
|
|
1543
|
+
setCollectionWithRetry = (0, metrics_1.default)(setCollectionWithRetry, 'OnyxUtils.setCollectionWithRetry');
|
|
1328
1544
|
});
|
|
1329
1545
|
exports.default = OnyxUtils;
|
package/dist/types.d.ts
CHANGED
|
@@ -311,6 +311,22 @@ type SetOptions = {
|
|
|
311
311
|
/** Skip the deep equality check against the cached value. Improves performance for large objects. */
|
|
312
312
|
skipCacheCheck?: boolean;
|
|
313
313
|
};
|
|
314
|
+
type SetParams<TKey extends OnyxKey> = {
|
|
315
|
+
key: TKey;
|
|
316
|
+
value: OnyxSetInput<TKey>;
|
|
317
|
+
options?: SetOptions;
|
|
318
|
+
};
|
|
319
|
+
type SetCollectionParams<TKey extends CollectionKeyBase> = {
|
|
320
|
+
collectionKey: TKey;
|
|
321
|
+
collection: OnyxSetCollectionInput<TKey>;
|
|
322
|
+
};
|
|
323
|
+
type MergeCollectionWithPatchesParams<TKey extends CollectionKeyBase> = {
|
|
324
|
+
collectionKey: TKey;
|
|
325
|
+
collection: OnyxMergeCollectionInput<TKey>;
|
|
326
|
+
mergeReplaceNullPatches?: MultiMergeReplaceNullPatches;
|
|
327
|
+
isProcessingCollectionUpdate?: boolean;
|
|
328
|
+
};
|
|
329
|
+
type RetriableOnyxOperation = typeof OnyxUtils.setWithRetry | typeof OnyxUtils.multiSetWithRetry | typeof OnyxUtils.setCollectionWithRetry | typeof OnyxUtils.mergeCollectionWithPatches | typeof OnyxUtils.partialSetCollection;
|
|
314
330
|
/**
|
|
315
331
|
* Represents the options used in `Onyx.init()` method.
|
|
316
332
|
*/
|
|
@@ -368,4 +384,4 @@ type MixedOperationsQueue = {
|
|
|
368
384
|
mergeReplaceNullPatches: MultiMergeReplaceNullPatches;
|
|
369
385
|
set: OnyxInputKeyValueMapping;
|
|
370
386
|
};
|
|
371
|
-
export type { BaseConnectOptions, Collection, CollectionConnectCallback, CollectionConnectOptions, CollectionKey, CollectionKeyBase, ConnectOptions, CustomTypeOptions, DeepRecord, DefaultConnectCallback, DefaultConnectOptions, ExtractOnyxCollectionValue, GenericFunction, InitOptions, Key, KeyValueMapping, CallbackToStateMapping, NonNull, NonUndefined, OnyxInputKeyValueMapping, NullishDeep, OnyxCollection, OnyxEntry, OnyxKey, OnyxInputValue, OnyxCollectionInputValue, OnyxInput, OnyxSetInput, OnyxMultiSetInput, OnyxMergeInput, OnyxMergeCollectionInput, OnyxSetCollectionInput, OnyxMethod, OnyxMethodMap, OnyxUpdate, OnyxValue, Selector, SetOptions, MultiMergeReplaceNullPatches, MixedOperationsQueue, };
|
|
387
|
+
export type { BaseConnectOptions, Collection, CollectionConnectCallback, CollectionConnectOptions, CollectionKey, CollectionKeyBase, ConnectOptions, CustomTypeOptions, DeepRecord, DefaultConnectCallback, DefaultConnectOptions, ExtractOnyxCollectionValue, GenericFunction, InitOptions, Key, KeyValueMapping, CallbackToStateMapping, NonNull, NonUndefined, OnyxInputKeyValueMapping, NullishDeep, OnyxCollection, OnyxEntry, OnyxKey, OnyxInputValue, OnyxCollectionInputValue, OnyxInput, OnyxSetInput, OnyxMultiSetInput, OnyxMergeInput, OnyxMergeCollectionInput, OnyxSetCollectionInput, OnyxMethod, OnyxMethodMap, OnyxUpdate, OnyxValue, Selector, SetOptions, SetParams, SetCollectionParams, MergeCollectionWithPatchesParams, MultiMergeReplaceNullPatches, MixedOperationsQueue, RetriableOnyxOperation, };
|