Skip to content
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
78f09d0
Update Reassure version and docs
fabioh8010 Feb 17, 2025
cfa3b88
Add empty perf test functions
fabioh8010 Feb 17, 2025
ff135bd
Move updateSnapshots to OnyxUtils
fabioh8010 Feb 17, 2025
9fed464
Implement several tests for Onyx.ts
fabioh8010 Feb 19, 2025
1cf0020
Merge remote-tracking branch 'origin/main' into feature/reassure
fabioh8010 Feb 24, 2025
56e358c
Add test for tupleGet
fabioh8010 Feb 24, 2025
215653e
Remove one-object tests
fabioh8010 Feb 24, 2025
a10cde2
Finish tests for Onyx.ts
fabioh8010 Feb 24, 2025
c97ac27
Minor fix
fabioh8010 Feb 24, 2025
32fe4b5
Update Reassure to 1.4.0-next.0
fabioh8010 Mar 9, 2025
8069e53
Use measureAsyncFunction in Onyx.perf-test.ts
fabioh8010 Mar 9, 2025
5a82e9d
Implement some OnyxUtils tests
fabioh8010 Mar 9, 2025
661af4e
Update Reassure to 1.4.0
fabioh8010 Mar 14, 2025
493c31a
Fix Onyx.perf-test.ts tests to correctly set setup/cleanup functions
fabioh8010 Mar 14, 2025
0d330a3
Finish tests for OnyxUtils
fabioh8010 Mar 17, 2025
a7d3c3b
Create variable for Object.keys(mockedReportActionsMap)
fabioh8010 Mar 17, 2025
1389439
Increase test timeout
fabioh8010 Mar 17, 2025
945d57f
Implement tests for OnyxCache
fabioh8010 Mar 23, 2025
fbd4196
Implement tests for OnyxConnectionManager
fabioh8010 Mar 24, 2025
4789b68
Merge branch 'main' into feature/reassure
fabioh8010 Apr 4, 2025
4a34c15
Fix types
fabioh8010 Apr 4, 2025
d98bc3d
Add gh-actions-build command
fabioh8010 Apr 4, 2025
b7f7730
Add compiled GH actions to .prettierignore
fabioh8010 Apr 4, 2025
d144844
Remove .vscode/settings.json
fabioh8010 Apr 4, 2025
c520dd4
Fix Reassure workflow
fabioh8010 Apr 4, 2025
ecd8610
Improve tests
fabioh8010 Apr 4, 2025
e345a47
Improve buildActions.sh script
fabioh8010 Apr 13, 2025
ec952eb
Improve Reassure workflow
fabioh8010 Apr 13, 2025
75a8397
Fix script
fabioh8010 Apr 13, 2025
b963633
Use script from E/App
fabioh8010 Apr 13, 2025
0bbd8fa
Test removing steps
fabioh8010 Apr 13, 2025
0c88d28
Add setupNode YML
fabioh8010 Apr 13, 2025
f82a5a7
Uses fetch-depth 0
fabioh8010 Apr 13, 2025
a6c9a94
Merge remote-tracking branch 'origin/main' into feature/reassure
fabioh8010 Apr 23, 2025
4bcd420
Use SHA
fabioh8010 Apr 23, 2025
9c7d14d
Install dependencies before Reassure
fabioh8010 Apr 23, 2025
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
26,902 changes: 26,902 additions & 0 deletions .github/actions/javascript/validateReassureOutput/index.js

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*/

import * as core from '@actions/core';
import type {CompareResult, PerformanceEntry} from '@callstack/reassure-compare/src/types';
import type {CompareResult, MeasureEntry} from '@callstack/reassure-compare';
import fs from 'fs';

