react-native-onyx 3.0.75 → 3.0.77

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>;
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();
@@ -58,27 +58,15 @@ function degradePerformance(error) {
58
58
  * Runs a piece of code and degrades performance if certain errors are thrown
59
59
  */
60
60
  function tryOrDegradePerformance(fn, waitForInitialization = true) {
61
- return new Promise((resolve, reject) => {
62
- const promise = waitForInitialization ? initPromise : Promise.resolve();
63
- promise.then(() => {
64
- try {
65
- resolve(fn());
66
- }
67
- catch (error) {
68
- // Test for known critical errors that the storage provider throws, e.g. when storage is full
69
- if (error instanceof Error) {
70
- // IndexedDB error when storage is full (https://github.com/Expensify/App/issues/29403)
71
- if (error.message.includes('Internal error opening backing store for indexedDB.open')) {
72
- degradePerformance(error);
73
- }
74
- // catch the error if DB connection can not be established/DB can not be created
75
- if (error.message.includes('IDBKeyVal store could not be created')) {
76
- degradePerformance(error);
77
- }
78
- }
79
- reject(error);
80
- }
81
- });
61
+ const initialization = waitForInitialization ? initPromise : Promise.resolve();
62
+ return initialization
63
+ .then(() => fn())
64
+ .catch((error) => {
65
+ // catch the error if DB connection can not be established/DB can not be created
66
+ if (error instanceof Error && error.message.includes('IDBKeyVal store could not be created')) {
67
+ degradePerformance(error);
68
+ }
69
+ return Promise.reject(error);
82
70
  });
83
71
  }
84
72
  const storage = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-onyx",
3
- "version": "3.0.75",
3
+ "version": "3.0.77",
4
4
  "author": "Expensify, Inc.",
5
5
  "homepage": "https://expensify.com",
6
6
  "description": "State management for React Native",