Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
b0eb40b
Remove macro/micro tasks during subscriber update
VickyStash Jan 23, 2026
62ceec2
Don't send data during connection, if it's already there
VickyStash Jan 26, 2026
8cffc45
Merge branch 'main' into VickyStash/poc/get-rid-of-macro-micro-tasks
VickyStash Jan 26, 2026
5fdc333
Merge branch 'main' into VickyStash/poc/get-rid-of-macro-micro-tasks
VickyStash Feb 11, 2026
e0b0fd7
Adjustment after merging main
VickyStash Feb 11, 2026
35496b7
Clean up the code
VickyStash Feb 11, 2026
864857a
Remove scheduleSubscriberUpdate and scheduleNotifyCollectionSubscribe…
VickyStash Feb 13, 2026
7813305
Keep the logic consistent with how it was
VickyStash Feb 13, 2026
5c763e1
Merge branch 'main' into VickyStash/poc/get-rid-of-macro-micro-tasks
VickyStash Feb 13, 2026
c5263aa
Run prettier
VickyStash Feb 13, 2026
790ce25
Remove outdated perf tests
VickyStash Feb 13, 2026
90c26de
Return updates back
VickyStash Feb 13, 2026
d21a2fc
Fix race condition in keysChanged for collection subscribers
VickyStash Feb 17, 2026
66140d3
Remove unnecessary OnyxUtils prefix
VickyStash Feb 17, 2026
6318f5e
Re-run checks
VickyStash Feb 19, 2026
1b6ea57
Remove unused promise variables for void-returning keyChanged/keysCha…
VickyStash Feb 24, 2026
bf33b18
Merge branch 'main' into VickyStash/poc/get-rid-of-macro-micro-tasks
VickyStash Feb 24, 2026
7d4e71b
Restore promise chaining for previousCollectionPromise
VickyStash Feb 24, 2026
f34b695
Align the code with how it was
VickyStash Feb 24, 2026
74d444b
Move up lastConnectionCallbackData.set
VickyStash Feb 25, 2026
3d96fe9
Re-run perf test
VickyStash Feb 25, 2026
5d161c8
Revert "Move up lastConnectionCallbackData.set"
VickyStash Feb 25, 2026
ea9f16e
Reapply "Move up lastConnectionCallbackData.set"
VickyStash Feb 25, 2026
95947ec
Update sendDataToConnection function
VickyStash Feb 27, 2026
6e0395f
Refactor sendDataToConnection to read from cache
VickyStash Mar 3, 2026
ce36235
TS fix
VickyStash Mar 3, 2026
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
22 changes: 9 additions & 13 deletions lib/Onyx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,9 +254,8 @@ function merge<TKey extends OnyxKey>(key: TKey, changes: OnyxMergeInput<TKey>):
return Promise.resolve();
}

