Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions lib/Onyx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -542,12 +542,7 @@ function update<TKey extends OnyxKey>(data: Array<OnyxUpdate<TKey>>): Promise<vo
}
}

const snapshotPromises = OnyxUtils.updateSnapshots(data, merge);

// We need to run the snapshot updates before the other updates so the snapshot data can be updated before the loading state in the snapshot
const finalPromises = snapshotPromises.concat(promises);

return clearPromise.then(() => Promise.all(finalPromises.map((p) => p()))).then(() => undefined);
return clearPromise.then(() => Promise.all(promises.map((p) => p()))).then(() => undefined);
}

/**
Expand Down
62 changes: 0 additions & 62 deletions lib/OnyxUtils.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import {deepEqual} from 'fast-equals';
import type {ValueOf} from 'type-fest';
import lodashPick from 'lodash/pick';
import _ from 'underscore';
import DevTools from './DevTools';
import * as Logger from './Logger';
import type Onyx from './Onyx';
import cache, {TASK} from './OnyxCache';
import * as Str from './Str';
import Storage from './storage';
Expand All @@ -24,7 +22,6 @@ import type {
OnyxInputKeyValueMapping,
OnyxKey,
OnyxMergeCollectionInput,
OnyxUpdate,
OnyxValue,
Selector,
MergeCollectionWithPatchesParams,
Expand Down Expand Up @@ -1192,64 +1189,6 @@ function unsubscribeFromKey(subscriptionID: number): void {
delete callbackToStateMapping[subscriptionID];
}

function updateSnapshots<TKey extends OnyxKey>(data: Array<OnyxUpdate<TKey>>, mergeFn: typeof Onyx.merge): Array<() => Promise<void>> {
const snapshotCollectionKey = getSnapshotKey();
if (!snapshotCollectionKey) return [];

const promises: Array<() => Promise<void>> = [];

const snapshotCollection = getCachedCollection(snapshotCollectionKey);

for (const [snapshotEntryKey, snapshotEntryValue] of Object.entries(snapshotCollection)) {
// Snapshots may not be present in cache. We don't know how to update them so we skip.
if (!snapshotEntryValue) {
continue;
}

let updatedData: Record<string, unknown> = {};

for (const {key, value} of data) {
// snapshots are normal keys so we want to skip update if they are written to Onyx
if (isCollectionMemberKey(snapshotCollectionKey, key)) {
continue;
}

if (typeof snapshotEntryValue !== 'object' || !('data' in snapshotEntryValue)) {
continue;
}

const snapshotData = snapshotEntryValue.data;
if (!snapshotData || !snapshotData[key]) {
continue;
}

if (Array.isArray(value) || Array.isArray(snapshotData[key])) {
updatedData[key] = value || [];
continue;
}

if (value === null) {
updatedData[key] = value;
continue;
}

const oldValue = updatedData[key] || {};
const newValue = lodashPick(value, Object.keys(snapshotData[key]));

updatedData = {...updatedData, [key]: Object.assign(oldValue, newValue)};
}

// Skip the update if there's no data to be merged
if (utils.isEmptyObject(updatedData)) {
continue;
}

promises.push(() => mergeFn(snapshotEntryKey, {data: updatedData}));
}

return promises;
}

/**
* Writes a value to our store with the given key.
* Serves as core implementation for `Onyx.set()` public function, the difference being
Expand Down Expand Up @@ -1708,7 +1647,6 @@ const OnyxUtils = {
deleteKeyBySubscriptions,
addKeyToRecentlyAccessedIfNeeded,
reduceCollectionWithSelector,
updateSnapshots,
mergeCollectionWithPatches,
partialSetCollection,
logKeyChanged,
Expand Down
36 changes: 1 addition & 35 deletions tests/perf-test/OnyxUtils.perf-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ import StorageMock from '../../lib/storage';
import OnyxCache from '../../lib/OnyxCache';
import OnyxUtils, {clearOnyxUtilsInternals} from '../../lib/OnyxUtils';
import type GenericCollection from '../utils/GenericCollection';
import type {OnyxUpdate} from '../../lib/Onyx';
import createDeferredTask from '../../lib/createDeferredTask';
import type {OnyxEntry, OnyxInputKeyValueMapping, OnyxKey, RetriableOnyxOperation} from '../../lib/types';
import type {OnyxEntry, OnyxKey, RetriableOnyxOperation} from '../../lib/types';

const ONYXKEYS = {
TEST_KEY: 'test',
Expand Down Expand Up @@ -794,37 +793,4 @@ describe('OnyxUtils', () => {
await measureFunction(() => OnyxUtils.reduceCollectionWithSelector(mockedReportActionsMap, selector));
});
});

describe('updateSnapshots', () => {
test('one call with 100 updates', async () => {
const updates: Array<OnyxUpdate<OnyxKey>> = [];
for (let i = 0; i < 100; i++) {
updates.push({
onyxMethod: OnyxUtils.METHOD.MERGE,
key: `${collectionKey}${i}`,
value: createRandomReportAction(i),
});
}

await measureAsyncFunction(() => Promise.all(OnyxUtils.updateSnapshots(updates, Onyx.merge).map((p) => p())), {
beforeEach: async () => {
const searchData: Partial<OnyxInputKeyValueMapping> = {};
const data: Partial<OnyxInputKeyValueMapping> = {
...mockedReportActionsMap,
[`${ONYXKEYS.COLLECTION.SNAPSHOT}hash0`]: {
data: searchData,
search: {},
},
};

for (let i = 0; i < 100; i++) {
searchData[`${collectionKey}${i}`] = mockedReportActionsMap[`${collectionKey}${i}`];
}

await Onyx.multiSet(data);
},
afterEach: clearOnyxAfterEachMeasure,
});
});
});
});
26 changes: 0 additions & 26 deletions tests/unit/onyxTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1550,32 +1550,6 @@ describe('Onyx', () => {
});
});

it('should update Snapshot when its data changed', async () => {
const cat = `${ONYX_KEYS.COLLECTION.ANIMALS}cat`;
const snapshot1 = `${ONYX_KEYS.COLLECTION.SNAPSHOT}1`;

const initialValue = {name: 'Fluffy'};
const finalValue = {name: 'Kitty'};

await Onyx.set(cat, initialValue);
await Onyx.set(snapshot1, {data: {[cat]: initialValue}});

const callback = jest.fn();

Onyx.connect({
key: ONYX_KEYS.COLLECTION.SNAPSHOT,
callback,
});

await waitForPromisesToResolve();

await Onyx.update([{key: cat, value: finalValue, onyxMethod: Onyx.METHOD.MERGE}]);

expect(callback).toBeCalledTimes(2);
expect(callback).toHaveBeenNthCalledWith(1, {data: {[cat]: initialValue}}, snapshot1);
expect(callback).toHaveBeenNthCalledWith(2, {data: {[cat]: finalValue}}, snapshot1);
});

describe('update', () => {
it('should squash all updates of collection-related keys into a single mergeCollection call', () => {
const connections: Connection[] = [];
Expand Down