-
Notifications
You must be signed in to change notification settings - Fork 82
Update error handling in Onyx to prevent unnecessary data eviction #694
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
mountiny
merged 26 commits into
Expensify:main
from
callstack-internal:VickyStash/bugfix/update-eviction-rules
Nov 5, 2025
+479
−232
Merged
Changes from 3 commits
Commits
Show all changes
26 commits
Select commit
Hold shift + click to select a range
df729c3
Update evictStorageAndRetry to not evict the data if error isn't stor…
VickyStash 6fc70ed
Minor improvement and test fix
VickyStash c4d29dc
Applied feedback
VickyStash 67bd9d4
Add comments
VickyStash a8fbd85
Add a simple limitation of operations retries
VickyStash 42f44fb
Merge branch 'main' into VickyStash/bugfix/update-eviction-rules
VickyStash 3bfb0e5
re-run checks
VickyStash 9db02f2
Add internal functions for retries
VickyStash c146abf
Update mergeCollectionWithPatches
VickyStash 5a6d696
Update partialSetCollection
VickyStash 23e996e
Rename const
VickyStash 1bd718a
Minor clean-up
VickyStash b57b22a
Rename const
VickyStash 5e0c4ad
Move setWithRetry, multiSetWithRetry, setCollectionWithRetry to OnyxU…
VickyStash 7f0bf74
Minor code improvements
VickyStash ca326b9
Add unit tests
VickyStash c55cc64
Update the docs
VickyStash 7da26ae
Adjust params passed to the retry function
VickyStash f5e8b4b
Apply feedback
VickyStash fa98ffb
Merge branch 'main' into VickyStash/bugfix/update-eviction-rules
VickyStash 3a6e61d
Add changes from main
VickyStash 8ebfc39
Add logging when max retries are reached
VickyStash fddfe2d
Re-run checks
VickyStash 5b3fcd1
Merge branch 'main' into VickyStash/bugfix/update-eviction-rules
VickyStash fa363e8
TS adjustments after merging main
VickyStash 447f9e3
Minor improvement
VickyStash File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -49,6 +49,10 @@ const METHOD = { | |
| CLEAR: 'clear', | ||
| } as const; | ||
|
|
||
| const IDB_STORAGE_ERRORS = ['quotaexceedederror'] as const; | ||
VickyStash marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| const SQL_STORAGE_ERRORS = ['database or disk is full', 'disk I/O error', 'out of memory'] as const; | ||
| const STORAGE_ERRORS = [...IDB_STORAGE_ERRORS, ...SQL_STORAGE_ERRORS]; | ||
tgolen marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| type OnyxMethod = ValueOf<typeof METHOD>; | ||
|
|
||
| // Key/value store of Onyx key and arrays of values to merge | ||
|
|
@@ -858,11 +862,12 @@ function reportStorageQuota(): Promise<void> { | |
| } | ||
|
|
||
| /** | ||
| * If we fail to set or merge we must handle this by | ||
| * evicting some data from Onyx and then retrying to do | ||
| * whatever it is we attempted to do. | ||
| * Handles storage operation failures based on the error type: | ||
| * - Storage capacity errors: evicts data and retries the operation | ||
| * - Invalid data errors: logs an alert and throws an error | ||
| * - Other errors: retries the operation | ||
| */ | ||
| function evictStorageAndRetry<TMethod extends typeof Onyx.set | typeof Onyx.multiSet | typeof Onyx.mergeCollection | typeof Onyx.setCollection>( | ||
| function retryOperation<TMethod extends typeof Onyx.set | typeof Onyx.multiSet | typeof Onyx.mergeCollection | typeof Onyx.setCollection>( | ||
|
||
| error: Error, | ||
| onyxMethod: TMethod, | ||
| ...args: Parameters<TMethod> | ||
|
|
@@ -874,6 +879,14 @@ function evictStorageAndRetry<TMethod extends typeof Onyx.set | typeof Onyx.mult | |
| throw error; | ||
| } | ||
|
|
||
| const errorMessage = error?.message?.toLowerCase?.(); | ||
| const isStorageCapacityError = STORAGE_ERRORS.some((storageError) => storageError === error?.name?.toLowerCase() || errorMessage?.includes(storageError)); | ||
VickyStash marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| if (!isStorageCapacityError) { | ||
| // @ts-expect-error No overload matches this call. | ||
mountiny marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| return onyxMethod(...args); | ||
| } | ||
VickyStash marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| // Find the first key that we can remove that has no subscribers in our blocklist | ||
| const keyForRemoval = cache.getKeyForEviction(); | ||
| if (!keyForRemoval) { | ||
|
|
@@ -1341,7 +1354,7 @@ function mergeCollectionWithPatches<TKey extends CollectionKeyBase, TMap>( | |
| }); | ||
|
|
||
| return Promise.all(promises) | ||
| .catch((error) => evictStorageAndRetry(error, mergeCollectionWithPatches, collectionKey, resultCollection)) | ||
| .catch((error) => retryOperation(error, mergeCollectionWithPatches, collectionKey, resultCollection)) | ||
| .then(() => { | ||
| sendActionToDevTools(METHOD.MERGE_COLLECTION, undefined, resultCollection); | ||
| return promiseUpdate; | ||
|
|
@@ -1396,7 +1409,7 @@ function partialSetCollection<TKey extends CollectionKeyBase, TMap>(collectionKe | |
| const updatePromise = scheduleNotifyCollectionSubscribers(collectionKey, mutableCollection, previousCollection); | ||
|
|
||
| return Storage.multiSet(keyValuePairs) | ||
| .catch((error) => evictStorageAndRetry(error, partialSetCollection, collectionKey, collection)) | ||
| .catch((error) => retryOperation(error, partialSetCollection, collectionKey, collection)) | ||
| .then(() => { | ||
| sendActionToDevTools(METHOD.SET_COLLECTION, undefined, mutableCollection); | ||
| return updatePromise; | ||
|
|
@@ -1452,7 +1465,7 @@ const OnyxUtils = { | |
| scheduleNotifyCollectionSubscribers, | ||
| remove, | ||
| reportStorageQuota, | ||
| evictStorageAndRetry, | ||
| retryOperation, | ||
| broadcastUpdate, | ||
| hasPendingMergeForKey, | ||
| prepareKeyValuePairsForStorage, | ||
|
|
@@ -1512,7 +1525,7 @@ GlobalSettings.addGlobalSettingsChangeListener(({enablePerformanceMetrics}) => { | |
| // @ts-expect-error Reassign | ||
| reportStorageQuota = decorateWithMetrics(reportStorageQuota, 'OnyxUtils.reportStorageQuota'); | ||
| // @ts-expect-error Complex type signature | ||
| evictStorageAndRetry = decorateWithMetrics(evictStorageAndRetry, 'OnyxUtils.evictStorageAndRetry'); | ||
| retryOperation = decorateWithMetrics(retryOperation, 'OnyxUtils.retryOperation'); | ||
| // @ts-expect-error Reassign | ||
| broadcastUpdate = decorateWithMetrics(broadcastUpdate, 'OnyxUtils.broadcastUpdate'); | ||
| // @ts-expect-error Reassign | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you regenerate these docs after your recent changes? I don't think
retryOperation()is exposed anywhere publicly, right?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tgolen I've re-generated it one more time.
Yeah, it's not public! This file is also API-INTERNAL (describes internal methods)