PromucFlow_constructor/app/client/src/workers/Evaluation/evalTreeWithChanges.ts
Vemparala Surya Vamsi e151524d1c
feat: constrained diff between states (#31847)
## Description
We are constraining the diff between the old dataTree and the
newDataTree to its only affected nodes. The affected nodes list is the
evalOrder, unevalUpdates and updatedValuePaths (which represents
localStorage and setter updates). Through limiting the diff to the
affected node list this should help in reducing the diff computation
latency and overall improve the performance of each evaluation cycle.
We are also cleaning up code related to compressing and decompressing
updates since we deprecated that functionality.

Fixes #31272  

## Automation

/ok-to-test tags="@tag.All"

### 🔍 Cypress test results
<!-- This is an auto-generated comment: Cypress test results  -->
> [!IMPORTANT]
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/8447023192>
> Commit: `cb925afbb99577947fbc7233a35e4454223b402a`
> Cypress dashboard url: <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=8447023192&attempt=2"
target="_blank">Click here!</a>
> All cypress tests have passed 🎉🎉🎉

<!-- end of auto-generated comment: Cypress test results  -->


















































































<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Introduced new logic for handling widget state updates efficiently.
- Enhanced evaluation logic to support optimized diff updates and
serialization.
- Improved data tree generation for error handling and evaluation order.
- **Bug Fixes**
- Addressed issues in generating optimized updates for large collections
and handling `undefined` values.
- Fixed Cypress tests in the "PgAdmin Clone App" spec for more reliable
interaction with UI elements.
- **Refactor**
- Simplified the logic for widget state cleanup and evaluation paths
handling.
- Removed unused variables and functions related to widget meta
properties and evaluation paths.
- **Tests**
- Added new spec file `PgAdmin_spec.js` to Cypress limited tests for
client-side regression testing.
- **Chores**
- Updated type imports across various files to reflect changes in
evaluation logic.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2024-03-27 14:37:46 +05:30

118 lines
3.6 KiB
TypeScript

import type {
ConfigTree,
DataTree,
UnEvalTree,
} from "entities/DataTree/dataTreeTypes";
import { dataTreeEvaluator } from "./handlers/evalTree";
import type { DataTreeDiff } from "@appsmith/workers/Evaluation/evaluationUtils";
import type { EvalMetaUpdates } from "@appsmith/workers/common/DataTreeEvaluator/types";
import type { DependencyMap, EvalError } from "utils/DynamicBindingUtils";
import { makeEntityConfigsAsObjProperties } from "@appsmith/workers/Evaluation/dataTreeUtils";
import type { EvalTreeResponseData } from "./types";
import { MessageType, sendMessage } from "utils/MessageUtil";
import { MAIN_THREAD_ACTION } from "@appsmith/workers/Evaluation/evalWorkerActions";
import type { UpdateDataTreeMessageData } from "sagas/EvalWorkerActionSagas";
import type { JSUpdate } from "utils/JSPaneUtils";
import {
generateOptimisedUpdatesAndSetPrevState,
getNewDataTreeUpdates,
uniqueOrderUpdatePaths,
} from "./helpers";
export function evalTreeWithChanges(
updatedValuePaths: string[][],
metaUpdates: EvalMetaUpdates = [],
) {
let evalOrder: string[] = [];
let jsUpdates: Record<string, JSUpdate> = {};
let unEvalUpdates: DataTreeDiff[] = [];
const isCreateFirstTree = false;
let dataTree: DataTree = {};
const errors: EvalError[] = [];
const logs: any[] = [];
const dependencies: DependencyMap = {};
let evalMetaUpdates: EvalMetaUpdates = [...metaUpdates];
let staleMetaIds: string[] = [];
const removedPaths: Array<{ entityId: string; fullpath: string }> = [];
let unevalTree: UnEvalTree = {};
let configTree: ConfigTree = {};
if (dataTreeEvaluator) {
const setupUpdateTreeResponse =
dataTreeEvaluator.setupUpdateTreeWithDifferences(updatedValuePaths);
evalOrder = setupUpdateTreeResponse.evalOrder;
unEvalUpdates = setupUpdateTreeResponse.unEvalUpdates;
jsUpdates = setupUpdateTreeResponse.jsUpdates;
const updateResponse = dataTreeEvaluator.evalAndValidateSubTree(
evalOrder,
dataTreeEvaluator.oldConfigTree,
unEvalUpdates,
);
dataTree = makeEntityConfigsAsObjProperties(dataTreeEvaluator.evalTree, {
evalProps: dataTreeEvaluator.evalProps,
});
/** Make sure evalMetaUpdates is sanitized to prevent postMessage failure */
evalMetaUpdates = JSON.parse(
JSON.stringify([...evalMetaUpdates, ...updateResponse.evalMetaUpdates]),
);
staleMetaIds = updateResponse.staleMetaIds;
unevalTree = dataTreeEvaluator.getOldUnevalTree();
configTree = dataTreeEvaluator.oldConfigTree;
}
const allUnevalUpdates = unEvalUpdates.map(
(update) => update.payload.propertyPath,
);
const completeEvalOrder = uniqueOrderUpdatePaths([
...allUnevalUpdates,
...evalOrder,
]);
const setterAndLocalStorageUpdates = getNewDataTreeUpdates(
uniqueOrderUpdatePaths(updatedValuePaths.map((val) => val.join("."))),
dataTree,
);
const updates = generateOptimisedUpdatesAndSetPrevState(
dataTree,
dataTreeEvaluator,
completeEvalOrder,
setterAndLocalStorageUpdates,
);
const evalTreeResponse: EvalTreeResponseData = {
updates,
dependencies,
errors,
evalMetaUpdates,
evaluationOrder: evalOrder,
jsUpdates,
logs,
unEvalUpdates,
isCreateFirstTree,
configTree,
staleMetaIds,
removedPaths,
isNewWidgetAdded: false,
undefinedEvalValuesMap: dataTreeEvaluator?.undefinedEvalValuesMap || {},
jsVarsCreatedEvent: [],
};
const data: UpdateDataTreeMessageData = {
workerResponse: evalTreeResponse,
unevalTree,
};
sendMessage.call(self, {
messageType: MessageType.DEFAULT,
body: {
data,
method: MAIN_THREAD_ACTION.UPDATE_DATATREE,
},
});
}