react-native-onyx 3.0.74 → 3.0.76

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.
@@ -137,6 +137,7 @@ declare function reportStorageQuota(error?: Error): Promise<void>;
137
137
  * Handles storage operation failures based on the error type:
138
138
  * - Storage capacity errors: evicts data and retries the operation
139
139
  * - Invalid data errors: logs an alert and throws an error
140
+ * - Non-retriable errors: logs an alert and resolves without retrying
140
141
  * - Other errors: retries the operation
141
142
  */
142
143
  declare function retryOperation<TMethod extends RetriableOnyxOperation>(error: Error, onyxMethod: TMethod, defaultParams: Parameters<TMethod>[0], retryAttempt: number | undefined): Promise<void>;
@@ -254,10 +255,6 @@ declare function mergeCollectionWithPatches<TKey extends CollectionKeyBase>({ co
254
255
  declare function partialSetCollection<TKey extends CollectionKeyBase>({ collectionKey, collection }: SetCollectionParams<TKey>, retryAttempt?: number): Promise<void>;
255
256
  declare function logKeyChanged(onyxMethod: Extract<OnyxMethod, 'set' | 'merge'>, key: OnyxKey, value: unknown, hasChanged: boolean): void;
256
257
  declare function logKeyRemoved(onyxMethod: Extract<OnyxMethod, 'set' | 'merge'>, key: OnyxKey): void;
257
- /**
258
- * Getter - returns the callback to state mapping, useful in test environments.
259
- */
260
- declare function getCallbackToStateMapping(): Record<number, CallbackToStateMapping<OnyxKey>>;
261
258
  /**
262
259
  * Clear internal variables used in this file, useful in test environments.
263
260
  */
@@ -317,7 +314,6 @@ declare const OnyxUtils: {
317
314
  setWithRetry: typeof setWithRetry;
318
315
  multiSetWithRetry: typeof multiSetWithRetry;
319
316
  setCollectionWithRetry: typeof setCollectionWithRetry;
320
- getCallbackToStateMapping: typeof getCallbackToStateMapping;
321
317
  };
322
318
  export type { OnyxMethod };
323
319
  export default OnyxUtils;
package/dist/OnyxUtils.js CHANGED
@@ -66,6 +66,12 @@ const SQLITE_STORAGE_ERRORS = [
66
66
  'database or disk is full', // Device storage is full
67
67
  ];
68
68
  const STORAGE_ERRORS = [...IDB_STORAGE_ERRORS, ...SQLITE_STORAGE_ERRORS];
69
+ // IndexedDB errors where retrying is futile because the underlying connection/store is broken.
70
+ // The healing path (separate from retryOperation) is responsible for recovery.
71
+ const IDB_NON_RETRIABLE_ERRORS = [
72
+ 'internal error opening backing store', // LevelDB backing store is broken at the filesystem level
73
+ ];
74
+ const NON_RETRIABLE_ERRORS = [...IDB_NON_RETRIABLE_ERRORS];
69
75
  // Max number of retries for failed storage operations
70
76
  const MAX_STORAGE_OPERATION_RETRY_ATTEMPTS = 5;
71
77
  // Key/value store of Onyx key and arrays of values to merge
@@ -663,6 +669,7 @@ function reportStorageQuota(error) {
663
669
  * Handles storage operation failures based on the error type:
664
670
  * - Storage capacity errors: evicts data and retries the operation
665
671
  * - Invalid data errors: logs an alert and throws an error
672
+ * - Non-retriable errors: logs an alert and resolves without retrying
666
673
  * - Other errors: retries the operation
667
674
  */
668
675
  function retryOperation(error, onyxMethod, defaultParams, retryAttempt) {
@@ -677,6 +684,11 @@ function retryOperation(error, onyxMethod, defaultParams, retryAttempt) {
677
684
  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);
678
685
  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);
679
686
  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)));