return OnyxMerge.applyMerge(key, existingValue, validChanges).then(({mergedValue, updatePromise}) => {
return OnyxMerge.applyMerge(key, existingValue, validChanges).then(({mergedValue}) => {
OnyxUtils.sendActionToDevTools(OnyxUtils.METHOD.MERGE, key, changes, mergedValue);
return updatePromise;
});
} catch (error) {
Logger.logAlert(`An error occurred while applying merge for key: ${key}, Error: ${error}`);
Expand Down Expand Up @@ -368,16 +367,6 @@ function clear(keysToPreserve: OnyxKey[] = []): Promise<void> {
keysToBeClearedFromStorage.push(key);
}

const updatePromises: Array<Promise<void>> = [];

// Notify the subscribers for each key/value group so they can receive the new values
for (const [key, value] of Object.entries(keyValuesToResetIndividually)) {
updatePromises.push(OnyxUtils.scheduleSubscriberUpdate(key, value));
}
for (const [key, value] of Object.entries(keyValuesToResetAsCollection)) {
updatePromises.push(OnyxUtils.scheduleNotifyCollectionSubscribers(key, value.newValues, value.oldValues));
}

// Exclude RAM-only keys to prevent them from being saved to storage
const defaultKeyValuePairs = Object.entries(
Object.keys(defaultKeyStates)
Expand All @@ -396,7 +385,14 @@ function clear(keysToPreserve: OnyxKey[] = []): Promise<void> {
.then(() => Storage.multiSet(defaultKeyValuePairs))
.then(() => {
DevTools.clearState(keysToPreserve);
return Promise.all(updatePromises);

// Notify the subscribers for each key/value group so they can receive the new values
for (const [key, value] of Object.entries(keyValuesToResetIndividually)) {
OnyxUtils.keyChanged(key, value);
}
for (const [key, value] of Object.entries(keyValuesToResetAsCollection)) {
OnyxUtils.keysChanged(key, value.newValues, value.oldValues);
}
});
})
.then(() => undefined);
Expand Down
5 changes: 2 additions & 3 deletions lib/OnyxMerge/index.native.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,20 @@ const applyMerge: ApplyMerge = <TKey extends OnyxKey, TValue extends OnyxInput<T
OnyxUtils.logKeyChanged(OnyxUtils.METHOD.MERGE, key, mergedValue, hasChanged);

// This approach prioritizes fast UI changes without waiting for data to be stored in device storage.
const updatePromise = OnyxUtils.broadcastUpdate(key, mergedValue as OnyxValue<TKey>, hasChanged);
OnyxUtils.broadcastUpdate(key, mergedValue as OnyxValue<TKey>, hasChanged);

const shouldSkipStorageOperations = !hasChanged || OnyxUtils.isRamOnlyKey(key);

// If the value has not changed, calling Storage.setItem() would be redundant and a waste of performance, so return early instead.
// If the key is marked as RAM-only, it should not be saved nor updated in the storage.
if (shouldSkipStorageOperations) {
return Promise.resolve({mergedValue, updatePromise});
return Promise.resolve({mergedValue});
}

// For native platforms we use `mergeItem` that will take advantage of JSON_PATCH and JSON_REPLACE SQL operations to
// merge the object in a performant way.
return Storage.mergeItem(key, batchedChanges as OnyxValue<TKey>, replaceNullPatches).then(() => ({
mergedValue,
updatePromise,
}));
};

Expand Down
5 changes: 2 additions & 3 deletions lib/OnyxMerge/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,19 @@ const applyMerge: ApplyMerge = <TKey extends OnyxKey, TValue extends OnyxInput<T
OnyxUtils.logKeyChanged(OnyxUtils.METHOD.MERGE, key, mergedValue, hasChanged);

// This approach prioritizes fast UI changes without waiting for data to be stored in device storage.
const updatePromise = OnyxUtils.broadcastUpdate(key, mergedValue as OnyxValue<TKey>, hasChanged);
OnyxUtils.broadcastUpdate(key, mergedValue as OnyxValue<TKey>, hasChanged);

const shouldSkipStorageOperations = !hasChanged || OnyxUtils.isRamOnlyKey(key);

// If the value has not changed, calling Storage.setItem() would be redundant and a waste of performance, so return early instead.
// If the key is marked as RAM-only, it should not be saved nor updated in the storage.
if (shouldSkipStorageOperations) {
return Promise.resolve({mergedValue, updatePromise});
return Promise.resolve({mergedValue});
}

// For web platforms we use `setItem` since the object was already merged with its changes before.
return Storage.setItem(key, mergedValue as OnyxValue<TKey>).then(() => ({
mergedValue,
updatePromise,
}));
};

Expand Down
1 change: 0 additions & 1 deletion lib/OnyxMerge/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import type {OnyxInput, OnyxKey} from '../types';

type ApplyMergeResult<TValue> = {
mergedValue: TValue;
updatePromise: Promise<void>;
};

type ApplyMerge = <TKey extends OnyxKey, TValue extends OnyxInput<OnyxKey> | undefined, TChange extends OnyxInput<OnyxKey> | null>(
Expand Down
Loading