Skip to content

Commit 2c24bb5

Browse files
committed
feat: Log original error
1 parent 272cbcb commit 2c24bb5

2 files changed

Lines changed: 45 additions & 8 deletions

File tree

lib/OnyxUtils.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -765,13 +765,13 @@ function remove<TKey extends OnyxKey>(key: TKey, isProcessingCollectionUpdate?:
765765
return Storage.removeItem(key).then(() => undefined);
766766
}
767767

768-
function reportStorageQuota(): Promise<void> {
768+
function reportStorageQuota(error?: Error): Promise<void> {
769769
return Storage.getDatabaseSize()
770770
.then(({bytesUsed, bytesRemaining}) => {
771-
Logger.logInfo(`Storage Quota Check -- bytesUsed: ${bytesUsed} bytesRemaining: ${bytesRemaining}`);
771+
Logger.logInfo(`Storage Quota Check -- bytesUsed: ${bytesUsed} bytesRemaining: ${bytesRemaining}. Original error: ${error}`);
772772
})
773773
.catch((dbSizeError) => {
774-
Logger.logAlert(`Unable to get database size. Error: ${dbSizeError}`);
774+
Logger.logAlert(`Unable to get database size. Original error: ${error}. getDatabaseSize error: ${dbSizeError}`);
775775
});
776776
}
777777

@@ -788,7 +788,7 @@ function retryOperation<TMethod extends RetriableOnyxOperation>(error: Error, on
788788
Logger.logInfo(`Failed to save to storage. Error: ${error}. onyxMethod: ${onyxMethod.name}. retryAttempt: ${currentRetryAttempt}/${MAX_STORAGE_OPERATION_RETRY_ATTEMPTS}`);
789789

790790
if (error && Str.startsWith(error.message, "Failed to execute 'put' on 'IDBObjectStore'")) {
791-
Logger.logAlert('Attempted to set invalid data set in Onyx. Please ensure all data is serializable.');
791+
Logger.logAlert(`Attempted to set invalid data set in Onyx. Please ensure all data is serializable. Error: ${error}`);
792792
throw error;
793793
}
794794

@@ -812,13 +812,13 @@ function retryOperation<TMethod extends RetriableOnyxOperation>(error: Error, on
812812
// If we have no acceptable keys to remove then we are possibly trying to save mission critical data. If this is the case,
813813
// then we should stop retrying as there is not much the user can do to fix this. Instead of getting them stuck in an infinite loop we
814814
// will allow this write to be skipped.
815-
Logger.logAlert('Out of storage. But found no acceptable keys to remove.');
816-
return reportStorageQuota();
815+
Logger.logAlert(`Out of storage. But found no acceptable keys to remove. Error: ${error}`);
816+
return reportStorageQuota(error);
817817
}
818818

819819
// Remove the least recently accessed key and retry.
820-
Logger.logInfo(`Out of storage. Evicting least recently accessed key (${keyForRemoval}) and retrying.`);
821-
reportStorageQuota();
820+
Logger.logInfo(`Out of storage. Evicting least recently accessed key (${keyForRemoval}) and retrying. Error: ${error}`);
821+
reportStorageQuota(error);
822822

823823
// @ts-expect-error No overload matches this call.
824824
return remove(keyForRemoval).then(() => onyxMethod(defaultParams, nextRetryAttempt));

tests/unit/onyxUtilsTest.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import utils from '../../lib/utils';
66
import type {Collection, OnyxCollection} from '../../lib/types';
77
import type GenericCollection from '../utils/GenericCollection';
88
import OnyxCache from '../../lib/OnyxCache';
9+
import * as Logger from '../../lib/Logger';
910
import StorageMock from '../../lib/storage';
1011
import createDeferredTask from '../../lib/createDeferredTask';
1112
import waitForPromisesToResolve from '../utils/waitForPromisesToResolve';
@@ -395,6 +396,26 @@ describe('OnyxUtils', () => {
395396
expect(retryOperationSpy).toHaveBeenCalledTimes(1);
396397
});
397398

399+
it('should include the error in logAlert for IDBObjectStore invalid data errors', async () => {
400+
const logAlertSpy = jest.spyOn(Logger, 'logAlert');
401+
StorageMock.setItem = jest.fn().mockRejectedValueOnce(invalidDataError);
402+
403+
await expect(Onyx.set(ONYXKEYS.TEST_KEY, {test: 'data'})).rejects.toThrow(invalidDataError);
404+
405+
expect(logAlertSpy).toHaveBeenCalledWith(`Attempted to set invalid data set in Onyx. Please ensure all data is serializable. Error: ${invalidDataError}`);
406+
});
407+
408+
it('should include the error in logs when out of storage with no evictable keys', async () => {
409+
const logAlertSpy = jest.spyOn(Logger, 'logAlert');
410+
const logInfoSpy = jest.spyOn(Logger, 'logInfo');
411+
StorageMock.setItem = jest.fn().mockRejectedValue(memoryError);
412+
413+
await Onyx.set(ONYXKEYS.TEST_KEY, {test: 'data'});
414+
415+
expect(logAlertSpy).toHaveBeenCalledWith(`Out of storage. But found no acceptable keys to remove. Error: ${memoryError}`);
416+
expect(logInfoSpy).toHaveBeenCalledWith(`Storage Quota Check -- bytesUsed: 0 bytesRemaining: Infinity. Original error: ${memoryError}`);
417+
});
418+
398419
it('should not re-add an evicted key to recentlyAccessedKeys after removal', async () => {
399420
// Re-init with evictable keys so getKeyForEviction() has something to return
400421
Object.assign(OnyxUtils.getDeferredInitTask(), createDeferredTask());
@@ -422,6 +443,7 @@ describe('OnyxUtils', () => {
422443
let LocalOnyxUtils: typeof OnyxUtils;
423444
let LocalOnyxCache: typeof OnyxCache;
424445
let LocalStorageMock: typeof StorageMock;
446+
let LocalLogger: typeof Logger;
425447

426448
// Reset all modules to get fresh singletons (OnyxCache, OnyxUtils, etc.)
427449
// then re-init Onyx with evictableKeys configured
@@ -432,6 +454,7 @@ describe('OnyxUtils', () => {
432454
LocalOnyxUtils = require('../../lib/OnyxUtils').default;
433455
LocalOnyxCache = require('../../lib/OnyxCache').default;
434456
LocalStorageMock = require('../../lib/storage').default;
457+
LocalLogger = require('../../lib/Logger');
435458

436459
LocalOnyx.init({
437460
keys: ONYXKEYS,
@@ -537,6 +560,20 @@ describe('OnyxUtils', () => {
537560
expect(keyForEviction).toBeDefined();
538561
expect(keyForEviction?.startsWith(ONYXKEYS.COLLECTION.TEST_KEY)).toBe(true);
539562
});
563+
564+
it('should include the error in logs when evicting a key', async () => {
565+
const logInfoSpy = jest.spyOn(LocalLogger, 'logInfo');
566+
const key1 = `${ONYXKEYS.COLLECTION.TEST_KEY}1`;
567+
568+
await LocalOnyx.set(key1, {id: 1});
569+
570+
LocalStorageMock.setItem = jest.fn(LocalStorageMock.setItem).mockRejectedValueOnce(diskFullError).mockImplementation(LocalStorageMock.setItem);
571+
572+
await LocalOnyx.set(ONYXKEYS.TEST_KEY, {test: 'data'});
573+
574+
expect(logInfoSpy).toHaveBeenCalledWith(`Out of storage. Evicting least recently accessed key (${key1}) and retrying. Error: ${diskFullError}`);
575+
expect(logInfoSpy).toHaveBeenCalledWith(`Storage Quota Check -- bytesUsed: 0 bytesRemaining: Infinity. Original error: ${diskFullError}`);
576+
});
540577
});
541578

542579
describe('afterInit', () => {

0 commit comments

Comments
 (0)