687
+ const isNonRetriableError = NON_RETRIABLE_ERRORS.some((nonRetriableError) => (errorName === null || errorName === void 0 ? void 0 : errorName.includes(nonRetriableError)) || (errorMessage === null || errorMessage === void 0 ? void 0 : errorMessage.includes(nonRetriableError)));
688
+ if (isNonRetriableError) {
689
+ Logger.logAlert(`Storage operation skipped retry for non-retriable error. Error: ${error}. onyxMethod: ${onyxMethod.name}.`);
690
+ return Promise.resolve();
691
+ }
680
692
  if (nextRetryAttempt > MAX_STORAGE_OPERATION_RETRY_ATTEMPTS) {
681
693
  Logger.logAlert(`Storage operation failed after 5 retries. Error: ${error}. onyxMethod: ${onyxMethod.name}.`);
682
694
  return Promise.resolve();
@@ -882,24 +894,6 @@ function subscribeToKey(connectOptions) {
882
894
  const subscriptionID = lastSubscriptionID++;
883
895
  callbackToStateMapping[subscriptionID] = mapping;
884
896
  callbackToStateMapping[subscriptionID].subscriptionID = subscriptionID;
885
- // If the subscriber is attempting to connect to a collection member whose ID is skippable (e.g. "undefined", "null", etc.)
886
- // we suppress wiring the subscription fully to avoid unnecessary callback emissions such as for "report_undefined".
887
- // We still return a valid subscriptionID so callers can disconnect safely.
888
- try {
889
- const skippableIDs = getSkippableCollectionMemberIDs();
890
- if (skippableIDs.size) {
891
- const [, collectionMemberID] = OnyxKeys_1.default.splitCollectionMemberKey(mapping.key);
892
- if (skippableIDs.has(collectionMemberID)) {
893
- // Clean up the provisional mapping to avoid retaining unused subscribers.
894
- OnyxCache_1.default.addNullishStorageKey(mapping.key);
895
- delete callbackToStateMapping[subscriptionID];
896
- return subscriptionID;
897
- }
898
- }
899
- }
900
- catch (e) {
901
- // Not a collection member key, proceed as usual.
902
- }
903
897
  // When keyChanged is called, a key is passed and the method looks through all the Subscribers in callbackToStateMapping for the matching key to get the subscriptionID
904
898
  // to avoid having to loop through all the Subscribers all the time (even when just one connection belongs to one key),
905
899
  // We create a mapping from key to lists of subscriptionIDs to access the specific list of subscriptionIDs.
@@ -1433,12 +1427,6 @@ function logKeyChanged(onyxMethod, key, value, hasChanged) {
1433
1427
  function logKeyRemoved(onyxMethod, key) {
1434
1428
  Logger.logInfo(`${onyxMethod} called for key: ${key} => null passed, so key was removed`);
1435
1429
  }
1436
- /**
1437
- * Getter - returns the callback to state mapping, useful in test environments.
1438
- */
1439
- function getCallbackToStateMapping() {
1440
- return callbackToStateMapping;
1441
- }
1442
1430
  /**
1443
1431
  * Clear internal variables used in this file, useful in test environments.
1444
1432
  */
@@ -1497,6 +1485,5 @@ const OnyxUtils = {
1497
1485
  setWithRetry,
1498
1486
  multiSetWithRetry,
1499
1487
  setCollectionWithRetry,
1500
- getCallbackToStateMapping,
1501
1488
  };
1502
1489
  exports.default = OnyxUtils;
package/dist/useOnyx.js CHANGED
@@ -210,12 +210,8 @@ function useOnyx(key, options, dependencies = []) {
210
210
  newValueRef.current = null;
211
211
  sourceValueRef.current = undefined;
212
212
  resultRef.current = [undefined, { status: 'loading' }];
213
+ shouldGetCachedValueRef.current = true;
213
214
  }
214
- // Force a cache re-read on every (re)subscription so any side effects from
215
- // subscribeToKey (e.g. addNullishStorageKey for skippable collection member ids)
216
- // are reflected in the next getSnapshot. Resetting this flag does not change
217
- // resultRef by itself, so it doesn't cause an extra mount render.
218
- shouldGetCachedValueRef.current = true;
219
215
  hasMountedRef.current = true;
220
216
  isConnectingRef.current = true;
221
217
  onStoreChangeFnRef.current = onStoreChange;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-onyx",
3
- "version": "3.0.74",
3
+ "version": "3.0.76",
4
4
  "author": "Expensify, Inc.",
5
5
  "homepage": "https://expensify.com",
6
6
  "description": "State management for React Native",