From 86cca9ff0a1d106d52e826198f77a0c1b2f4f7d5 Mon Sep 17 00:00:00 2001 From: Hetu Nandu Date: Tue, 3 Nov 2020 15:36:44 +0530 Subject: [PATCH 1/2] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0370fb76c7..7b7924972e 100644 --- a/README.md +++ b/README.md @@ -122,7 +122,7 @@ The Appsmith platform is available under the [Apache License 2.0](https://www.ap
Adam

💻 -
Sumanth Yedoti

🔧 💻 +
Sumanth Yedoti

💻 From 4cba17ab8204eb22621ab4786f6f6311a8bf8f2c Mon Sep 17 00:00:00 2001 From: Hetu Nandu Date: Tue, 3 Nov 2020 15:46:11 +0530 Subject: [PATCH 2/2] Add post eval action support (#1529) Fixes #1504 --- app/client/src/actions/pageActions.tsx | 11 ++++- app/client/src/actions/widgetActions.tsx | 9 ++-- .../src/constants/ReduxActionConstants.tsx | 5 ++ app/client/src/sagas/PageSagas.tsx | 26 ++++++---- app/client/src/sagas/evaluationsSaga.ts | 49 +++++++++++++++---- app/client/src/selectors/dataTreeSelectors.ts | 1 - app/client/src/workers/evaluation.worker.ts | 3 +- 7 files changed, 75 insertions(+), 29 deletions(-) diff --git a/app/client/src/actions/pageActions.tsx b/app/client/src/actions/pageActions.tsx index f240ce802f..b18509dde1 100644 --- a/app/client/src/actions/pageActions.tsx +++ b/app/client/src/actions/pageActions.tsx @@ -2,6 +2,7 @@ import { FetchPageRequest, SavePageResponse } from "api/PageApi"; import { WidgetOperation, WidgetProps } from "widgets/BaseWidget"; import { WidgetType } from "constants/WidgetConstants"; import { + EvaluationReduxAction, ReduxAction, ReduxActionTypes, UpdateCanvasPayload, @@ -46,9 +47,13 @@ export const fetchPublishedPage = (pageId: string, bustCache = false) => ({ }, }); -export const fetchPageSuccess = () => { +export const fetchPageSuccess = ( + postEvalActions: ReduxAction[], +): EvaluationReduxAction => { return { type: ReduxActionTypes.FETCH_PAGE_SUCCESS, + payload: {}, + postEvalActions, }; }; @@ -60,9 +65,11 @@ export type FetchPublishedPageSuccessPayload = { export const fetchPublishedPageSuccess = ( payload: FetchPublishedPageSuccessPayload, -) => ({ + postEvalActions: ReduxAction[], +): EvaluationReduxAction => ({ type: ReduxActionTypes.FETCH_PUBLISHED_PAGE_SUCCESS, payload, + postEvalActions, }); export const updateCurrentPage = (id: string) => ({ diff --git a/app/client/src/actions/widgetActions.tsx b/app/client/src/actions/widgetActions.tsx index c617e85f35..e75b83e9c0 100644 --- a/app/client/src/actions/widgetActions.tsx +++ b/app/client/src/actions/widgetActions.tsx @@ -30,11 +30,10 @@ export const executeActionError = ( export const executePageLoadActions = ( payload: PageAction[][], -): BatchAction => - batchAction({ - type: ReduxActionTypes.EXECUTE_PAGE_LOAD_ACTIONS, - payload, - }); +): ReduxAction => ({ + type: ReduxActionTypes.EXECUTE_PAGE_LOAD_ACTIONS, + payload, +}); export const disableDragAction = ( isDraggingDisabled: boolean, diff --git a/app/client/src/constants/ReduxActionConstants.tsx b/app/client/src/constants/ReduxActionConstants.tsx index 692b88d1be..ffd5ae511c 100644 --- a/app/client/src/constants/ReduxActionConstants.tsx +++ b/app/client/src/constants/ReduxActionConstants.tsx @@ -410,6 +410,11 @@ export type ReduxActionWithoutPayload = Pick, "type">; export interface ReduxActionWithMeta extends ReduxAction { meta: M; } + +export interface EvaluationReduxAction extends ReduxAction { + postEvalActions?: ReduxAction[]; +} + export interface PromisePayload { reject: any; resolve: any; diff --git a/app/client/src/sagas/PageSagas.tsx b/app/client/src/sagas/PageSagas.tsx index 3dd72719fd..04ef3fa647 100644 --- a/app/client/src/sagas/PageSagas.tsx +++ b/app/client/src/sagas/PageSagas.tsx @@ -43,6 +43,7 @@ import { select, takeLatest, takeLeading, + take, } from "redux-saga/effects"; import history from "utils/history"; import { BUILDER_PAGE_URL } from "constants/routes"; @@ -173,9 +174,12 @@ export function* fetchPageSaga( // set current page yield put(updateCurrentPage(id)); // dispatch fetch page success - yield put(fetchPageSuccess()); - // Execute page load actions - yield put(executePageLoadActions(canvasWidgetsPayload.pageActions)); + yield put( + fetchPageSuccess([ + // Execute page load actions after evaluation of fetch page + executePageLoadActions(canvasWidgetsPayload.pageActions), + ]), + ); // Add this to the page DSLs for entity explorer yield put({ @@ -237,17 +241,19 @@ export function* fetchPublishedPageSaga( yield put(updateCurrentPage(pageId)); // dispatch fetch page success yield put( - fetchPublishedPageSuccess({ - dsl: response.data.layouts[0].dsl, - pageId: request.pageId, - pageWidgetId: canvasWidgetsPayload.pageWidgetId, - }), + fetchPublishedPageSuccess( + { + dsl: response.data.layouts[0].dsl, + pageId: request.pageId, + pageWidgetId: canvasWidgetsPayload.pageWidgetId, + }, + // Execute page load actions post published page eval + [executePageLoadActions(canvasWidgetsPayload.pageActions)], + ), ); - // Execute page load actions PerformanceTracker.stopAsyncTracking( PerformanceTransactionName.FETCH_PAGE_API, ); - yield put(executePageLoadActions(canvasWidgetsPayload.pageActions)); } } catch (error) { PerformanceTracker.stopAsyncTracking( diff --git a/app/client/src/sagas/evaluationsSaga.ts b/app/client/src/sagas/evaluationsSaga.ts index a5d0ac953f..105edc071a 100644 --- a/app/client/src/sagas/evaluationsSaga.ts +++ b/app/client/src/sagas/evaluationsSaga.ts @@ -9,11 +9,15 @@ import { } from "redux-saga/effects"; import { eventChannel, EventChannel } from "redux-saga"; import { + EvaluationReduxAction, ReduxAction, ReduxActionErrorTypes, ReduxActionTypes, } from "constants/ReduxActionConstants"; -import { getUnevaluatedDataTree } from "selectors/dataTreeSelectors"; +import { + getDataTree, + getUnevaluatedDataTree, +} from "selectors/dataTreeSelectors"; import WidgetFactory, { WidgetTypeConfigMap } from "../utils/WidgetFactory"; import Worker from "worker-loader!../workers/evaluation.worker"; import { @@ -27,12 +31,19 @@ import log from "loglevel"; import _ from "lodash"; import { WidgetType } from "../constants/WidgetConstants"; import { WidgetProps } from "../widgets/BaseWidget"; +import PerformanceTracker, { + PerformanceTransactionName, +} from "../utils/PerformanceTracker"; let evaluationWorker: Worker; let workerChannel: EventChannel; let widgetTypeConfigMap: WidgetTypeConfigMap; const initEvaluationWorkers = () => { + // If an old worker exists, terminate it + if (evaluationWorker) { + evaluationWorker.terminate(); + } widgetTypeConfigMap = WidgetFactory.getWidgetTypeConfigMap(); evaluationWorker = new Worker(); workerChannel = eventChannel(emitter => { @@ -56,7 +67,16 @@ const evalErrorHandler = (errors: EvalError[]) => { }); }; -function* evaluateTreeSaga() { +function* postEvalActionDispatcher(actions: ReduxAction[]) { + for (const action of actions) { + yield put(action); + } +} + +function* evaluateTreeSaga(postEvalActions?: ReduxAction[]) { + PerformanceTracker.startAsyncTracking( + PerformanceTransactionName.DATA_TREE_EVALUATION, + ); const unEvalTree = yield select(getUnevaluatedDataTree); log.debug({ unEvalTree }); evaluationWorker.postMessage({ @@ -73,14 +93,20 @@ function* evaluateTreeSaga() { type: ReduxActionTypes.SET_EVALUATED_TREE, payload: parsedDataTree, }); + PerformanceTracker.stopAsyncTracking( + PerformanceTransactionName.DATA_TREE_EVALUATION, + ); + if (postEvalActions && postEvalActions.length) { + yield call(postEvalActionDispatcher, postEvalActions); + } } export function* evaluateSingleValue(binding: string) { if (evaluationWorker) { - const unEvalTree = yield select(getUnevaluatedDataTree); + const dataTree = yield select(getDataTree); evaluationWorker.postMessage({ action: EVAL_WORKER_ACTIONS.EVAL_SINGLE, - dataTree: unEvalTree, + dataTree, binding, }); const workerResponse = yield take(workerChannel); @@ -190,14 +216,19 @@ const EVALUATE_REDUX_ACTIONS = [ function* evaluationChangeListenerSaga() { initEvaluationWorkers(); - yield call(evaluateTreeSaga); + yield fork(evaluateTreeSaga); while (true) { - const action: ReduxAction = yield take(EVALUATE_REDUX_ACTIONS); + const action: EvaluationReduxAction = yield take( + EVALUATE_REDUX_ACTIONS, + ); // When batching success action happens, we need to only evaluate // if the batch had any action we need to evaluate properties for - if (action.type === ReduxActionTypes.BATCH_UPDATES_SUCCESS) { + if ( + action.type === ReduxActionTypes.BATCH_UPDATES_SUCCESS && + Array.isArray(action.payload) + ) { const batchedActionTypes = action.payload.map( - (batchedAction: ReduxAction) => batchedAction.type, + (batchedAction: ReduxAction) => batchedAction.type, ); if ( _.intersection(EVALUATE_REDUX_ACTIONS, batchedActionTypes).length === 0 @@ -206,7 +237,7 @@ function* evaluationChangeListenerSaga() { } } log.debug(`Evaluating`, { action }); - yield fork(evaluateTreeSaga); + yield fork(evaluateTreeSaga, action.postEvalActions); } // TODO(hetu) need an action to stop listening and evaluate (exit app) } diff --git a/app/client/src/selectors/dataTreeSelectors.ts b/app/client/src/selectors/dataTreeSelectors.ts index eabc38fe13..4980b443c1 100644 --- a/app/client/src/selectors/dataTreeSelectors.ts +++ b/app/client/src/selectors/dataTreeSelectors.ts @@ -3,7 +3,6 @@ import { getActionsForCurrentPage, getAppData } from "./entitiesSelector"; import { ActionDataState } from "reducers/entityReducers/actionsReducer"; import { DataTree, DataTreeFactory } from "entities/DataTree/dataTreeFactory"; import { getWidgets, getWidgetsMeta } from "sagas/selectors"; -import * as log from "loglevel"; import "url-search-params-polyfill"; import { getPageList } from "./appViewSelectors"; import PerformanceTracker, { diff --git a/app/client/src/workers/evaluation.worker.ts b/app/client/src/workers/evaluation.worker.ts index 8d0337d295..76f1cbd31a 100644 --- a/app/client/src/workers/evaluation.worker.ts +++ b/app/client/src/workers/evaluation.worker.ts @@ -63,8 +63,7 @@ ctx.addEventListener("message", e => { } case EVAL_WORKER_ACTIONS.EVAL_SINGLE: { const { binding, dataTree } = rest; - const evalTree = getEvaluatedDataTree(dataTree); - const withFunctions = addFunctions(evalTree); + const withFunctions = addFunctions(dataTree); const value = getDynamicValue(binding, withFunctions, false); ctx.postMessage({ value, errors: ERRORS }); ERRORS = [];