async function run() {
Expand All @@ -21,8 +21,8 @@ async function run() {

for (let i = 0; i < regressionOutput.significant.length; i++) {
const measurement = regressionOutput.significant[i];
const baseline: PerformanceEntry = measurement.baseline;
const current: PerformanceEntry = measurement.current;
const baseline: MeasureEntry = measurement.baseline;
const current: MeasureEntry = measurement.current;

console.log(`Processing measurement ${i + 1}: ${measurement.name}`);

Expand Down
26,708 changes: 0 additions & 26,708 deletions .github/actions/validateReassureOutput/index.js

This file was deleted.

43 changes: 43 additions & 0 deletions .github/scripts/buildActions.sh
Comment thread
fabioh8010 marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/bin/bash
#
# Used to precompile all Github Action node.js scripts using ncc.
# This bundles them with their dependencies into a single executable node.js script.

# In order for this script to be safely run from anywhere, we cannot use the raw relative path '../actions'.
declare ACTIONS_DIR
ACTIONS_DIR="$(dirname "$(dirname "$0")")/actions/javascript"

# List of paths to all JS files that implement our GH Actions
declare -r GITHUB_ACTIONS=(
"$ACTIONS_DIR/validateReassureOutput/validateReassureOutput.ts"
)

# This will be inserted at the top of all compiled files as a warning to devs.
declare -r NOTE_DONT_EDIT='/**
* NOTE: This is a compiled file. DO NOT directly edit this file.
*/
'

# This stores all the process IDs of the ncc commands so they can run in parallel
declare ASYNC_BUILDS

for ((i=0; i < ${#GITHUB_ACTIONS[@]}; i++)); do
ACTION=${GITHUB_ACTIONS[$i]}
ACTION_DIR=$(dirname "$ACTION")

# Build the action in the background
npx ncc build --transpile-only --external encoding "$ACTION" -o "$ACTION_DIR" &
ASYNC_BUILDS[i]=$!
done

for ((i=0; i < ${#GITHUB_ACTIONS[@]}; i++)); do
ACTION=${GITHUB_ACTIONS[$i]}
ACTION_DIR=$(dirname "$ACTION")

# Wait for the background build to finish
wait "${ASYNC_BUILDS[$i]}"

# Prepend the warning note to the top of the compiled file
OUTPUT_FILE="$ACTION_DIR/index.js"
echo "$NOTE_DONT_EDIT$(cat "$OUTPUT_FILE")" > "$OUTPUT_FILE"
done
2 changes: 1 addition & 1 deletion .github/workflows/reassurePerfTests.yml
Comment thread
fabioh8010 marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,6 @@ jobs:
npx reassure --branch
- name: Validate output.json
id: validateReassureOutput
uses: ./.github/actions/validateReassureOutput
uses: ./.github/actions/javascript/validateReassureOutput
with:
DURATION_DEVIATION_PERCENTAGE: 20
2 changes: 2 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# The GH actions don't seem to compile and verify themselves well when Prettier is applied to them
.github/actions/javascript/**/index.js
dist
package.json
package-lock.json
Expand Down
1 change: 1 addition & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ module.exports = {
timers: 'fake',
testEnvironment: 'jsdom',
setupFilesAfterEnv: ['@testing-library/jest-native/extend-expect', './jestSetup.js'],
testTimeout: 10000,
};
62 changes: 1 addition & 61 deletions lib/Onyx.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/* eslint-disable no-continue */
import _ from 'underscore';
import lodashPick from 'lodash/pick';
import * as Logger from './Logger';
import cache, {TASK} from './OnyxCache';
import * as PerformanceUtils from './PerformanceUtils';
Expand Down Expand Up @@ -620,65 +619,6 @@ function clear(keysToPreserve: OnyxKey[] = []): Promise<void> {
return cache.captureTask(TASK.CLEAR, promise) as Promise<void>;
}

function updateSnapshots(data: OnyxUpdate[]) {
const snapshotCollectionKey = OnyxUtils.getSnapshotKey();
if (!snapshotCollectionKey) return [];

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

const snapshotCollection = OnyxUtils.getCachedCollection(snapshotCollectionKey);
const snapshotCollectionKeyLength = snapshotCollectionKey.length;

Object.entries(snapshotCollection).forEach(([snapshotKey, snapshotValue]) => {
// Snapshots may not be present in cache. We don't know how to update them so we skip.
if (!snapshotValue) {
return;
}

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

data.forEach(({key, value}) => {
// snapshots are normal keys so we want to skip update if they are written to Onyx
if (OnyxUtils.isCollectionMemberKey(snapshotCollectionKey, key, snapshotCollectionKeyLength)) {
return;
}

if (typeof snapshotValue !== 'object' || !('data' in snapshotValue)) {
return;
}

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

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

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

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)) {
return;
}

promises.push(() => merge(snapshotKey, {data: updatedData}));
});

return promises;
}

/**
* Insert API responses and lifecycle data into Onyx
*
Expand Down Expand Up @@ -804,7 +744,7 @@ function update(data: OnyxUpdate[]): Promise<void> {
}
});

const snapshotPromises = updateSnapshots(data);
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);
Expand Down
74 changes: 70 additions & 4 deletions lib/OnyxUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import {deepEqual} from 'fast-equals';
import lodashClone from 'lodash/clone';
import type {ValueOf} from 'type-fest';
import lodashPick from 'lodash/pick';
import DevTools from './DevTools';
import * as Logger from './Logger';
import type Onyx from './Onyx';
Expand All @@ -25,6 +26,7 @@ import type {
OnyxInput,
OnyxKey,
OnyxMergeCollectionInput,
OnyxUpdate,
OnyxValue,
Selector,
} from './types';
Expand Down Expand Up @@ -650,8 +652,8 @@ function keysChanged<TKey extends CollectionKeyBase>(
collectionKey: TKey,
partialCollection: OnyxCollection<KeyValueMapping[TKey]>,
partialPreviousCollection: OnyxCollection<KeyValueMapping[TKey]> | undefined,
notifyRegularSubscibers = true,
notifyWithOnyxSubscibers = true,
notifyConnectSubscribers = true,
notifyWithOnyxSubscribers = true,
): void {
// We prepare the "cached collection" which is the entire collection + the new partial data that
// was merged in via mergeCollection().
Expand Down Expand Up @@ -687,7 +689,7 @@ function keysChanged<TKey extends CollectionKeyBase>(

// Regular Onyx.connect() subscriber found.
if (typeof subscriber.callback === 'function') {
if (!notifyRegularSubscibers) {
if (!notifyConnectSubscribers) {
continue;
}

Expand Down Expand Up @@ -731,7 +733,7 @@ function keysChanged<TKey extends CollectionKeyBase>(

// React component subscriber found.
if (utils.hasWithOnyxInstance(subscriber)) {
if (!notifyWithOnyxSubscibers) {
if (!notifyWithOnyxSubscribers) {
continue;
}

Expand Down Expand Up @@ -1436,6 +1438,65 @@ function unsubscribeFromKey(subscriptionID: number): void {
delete callbackToStateMapping[subscriptionID];
}

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

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

const snapshotCollection = OnyxUtils.getCachedCollection(snapshotCollectionKey);
const snapshotCollectionKeyLength = snapshotCollectionKey.length;

Object.entries(snapshotCollection).forEach(([snapshotEntryKey, snapshotEntryValue]) => {
Comment thread
fabioh8010 marked this conversation as resolved.
// Snapshots may not be present in cache. We don't know how to update them so we skip.
if (!snapshotEntryValue) {
return;
}

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

data.forEach(({key, value}) => {
// snapshots are normal keys so we want to skip update if they are written to Onyx
if (OnyxUtils.isCollectionMemberKey(snapshotCollectionKey, key, snapshotCollectionKeyLength)) {
return;
}

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

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

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

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

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)) {
return;
}

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

return promises;
}

const OnyxUtils = {
METHOD,
getMergeQueue,
Expand Down Expand Up @@ -1485,6 +1546,11 @@ const OnyxUtils = {
getEvictionBlocklist,
getSkippableCollectionMemberIDs,
setSkippableCollectionMemberIDs,
storeKeyBySubscriptions,
deleteKeyBySubscriptions,
addKeyToRecentlyAccessedIfNeeded,
reduceCollectionWithSelector,
updateSnapshots,
};

GlobalSettings.addGlobalSettingsChangeListener(({enablePerformanceMetrics}) => {
Expand Down
Loading