PromucFlow_constructor/app/client/src/workers/evaluation.worker.ts

176 lines
5.4 KiB
TypeScript
Raw Normal View History

2021-02-22 11:14:08 +00:00
import { DataTree } from "entities/DataTree/dataTreeFactory";
import {
DependencyMap,
EVAL_WORKER_ACTIONS,
EvalError,
EvalErrorTypes,
2021-02-22 05:00:16 +00:00
} from "utils/DynamicBindingUtils";
import {
2021-02-22 11:14:08 +00:00
addFunctions,
CrashingError,
getValidatedTree,
removeFunctions,
validateWidgetProperty,
} from "./evaluationUtils";
2021-02-22 11:14:08 +00:00
import DataTreeEvaluator from "workers/DataTreeEvaluator";
const ctx: Worker = self as any;
let dataTreeEvaluator: DataTreeEvaluator | undefined;
//TODO: Create a more complete RPC setup in the subtree-eval branch.
function messageEventListener(
fn: (message: EVAL_WORKER_ACTIONS, requestData: any) => void,
) {
return (e: MessageEvent) => {
const startTime = performance.now();
const { method, requestId, requestData } = e.data;
const responseData = fn(method, requestData);
const endTime = performance.now();
ctx.postMessage({
requestId,
responseData,
timeTaken: (endTime - startTime).toFixed(2),
});
};
}
ctx.addEventListener(
"message",
messageEventListener((method, requestData: any) => {
switch (method) {
case EVAL_WORKER_ACTIONS.EVAL_TREE: {
const { widgetTypeConfigMap, unevalTree } = requestData;
let dataTree: DataTree = unevalTree;
let errors: EvalError[] = [];
2021-02-22 11:14:08 +00:00
let logs: any[] = [];
let dependencies: DependencyMap = {};
try {
if (!dataTreeEvaluator) {
dataTreeEvaluator = new DataTreeEvaluator(widgetTypeConfigMap);
dataTreeEvaluator.createFirstTree(unevalTree);
dataTree = dataTreeEvaluator.evalTree;
} else {
dataTree = dataTreeEvaluator.updateDataTree(unevalTree);
}
// We need to clean it to remove any possible functions inside the tree.
// If functions exist, it will crash the web worker
dataTree = JSON.parse(JSON.stringify(dataTree));
2021-01-14 14:37:21 +00:00
dependencies = dataTreeEvaluator.inverseDependencyMap;
errors = dataTreeEvaluator.errors;
dataTreeEvaluator.clearErrors();
2021-02-22 11:14:08 +00:00
logs = dataTreeEvaluator.logs;
dataTreeEvaluator.clearLogs();
} catch (e) {
if (dataTreeEvaluator !== undefined) {
errors = dataTreeEvaluator.errors;
2021-02-22 11:14:08 +00:00
logs = dataTreeEvaluator.logs;
}
if (!(e instanceof CrashingError)) {
errors.push({
type: EvalErrorTypes.UNKNOWN_ERROR,
message: e.message,
});
console.error(e);
}
dataTree = getValidatedTree(widgetTypeConfigMap, unevalTree);
dataTreeEvaluator = undefined;
}
return {
dataTree,
dependencies,
errors,
2021-02-22 11:14:08 +00:00
logs,
};
}
2021-01-14 14:37:21 +00:00
case EVAL_WORKER_ACTIONS.EVAL_ACTION_BINDINGS: {
const { bindings, executionParams } = requestData;
if (!dataTreeEvaluator) {
return { values: undefined, errors: [] };
}
2021-01-14 14:37:21 +00:00
const values = dataTreeEvaluator.evaluateActionBindings(
bindings,
executionParams,
);
2021-01-14 14:37:21 +00:00
const cleanValues = removeFunctions(values);
const errors = dataTreeEvaluator.errors;
dataTreeEvaluator.clearErrors();
return { values: cleanValues, errors };
}
case EVAL_WORKER_ACTIONS.EVAL_TRIGGER: {
const { dynamicTrigger, callbackData, dataTree } = requestData;
if (!dataTreeEvaluator) {
return { triggers: [], errors: [] };
}
const evalTree = dataTreeEvaluator.updateDataTree(dataTree);
const withFunctions = addFunctions(evalTree);
const triggers = dataTreeEvaluator.getDynamicValue(
dynamicTrigger,
withFunctions,
true,
callbackData,
);
const cleanTriggers = removeFunctions(triggers);
2021-02-22 05:00:16 +00:00
// Transforming eval errors into eval trigger errors. Since trigger
// errors occur less, we want to treat it separately
const errors = dataTreeEvaluator.errors.map((error) => {
if (error.type === EvalErrorTypes.EVAL_ERROR) {
return {
...error,
type: EvalErrorTypes.EVAL_TRIGGER_ERROR,
};
}
return error;
});
dataTreeEvaluator.clearErrors();
return { triggers: cleanTriggers, errors };
}
case EVAL_WORKER_ACTIONS.CLEAR_CACHE: {
dataTreeEvaluator = undefined;
return true;
}
case EVAL_WORKER_ACTIONS.CLEAR_PROPERTY_CACHE: {
const { propertyPath } = requestData;
if (!dataTreeEvaluator) {
return true;
}
dataTreeEvaluator.clearPropertyCache(propertyPath);
return true;
}
case EVAL_WORKER_ACTIONS.CLEAR_PROPERTY_CACHE_OF_WIDGET: {
const { widgetName } = requestData;
if (!dataTreeEvaluator) {
return true;
}
dataTreeEvaluator.clearPropertyCacheOfWidget(widgetName);
return true;
}
case EVAL_WORKER_ACTIONS.VALIDATE_PROPERTY: {
const {
widgetType,
widgetTypeConfigMap,
property,
value,
props,
} = requestData;
return removeFunctions(
validateWidgetProperty(
widgetTypeConfigMap,
widgetType,
property,
value,
props,
),
);
}
default: {
console.error("Action not registered on worker", method);
2020-12-23 14:18:46 +00:00
}
}
}),
);