Skip to content

Commit 58d2a8c

Browse files
leshniakclaude
andcommitted
feat: add backoff constants and helpers for retry delay
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 0129ed0 commit 58d2a8c

1 file changed

Lines changed: 38 additions & 0 deletions

File tree

lib/OnyxUtils.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,24 @@ const STORAGE_ERRORS = [...IDB_STORAGE_ERRORS, ...SQLITE_STORAGE_ERRORS];
6464
// Max number of retries for failed storage operations
6565
const MAX_STORAGE_OPERATION_RETRY_ATTEMPTS = 5;
6666

67+
// Connection/state errors where the DB needs time to recover — backoff helps, eviction does not
68+
const IDB_CONNECTION_ERRORS = [
69+
'internal error opening backing store', // Chrome/Edge: corrupted IDB state
70+
'connection to indexed database server lost', // Safari: IDB connection dropped
71+
'the database connection is closing', // Cross-browser: DB closing during write
72+
] as const;
73+
74+
const SQLITE_CONNECTION_ERRORS = [
75+
'disk i/o error', // Native: filesystem/device stress
76+
'database is locked', // Native: concurrent access contention
77+
] as const;
78+
79+
const CONNECTION_ERRORS = [...IDB_CONNECTION_ERRORS, ...SQLITE_CONNECTION_ERRORS];
80+
81+
// Retry backoff configuration
82+
const RETRY_BASE_DELAY_MS = 100;
83+
const RETRY_JITTER_FACTOR = 0.25;
84+
6785
type OnyxMethod = ValueOf<typeof METHOD>;
6886

6987
// Key/value store of Onyx key and arrays of values to merge
@@ -763,6 +781,26 @@ function remove<TKey extends OnyxKey>(key: TKey, isProcessingCollectionUpdate?:
763781
return Storage.removeItem(key).then(() => undefined);
764782
}
765783

784+
/**
785+
* Returns a promise that resolves after the given number of milliseconds.
786+
*/
787+
function wait(ms: number): Promise<void> {
788+
return new Promise((resolve) => {
789+
setTimeout(resolve, ms);
790+
});
791+
}
792+
793+
/**
794+
* Calculates exponential backoff delay with jitter for a given retry attempt.
795+
* Formula: baseDelay * 2^attempt ± jitter
796+
* Attempt 0: ~100ms, Attempt 1: ~200ms, ..., Attempt 4: ~1600ms
797+
*/
798+
function getRetryDelay(attempt: number): number {
799+
const baseDelay = RETRY_BASE_DELAY_MS * 2 ** attempt;
800+
const jitter = baseDelay * RETRY_JITTER_FACTOR * (2 * Math.random() - 1);
801+
return Math.round(baseDelay + jitter);
802+
}
803+
766804
function reportStorageQuota(error?: Error): Promise<void> {
767805
return Storage.getDatabaseSize()
768806
.then(({bytesUsed, bytesRemaining}) => {

0 commit comments

Comments
 (0)