From 52a46b9e4874a4f94fdce368e92e4f6cb0de624e Mon Sep 17 00:00:00 2001 From: Carolina Herbster Date: Mon, 23 Oct 2023 12:39:02 -0300 Subject: [PATCH 1/7] v1 --- .../Data/Math/flowGraphNumberMathBlocks.ts | 22 ++++++++++++++++++- .../Data/flowGraphBinaryOperationBlock.ts | 4 ++-- .../core/src/FlowGraph/flowGraphContext.ts | 22 +++++++++++++++++++ .../src/FlowGraph/flowGraphCoordinator.ts | 7 ++++++ .../core/src/FlowGraph/flowGraphEventBlock.ts | 1 + .../FlowGraph/flowGraphSignalConnection.ts | 2 ++ 6 files changed, 55 insertions(+), 3 deletions(-) diff --git a/packages/dev/core/src/FlowGraph/Blocks/Data/Math/flowGraphNumberMathBlocks.ts b/packages/dev/core/src/FlowGraph/Blocks/Data/Math/flowGraphNumberMathBlocks.ts index ec21dd0496a..563e55693a3 100644 --- a/packages/dev/core/src/FlowGraph/Blocks/Data/Math/flowGraphNumberMathBlocks.ts +++ b/packages/dev/core/src/FlowGraph/Blocks/Data/Math/flowGraphNumberMathBlocks.ts @@ -7,6 +7,7 @@ import { FlowGraphUnaryOperationBlock } from "../flowGraphUnaryOperationBlock"; import type { FlowGraphDataConnection } from "../../../flowGraphDataConnection"; import type { FlowGraphContext } from "../../../flowGraphContext"; import { RegisterClass } from "../../../../Misc/typeStore"; +import { FlowGraphCoordinator } from "core/FlowGraph/flowGraphCoordinator"; /** * Module for all of the number math blocks. * @see https://docs.google.com/spreadsheets/d/1wSFUFLPpRFVlL-va3YtYC6sepNvPapVawG1-nzoTF34/edit#gid=0 @@ -357,7 +358,26 @@ const RNDNAME = "FGRandomNumberBlock"; */ export class FlowGraphRandomNumberBlock extends FlowGraphBinaryOperationBlock { constructor(config?: IFlowGraphBlockConfiguration) { - super(RichTypeNumber, RichTypeNumber, RichTypeNumber, (left, right) => left + Math.random() * (right - left), RNDNAME, config); + super( + RichTypeNumber, + RichTypeNumber, + RichTypeNumber, + (left, right, context) => { + // Check if there is already a cached value for this execution id + unique id + const executionId = context.executionId; + const cachedValue = FlowGraphCoordinator.globalContext._getExecutionVariable(context._firingBlock, RNDNAME + executionId); + if (cachedValue !== undefined) { + return cachedValue; + } else { + const value = left + Math.random() * (right - left); + // Cache the value for this execution id + unique id + FlowGraphCoordinator.globalContext._setExecutionVariable(context._firingBlock, RNDNAME + executionId, value); + return value; + } + }, + RNDNAME, + config + ); } } RegisterClass(RNDNAME, FlowGraphRandomNumberBlock); diff --git a/packages/dev/core/src/FlowGraph/Blocks/Data/flowGraphBinaryOperationBlock.ts b/packages/dev/core/src/FlowGraph/Blocks/Data/flowGraphBinaryOperationBlock.ts index 7b18dd66719..c41286e48d8 100644 --- a/packages/dev/core/src/FlowGraph/Blocks/Data/flowGraphBinaryOperationBlock.ts +++ b/packages/dev/core/src/FlowGraph/Blocks/Data/flowGraphBinaryOperationBlock.ts @@ -17,7 +17,7 @@ export class FlowGraphBinaryOperationBlock extends FlowG leftRichType: RichType, rightRichType: RichType, resultRichType: RichType, - private _operation: (left: LeftT, right: RightT) => ResultT, + private _operation: (left: LeftT, right: RightT, context: FlowGraphContext) => ResultT, private _className: string, config?: IFlowGraphBlockConfiguration ) { @@ -28,7 +28,7 @@ export class FlowGraphBinaryOperationBlock extends FlowG } public _updateOutputs(_context: FlowGraphContext): void { - this.output.setValue(this._operation(this.leftInput.getValue(_context), this.rightInput.getValue(_context)), _context); + this.output.setValue(this._operation(this.leftInput.getValue(_context), this.rightInput.getValue(_context), _context), _context); } public getClassName(): string { diff --git a/packages/dev/core/src/FlowGraph/flowGraphContext.ts b/packages/dev/core/src/FlowGraph/flowGraphContext.ts index 061fadbd563..c0e178dc490 100644 --- a/packages/dev/core/src/FlowGraph/flowGraphContext.ts +++ b/packages/dev/core/src/FlowGraph/flowGraphContext.ts @@ -6,6 +6,7 @@ import type { FlowGraphBlock } from "./flowGraphBlock"; import type { FlowGraphDataConnection } from "./flowGraphDataConnection"; import type { FlowGraphEventCoordinator } from "./flowGraphEventCoordinator"; import type { FlowGraph } from "./flowGraph"; +import { FlowGraphEventBlock } from "./flowGraphEventBlock"; function isMeshClassName(className: string) { return ( @@ -90,6 +91,16 @@ export class FlowGraphContext { * These are blocks that have currently pending tasks/listeners that need to be cleaned up. */ private _pendingBlocks: FlowGraphAsyncExecutionBlock[] = []; + /** + * An monotonically increasing ID for each execution. + * Incremented every for every block executed. + */ + private _executionId = 0; + /** + * @internal + * Corresponds to the block that fired execution of the context + */ + public _firingBlock: FlowGraphEventBlock; constructor(params: IFlowGraphContextConfiguration) { this._configuration = params; @@ -243,6 +254,17 @@ export class FlowGraphContext { this._pendingBlocks.length = 0; } + /** + * @internal + */ + public _increaseExecutionId() { + this._executionId++; + } + + public get executionId() { + return this._executionId; + } + /** * Serializes a context * @param serializationObject the object to write the values in diff --git a/packages/dev/core/src/FlowGraph/flowGraphCoordinator.ts b/packages/dev/core/src/FlowGraph/flowGraphCoordinator.ts index 88250af2696..942c3e358fd 100644 --- a/packages/dev/core/src/FlowGraph/flowGraphCoordinator.ts +++ b/packages/dev/core/src/FlowGraph/flowGraphCoordinator.ts @@ -1,5 +1,6 @@ import type { Scene } from "../scene"; import { FlowGraph } from "./flowGraph"; +import { FlowGraphContext } from "./flowGraphContext"; import { FlowGraphEventCoordinator } from "./flowGraphEventCoordinator"; /** @@ -29,6 +30,8 @@ export class FlowGraphCoordinator { public readonly eventCoordinator: FlowGraphEventCoordinator; private readonly _flowGraphs: FlowGraph[] = []; + public static globalContext: FlowGraphContext; + constructor(private _config: IFlowGraphCoordinatorConfiguration) { this.eventCoordinator = new FlowGraphEventCoordinator(); @@ -40,6 +43,10 @@ export class FlowGraphCoordinator { // Add itself to the SceneCoordinators list for the Inspector. const coordinators = FlowGraphCoordinator.SceneCoordinators.get(this._config.scene) ?? []; coordinators.push(this); + + if (!FlowGraphCoordinator.globalContext) { + FlowGraphCoordinator.globalContext = new FlowGraphContext({ scene: this._config.scene, eventCoordinator: this.eventCoordinator }); + } } /** diff --git a/packages/dev/core/src/FlowGraph/flowGraphEventBlock.ts b/packages/dev/core/src/FlowGraph/flowGraphEventBlock.ts index 1642c416a80..86ef41da616 100644 --- a/packages/dev/core/src/FlowGraph/flowGraphEventBlock.ts +++ b/packages/dev/core/src/FlowGraph/flowGraphEventBlock.ts @@ -11,6 +11,7 @@ export abstract class FlowGraphEventBlock extends FlowGraphAsyncExecutionBlock { * @internal */ public _execute(context: FlowGraphContext): void { + context._firingBlock = this; this.onDone._activateSignal(context); } } diff --git a/packages/dev/core/src/FlowGraph/flowGraphSignalConnection.ts b/packages/dev/core/src/FlowGraph/flowGraphSignalConnection.ts index 1d23295458a..5f135011268 100644 --- a/packages/dev/core/src/FlowGraph/flowGraphSignalConnection.ts +++ b/packages/dev/core/src/FlowGraph/flowGraphSignalConnection.ts @@ -23,7 +23,9 @@ export class FlowGraphSignalConnection extends FlowGraphConnection Date: Mon, 23 Oct 2023 14:14:29 -0300 Subject: [PATCH 2/7] v2 --- .../Data/Math/flowGraphNumberMathBlocks.ts | 22 +------- .../Data/flowGraphBinaryOperationBlock.ts | 12 ++++- .../Data/flowGraphCachedOperationBlock.ts | 8 +++ .../core/src/FlowGraph/flowGraphContext.ts | 6 +-- .../src/FlowGraph/flowGraphCoordinator.ts | 7 --- .../core/src/FlowGraph/flowGraphEventBlock.ts | 1 - .../FlowGraph/flowGraphSignalConnection.ts | 3 +- .../unit/FlowGraph/flowGraphDataNodes.test.ts | 51 ++++++++++++++++++- .../FlowGraph/flowGraphExecutionNodes.test.ts | 1 - 9 files changed, 74 insertions(+), 37 deletions(-) create mode 100644 packages/dev/core/src/FlowGraph/Blocks/Data/flowGraphCachedOperationBlock.ts diff --git a/packages/dev/core/src/FlowGraph/Blocks/Data/Math/flowGraphNumberMathBlocks.ts b/packages/dev/core/src/FlowGraph/Blocks/Data/Math/flowGraphNumberMathBlocks.ts index 563e55693a3..ec21dd0496a 100644 --- a/packages/dev/core/src/FlowGraph/Blocks/Data/Math/flowGraphNumberMathBlocks.ts +++ b/packages/dev/core/src/FlowGraph/Blocks/Data/Math/flowGraphNumberMathBlocks.ts @@ -7,7 +7,6 @@ import { FlowGraphUnaryOperationBlock } from "../flowGraphUnaryOperationBlock"; import type { FlowGraphDataConnection } from "../../../flowGraphDataConnection"; import type { FlowGraphContext } from "../../../flowGraphContext"; import { RegisterClass } from "../../../../Misc/typeStore"; -import { FlowGraphCoordinator } from "core/FlowGraph/flowGraphCoordinator"; /** * Module for all of the number math blocks. * @see https://docs.google.com/spreadsheets/d/1wSFUFLPpRFVlL-va3YtYC6sepNvPapVawG1-nzoTF34/edit#gid=0 @@ -358,26 +357,7 @@ const RNDNAME = "FGRandomNumberBlock"; */ export class FlowGraphRandomNumberBlock extends FlowGraphBinaryOperationBlock { constructor(config?: IFlowGraphBlockConfiguration) { - super( - RichTypeNumber, - RichTypeNumber, - RichTypeNumber, - (left, right, context) => { - // Check if there is already a cached value for this execution id + unique id - const executionId = context.executionId; - const cachedValue = FlowGraphCoordinator.globalContext._getExecutionVariable(context._firingBlock, RNDNAME + executionId); - if (cachedValue !== undefined) { - return cachedValue; - } else { - const value = left + Math.random() * (right - left); - // Cache the value for this execution id + unique id - FlowGraphCoordinator.globalContext._setExecutionVariable(context._firingBlock, RNDNAME + executionId, value); - return value; - } - }, - RNDNAME, - config - ); + super(RichTypeNumber, RichTypeNumber, RichTypeNumber, (left, right) => left + Math.random() * (right - left), RNDNAME, config); } } RegisterClass(RNDNAME, FlowGraphRandomNumberBlock); diff --git a/packages/dev/core/src/FlowGraph/Blocks/Data/flowGraphBinaryOperationBlock.ts b/packages/dev/core/src/FlowGraph/Blocks/Data/flowGraphBinaryOperationBlock.ts index c41286e48d8..bb685a2f742 100644 --- a/packages/dev/core/src/FlowGraph/Blocks/Data/flowGraphBinaryOperationBlock.ts +++ b/packages/dev/core/src/FlowGraph/Blocks/Data/flowGraphBinaryOperationBlock.ts @@ -17,7 +17,7 @@ export class FlowGraphBinaryOperationBlock extends FlowG leftRichType: RichType, rightRichType: RichType, resultRichType: RichType, - private _operation: (left: LeftT, right: RightT, context: FlowGraphContext) => ResultT, + private _operation: (left: LeftT, right: RightT) => ResultT, private _className: string, config?: IFlowGraphBlockConfiguration ) { @@ -28,7 +28,15 @@ export class FlowGraphBinaryOperationBlock extends FlowG } public _updateOutputs(_context: FlowGraphContext): void { - this.output.setValue(this._operation(this.leftInput.getValue(_context), this.rightInput.getValue(_context), _context), _context); + // Search for a cached value + const cachedValue = _context._getExecutionVariable(this, "cachedValue" + _context.executionId); + if (cachedValue !== undefined) { + this.output.setValue(cachedValue, _context); + return; + } + const calculatedValue = this._operation(this.leftInput.getValue(_context), this.rightInput.getValue(_context)); + _context._setExecutionVariable(this, "cachedValue" + _context.executionId, calculatedValue); + this.output.setValue(calculatedValue, _context); } public getClassName(): string { diff --git a/packages/dev/core/src/FlowGraph/Blocks/Data/flowGraphCachedOperationBlock.ts b/packages/dev/core/src/FlowGraph/Blocks/Data/flowGraphCachedOperationBlock.ts new file mode 100644 index 00000000000..78190ddcf38 --- /dev/null +++ b/packages/dev/core/src/FlowGraph/Blocks/Data/flowGraphCachedOperationBlock.ts @@ -0,0 +1,8 @@ +import { FlowGraphBlock } from "core/FlowGraph/flowGraphBlock"; +import { FlowGraphContext } from "core/FlowGraph/flowGraphContext"; + +const CACHE_NAME = "cachedValue"; + +export class FlowGraphCachedOperationBlock extends FlowGraphBlock { + public _updateOutputs(context: FlowGraphContext) {} +} diff --git a/packages/dev/core/src/FlowGraph/flowGraphContext.ts b/packages/dev/core/src/FlowGraph/flowGraphContext.ts index c0e178dc490..de837ae8883 100644 --- a/packages/dev/core/src/FlowGraph/flowGraphContext.ts +++ b/packages/dev/core/src/FlowGraph/flowGraphContext.ts @@ -6,7 +6,7 @@ import type { FlowGraphBlock } from "./flowGraphBlock"; import type { FlowGraphDataConnection } from "./flowGraphDataConnection"; import type { FlowGraphEventCoordinator } from "./flowGraphEventCoordinator"; import type { FlowGraph } from "./flowGraph"; -import { FlowGraphEventBlock } from "./flowGraphEventBlock"; +import type { FlowGraphExecutionBlock } from "./flowGraphExecutionBlock"; function isMeshClassName(className: string) { return ( @@ -98,9 +98,9 @@ export class FlowGraphContext { private _executionId = 0; /** * @internal - * Corresponds to the block that fired execution of the context + * Corresponds to the currently executing block */ - public _firingBlock: FlowGraphEventBlock; + public _currentExecutionBlock: FlowGraphExecutionBlock; constructor(params: IFlowGraphContextConfiguration) { this._configuration = params; diff --git a/packages/dev/core/src/FlowGraph/flowGraphCoordinator.ts b/packages/dev/core/src/FlowGraph/flowGraphCoordinator.ts index 942c3e358fd..88250af2696 100644 --- a/packages/dev/core/src/FlowGraph/flowGraphCoordinator.ts +++ b/packages/dev/core/src/FlowGraph/flowGraphCoordinator.ts @@ -1,6 +1,5 @@ import type { Scene } from "../scene"; import { FlowGraph } from "./flowGraph"; -import { FlowGraphContext } from "./flowGraphContext"; import { FlowGraphEventCoordinator } from "./flowGraphEventCoordinator"; /** @@ -30,8 +29,6 @@ export class FlowGraphCoordinator { public readonly eventCoordinator: FlowGraphEventCoordinator; private readonly _flowGraphs: FlowGraph[] = []; - public static globalContext: FlowGraphContext; - constructor(private _config: IFlowGraphCoordinatorConfiguration) { this.eventCoordinator = new FlowGraphEventCoordinator(); @@ -43,10 +40,6 @@ export class FlowGraphCoordinator { // Add itself to the SceneCoordinators list for the Inspector. const coordinators = FlowGraphCoordinator.SceneCoordinators.get(this._config.scene) ?? []; coordinators.push(this); - - if (!FlowGraphCoordinator.globalContext) { - FlowGraphCoordinator.globalContext = new FlowGraphContext({ scene: this._config.scene, eventCoordinator: this.eventCoordinator }); - } } /** diff --git a/packages/dev/core/src/FlowGraph/flowGraphEventBlock.ts b/packages/dev/core/src/FlowGraph/flowGraphEventBlock.ts index 86ef41da616..1642c416a80 100644 --- a/packages/dev/core/src/FlowGraph/flowGraphEventBlock.ts +++ b/packages/dev/core/src/FlowGraph/flowGraphEventBlock.ts @@ -11,7 +11,6 @@ export abstract class FlowGraphEventBlock extends FlowGraphAsyncExecutionBlock { * @internal */ public _execute(context: FlowGraphContext): void { - context._firingBlock = this; this.onDone._activateSignal(context); } } diff --git a/packages/dev/core/src/FlowGraph/flowGraphSignalConnection.ts b/packages/dev/core/src/FlowGraph/flowGraphSignalConnection.ts index 5f135011268..2f3e57b3048 100644 --- a/packages/dev/core/src/FlowGraph/flowGraphSignalConnection.ts +++ b/packages/dev/core/src/FlowGraph/flowGraphSignalConnection.ts @@ -23,7 +23,8 @@ export class FlowGraphSignalConnection extends FlowGraphConnection { @@ -51,4 +58,46 @@ describe("Flow Graph Data Nodes", () => { expect(console.log).toHaveBeenCalledWith(42); expect(console.log).toHaveBeenCalledWith(43); }); + + it("Values are cached for the same execution id", () => { + const sceneReady = new FlowGraphSceneReadyEventBlock({ name: "SceneReady" }); + flowGraph.addEventBlock(sceneReady); + + const add = new FlowGraphAddNumberBlock(); + + const rnd = new FlowGraphRandomNumberBlock(); + rnd.leftInput.setValue(0, flowGraphContext); + rnd.rightInput.setValue(1, flowGraphContext); + + // add a number to itself, which should only trigger the random number block once and cache the result + add.leftInput.connectTo(rnd.output); + add.rightInput.connectTo(rnd.output); + + // log ther result + const log = new FlowGraphLogBlock(); + log.message.connectTo(add.output); + sceneReady.onDone.connectTo(log.onStart); + + flowGraph.start(); + + let mockRandomIndex = 1; + const mockedRandom = (): number => { + return mockRandomIndex++; + }; + + // clear the random mock before calling + const random = jest.spyOn(global.Math, "random").mockImplementation(mockedRandom); + + scene.onReadyObservable.notifyObservers(scene); + + expect(random).toHaveBeenCalledTimes(1); + expect(console.log).toHaveBeenCalledWith(2); // 1 + 1 + + random.mockRestore(); + }); + + afterEach(() => { + scene.dispose(); + engine.dispose(); + }); }); diff --git a/packages/dev/core/test/unit/FlowGraph/flowGraphExecutionNodes.test.ts b/packages/dev/core/test/unit/FlowGraph/flowGraphExecutionNodes.test.ts index 5d6a003d5b8..f0f9b8057eb 100644 --- a/packages/dev/core/test/unit/FlowGraph/flowGraphExecutionNodes.test.ts +++ b/packages/dev/core/test/unit/FlowGraph/flowGraphExecutionNodes.test.ts @@ -155,7 +155,6 @@ describe("Flow Graph Execution Nodes", () => { const sceneReady = new FlowGraphSceneReadyEventBlock(); flowGraph.addEventBlock(sceneReady); - debugger; const switchBlock = new FlowGraphSwitchBlock({ cases: [1, 2, 3] }); sceneReady.onDone.connectTo(switchBlock.onStart); switchBlock.selection.setValue(2, flowGraphContext); From 33fd378f29680dcc833fdfabb1190dd7a987aa7c Mon Sep 17 00:00:00 2001 From: Carolina Herbster Date: Mon, 23 Oct 2023 14:29:45 -0300 Subject: [PATCH 3/7] common cache class --- .../Data/flowGraphBinaryOperationBlock.ts | 20 ++++--------- .../Data/flowGraphCachedOperationBlock.ts | 29 ++++++++++++++++--- .../Data/flowGraphConstantOperationBlock.ts | 14 ++++----- .../Data/flowGraphUnaryOperationBlock.ts | 13 ++++----- .../core/src/FlowGraph/flowGraphContext.ts | 6 ---- .../FlowGraph/flowGraphSignalConnection.ts | 2 -- 6 files changed, 40 insertions(+), 44 deletions(-) diff --git a/packages/dev/core/src/FlowGraph/Blocks/Data/flowGraphBinaryOperationBlock.ts b/packages/dev/core/src/FlowGraph/Blocks/Data/flowGraphBinaryOperationBlock.ts index bb685a2f742..a863dd60bc6 100644 --- a/packages/dev/core/src/FlowGraph/Blocks/Data/flowGraphBinaryOperationBlock.ts +++ b/packages/dev/core/src/FlowGraph/Blocks/Data/flowGraphBinaryOperationBlock.ts @@ -1,17 +1,16 @@ import type { FlowGraphDataConnection } from "../../flowGraphDataConnection"; -import { FlowGraphBlock } from "../../flowGraphBlock"; import type { RichType } from "../../flowGraphRichTypes"; import type { FlowGraphContext } from "../../flowGraphContext"; import type { IFlowGraphBlockConfiguration } from "../../flowGraphBlock"; +import { FlowGraphCachedOperationBlock } from "./flowGraphCachedOperationBlock"; /** * @experimental * The base block for all binary operation blocks. Receives an input of type * LeftT, one of type RightT, and outputs a value of type ResultT. */ -export class FlowGraphBinaryOperationBlock extends FlowGraphBlock { +export class FlowGraphBinaryOperationBlock extends FlowGraphCachedOperationBlock { leftInput: FlowGraphDataConnection; rightInput: FlowGraphDataConnection; - output: FlowGraphDataConnection; constructor( leftRichType: RichType, @@ -21,22 +20,13 @@ export class FlowGraphBinaryOperationBlock extends FlowG private _className: string, config?: IFlowGraphBlockConfiguration ) { - super(config); + super(resultRichType, config); this.leftInput = this._registerDataInput("leftInput", leftRichType); this.rightInput = this._registerDataInput("rightInput", rightRichType); - this.output = this._registerDataOutput("Output", resultRichType); } - public _updateOutputs(_context: FlowGraphContext): void { - // Search for a cached value - const cachedValue = _context._getExecutionVariable(this, "cachedValue" + _context.executionId); - if (cachedValue !== undefined) { - this.output.setValue(cachedValue, _context); - return; - } - const calculatedValue = this._operation(this.leftInput.getValue(_context), this.rightInput.getValue(_context)); - _context._setExecutionVariable(this, "cachedValue" + _context.executionId, calculatedValue); - this.output.setValue(calculatedValue, _context); + public override _doOperation(context: FlowGraphContext): ResultT { + return this._operation(this.leftInput.getValue(context), this.rightInput.getValue(context)); } public getClassName(): string { diff --git a/packages/dev/core/src/FlowGraph/Blocks/Data/flowGraphCachedOperationBlock.ts b/packages/dev/core/src/FlowGraph/Blocks/Data/flowGraphCachedOperationBlock.ts index 78190ddcf38..11db6b7379e 100644 --- a/packages/dev/core/src/FlowGraph/Blocks/Data/flowGraphCachedOperationBlock.ts +++ b/packages/dev/core/src/FlowGraph/Blocks/Data/flowGraphCachedOperationBlock.ts @@ -1,8 +1,29 @@ -import { FlowGraphBlock } from "core/FlowGraph/flowGraphBlock"; -import { FlowGraphContext } from "core/FlowGraph/flowGraphContext"; +import type { IFlowGraphBlockConfiguration } from "../../flowGraphBlock"; +import { FlowGraphBlock } from "../../flowGraphBlock"; +import type { FlowGraphContext } from "../../flowGraphContext"; +import type { FlowGraphDataConnection } from "../../flowGraphDataConnection"; +import type { RichType } from "../../flowGraphRichTypes"; const CACHE_NAME = "cachedValue"; -export class FlowGraphCachedOperationBlock extends FlowGraphBlock { - public _updateOutputs(context: FlowGraphContext) {} +export abstract class FlowGraphCachedOperationBlock extends FlowGraphBlock { + public readonly output: FlowGraphDataConnection; + + constructor(outputRichType: RichType, config?: IFlowGraphBlockConfiguration) { + super(config); + + this.output = this._registerDataOutput("output", outputRichType); + } + public abstract _doOperation(context: FlowGraphContext): OutputT; + + public _updateOutputs(context: FlowGraphContext) { + const cachedValue = context._getExecutionVariable(this, CACHE_NAME + context.executionId); + if (cachedValue !== undefined) { + this.output.setValue(cachedValue, context); + return; + } + const calculatedValue = this._doOperation(context); + context._setExecutionVariable(this, CACHE_NAME + context.executionId, calculatedValue); + this.output.setValue(calculatedValue, context); + } } diff --git a/packages/dev/core/src/FlowGraph/Blocks/Data/flowGraphConstantOperationBlock.ts b/packages/dev/core/src/FlowGraph/Blocks/Data/flowGraphConstantOperationBlock.ts index 962fd2662c5..97ff2a693be 100644 --- a/packages/dev/core/src/FlowGraph/Blocks/Data/flowGraphConstantOperationBlock.ts +++ b/packages/dev/core/src/FlowGraph/Blocks/Data/flowGraphConstantOperationBlock.ts @@ -1,22 +1,18 @@ import type { FlowGraphContext } from "../../flowGraphContext"; -import { FlowGraphBlock } from "../../flowGraphBlock"; -import type { FlowGraphDataConnection } from "../../flowGraphDataConnection"; import type { RichType } from "../../flowGraphRichTypes"; import type { IFlowGraphBlockConfiguration } from "../../flowGraphBlock"; +import { FlowGraphCachedOperationBlock } from "./flowGraphCachedOperationBlock"; /** * @experimental * Block that outputs a value of type ResultT, resulting of an operation with no inputs. */ -export class FlowGraphConstantOperationBlock extends FlowGraphBlock { - public output: FlowGraphDataConnection; - +export class FlowGraphConstantOperationBlock extends FlowGraphCachedOperationBlock { constructor(richType: RichType, private _operation: () => ResultT, private _className: string, config?: IFlowGraphBlockConfiguration) { - super(config); - this.output = this._registerDataOutput("output", richType); + super(richType, config); } - public _updateOutputs(context: FlowGraphContext): void { - this.output.setValue(this._operation(), context); + public override _doOperation(_context: FlowGraphContext): ResultT { + return this._operation(); } public getClassName(): string { diff --git a/packages/dev/core/src/FlowGraph/Blocks/Data/flowGraphUnaryOperationBlock.ts b/packages/dev/core/src/FlowGraph/Blocks/Data/flowGraphUnaryOperationBlock.ts index 284ed123d52..9b9051cb203 100644 --- a/packages/dev/core/src/FlowGraph/Blocks/Data/flowGraphUnaryOperationBlock.ts +++ b/packages/dev/core/src/FlowGraph/Blocks/Data/flowGraphUnaryOperationBlock.ts @@ -1,16 +1,15 @@ import type { FlowGraphDataConnection } from "../../flowGraphDataConnection"; import type { IFlowGraphBlockConfiguration } from "../../flowGraphBlock"; -import { FlowGraphBlock } from "../../flowGraphBlock"; import type { RichType } from "../../flowGraphRichTypes"; import type { FlowGraphContext } from "../../flowGraphContext"; +import { FlowGraphCachedOperationBlock } from "./flowGraphCachedOperationBlock"; /** * @experimental * The base block for all unary operation blocks. Receives an input of type InputT, and outputs a value of type ResultT. */ -export class FlowGraphUnaryOperationBlock extends FlowGraphBlock { +export class FlowGraphUnaryOperationBlock extends FlowGraphCachedOperationBlock { input: FlowGraphDataConnection; - output: FlowGraphDataConnection; constructor( inputRichType: RichType, @@ -19,13 +18,11 @@ export class FlowGraphUnaryOperationBlock extends FlowGraphBloc private _className: string, config?: IFlowGraphBlockConfiguration ) { - super(config); + super(resultRichType, config); this.input = this._registerDataInput("input", inputRichType); - this.output = this._registerDataOutput("resultOutput", resultRichType); } - - public _updateOutputs(_context: FlowGraphContext): void { - this.output.setValue(this._operation(this.input.getValue(_context)), _context); + public override _doOperation(context: FlowGraphContext): ResultT { + return this._operation(this.input.getValue(context)); } public getClassName(): string { diff --git a/packages/dev/core/src/FlowGraph/flowGraphContext.ts b/packages/dev/core/src/FlowGraph/flowGraphContext.ts index de837ae8883..0f64da2c845 100644 --- a/packages/dev/core/src/FlowGraph/flowGraphContext.ts +++ b/packages/dev/core/src/FlowGraph/flowGraphContext.ts @@ -6,7 +6,6 @@ import type { FlowGraphBlock } from "./flowGraphBlock"; import type { FlowGraphDataConnection } from "./flowGraphDataConnection"; import type { FlowGraphEventCoordinator } from "./flowGraphEventCoordinator"; import type { FlowGraph } from "./flowGraph"; -import type { FlowGraphExecutionBlock } from "./flowGraphExecutionBlock"; function isMeshClassName(className: string) { return ( @@ -96,11 +95,6 @@ export class FlowGraphContext { * Incremented every for every block executed. */ private _executionId = 0; - /** - * @internal - * Corresponds to the currently executing block - */ - public _currentExecutionBlock: FlowGraphExecutionBlock; constructor(params: IFlowGraphContextConfiguration) { this._configuration = params; diff --git a/packages/dev/core/src/FlowGraph/flowGraphSignalConnection.ts b/packages/dev/core/src/FlowGraph/flowGraphSignalConnection.ts index 2f3e57b3048..39ff64453ea 100644 --- a/packages/dev/core/src/FlowGraph/flowGraphSignalConnection.ts +++ b/packages/dev/core/src/FlowGraph/flowGraphSignalConnection.ts @@ -23,8 +23,6 @@ export class FlowGraphSignalConnection extends FlowGraphConnection Date: Tue, 24 Oct 2023 17:05:57 -0300 Subject: [PATCH 4/7] change how cache is saved so it doesn't grow data infinitely --- .../Data/flowGraphCachedOperationBlock.ts | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/packages/dev/core/src/FlowGraph/Blocks/Data/flowGraphCachedOperationBlock.ts b/packages/dev/core/src/FlowGraph/Blocks/Data/flowGraphCachedOperationBlock.ts index 11db6b7379e..821e2455617 100644 --- a/packages/dev/core/src/FlowGraph/Blocks/Data/flowGraphCachedOperationBlock.ts +++ b/packages/dev/core/src/FlowGraph/Blocks/Data/flowGraphCachedOperationBlock.ts @@ -4,8 +4,12 @@ import type { FlowGraphContext } from "../../flowGraphContext"; import type { FlowGraphDataConnection } from "../../flowGraphDataConnection"; import type { RichType } from "../../flowGraphRichTypes"; -const CACHE_NAME = "cachedValue"; +const CACHE_NAME = "cachedOperationValue"; +const EXEC_ID_NAME = "executionId"; +/** + * @experimental + */ export abstract class FlowGraphCachedOperationBlock extends FlowGraphBlock { public readonly output: FlowGraphDataConnection; @@ -17,13 +21,15 @@ export abstract class FlowGraphCachedOperationBlock extends FlowGraphBl public abstract _doOperation(context: FlowGraphContext): OutputT; public _updateOutputs(context: FlowGraphContext) { - const cachedValue = context._getExecutionVariable(this, CACHE_NAME + context.executionId); - if (cachedValue !== undefined) { + const cachedExecutionId = context._getExecutionVariable(this, EXEC_ID_NAME); + const cachedValue = context._getExecutionVariable(this, CACHE_NAME); + if (cachedValue !== undefined && cachedExecutionId === context.executionId) { this.output.setValue(cachedValue, context); - return; + } else { + const calculatedValue = this._doOperation(context); + context._setExecutionVariable(this, CACHE_NAME, calculatedValue); + context._setExecutionVariable(this, EXEC_ID_NAME, context.executionId); + this.output.setValue(calculatedValue, context); } - const calculatedValue = this._doOperation(context); - context._setExecutionVariable(this, CACHE_NAME + context.executionId, calculatedValue); - this.output.setValue(calculatedValue, context); } } From 6ac34f8034b9ef8fa8874e01c9f982a68482bb9f Mon Sep 17 00:00:00 2001 From: Carolina Date: Wed, 25 Oct 2023 13:23:30 -0300 Subject: [PATCH 5/7] Update packages/dev/core/src/FlowGraph/flowGraphContext.ts Co-authored-by: Popov72 --- packages/dev/core/src/FlowGraph/flowGraphContext.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dev/core/src/FlowGraph/flowGraphContext.ts b/packages/dev/core/src/FlowGraph/flowGraphContext.ts index 0f64da2c845..217eaa679b2 100644 --- a/packages/dev/core/src/FlowGraph/flowGraphContext.ts +++ b/packages/dev/core/src/FlowGraph/flowGraphContext.ts @@ -92,7 +92,7 @@ export class FlowGraphContext { private _pendingBlocks: FlowGraphAsyncExecutionBlock[] = []; /** * An monotonically increasing ID for each execution. - * Incremented every for every block executed. + * Incremented for every block executed. */ private _executionId = 0; From cce830f8f18a9ff01222c760ae9e5e046541b209 Mon Sep 17 00:00:00 2001 From: Carolina Date: Wed, 25 Oct 2023 13:23:35 -0300 Subject: [PATCH 6/7] Update packages/dev/core/src/FlowGraph/flowGraphContext.ts Co-authored-by: Popov72 --- packages/dev/core/src/FlowGraph/flowGraphContext.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dev/core/src/FlowGraph/flowGraphContext.ts b/packages/dev/core/src/FlowGraph/flowGraphContext.ts index 217eaa679b2..0532d70ef60 100644 --- a/packages/dev/core/src/FlowGraph/flowGraphContext.ts +++ b/packages/dev/core/src/FlowGraph/flowGraphContext.ts @@ -91,7 +91,7 @@ export class FlowGraphContext { */ private _pendingBlocks: FlowGraphAsyncExecutionBlock[] = []; /** - * An monotonically increasing ID for each execution. + * A monotonically increasing ID for each execution. * Incremented for every block executed. */ private _executionId = 0; From 3472c1458cbf9737570c317eaa521521cb03f92e Mon Sep 17 00:00:00 2001 From: Carolina Herbster Date: Wed, 25 Oct 2023 13:25:41 -0300 Subject: [PATCH 7/7] review changes --- .../Blocks/Data/flowGraphCachedOperationBlock.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/dev/core/src/FlowGraph/Blocks/Data/flowGraphCachedOperationBlock.ts b/packages/dev/core/src/FlowGraph/Blocks/Data/flowGraphCachedOperationBlock.ts index 821e2455617..7bf3a2e930b 100644 --- a/packages/dev/core/src/FlowGraph/Blocks/Data/flowGraphCachedOperationBlock.ts +++ b/packages/dev/core/src/FlowGraph/Blocks/Data/flowGraphCachedOperationBlock.ts @@ -5,12 +5,15 @@ import type { FlowGraphDataConnection } from "../../flowGraphDataConnection"; import type { RichType } from "../../flowGraphRichTypes"; const CACHE_NAME = "cachedOperationValue"; -const EXEC_ID_NAME = "executionId"; +const CACHE_EXEC_ID_NAME = "cachedExecutionId"; /** * @experimental */ export abstract class FlowGraphCachedOperationBlock extends FlowGraphBlock { + /** + * The output of the operation + */ public readonly output: FlowGraphDataConnection; constructor(outputRichType: RichType, config?: IFlowGraphBlockConfiguration) { @@ -18,17 +21,23 @@ export abstract class FlowGraphCachedOperationBlock extends FlowGraphBl this.output = this._registerDataOutput("output", outputRichType); } + + /** + * @internal + * Operation to realize + * @param context the graph context + */ public abstract _doOperation(context: FlowGraphContext): OutputT; public _updateOutputs(context: FlowGraphContext) { - const cachedExecutionId = context._getExecutionVariable(this, EXEC_ID_NAME); + const cachedExecutionId = context._getExecutionVariable(this, CACHE_EXEC_ID_NAME); const cachedValue = context._getExecutionVariable(this, CACHE_NAME); if (cachedValue !== undefined && cachedExecutionId === context.executionId) { this.output.setValue(cachedValue, context); } else { const calculatedValue = this._doOperation(context); context._setExecutionVariable(this, CACHE_NAME, calculatedValue); - context._setExecutionVariable(this, EXEC_ID_NAME, context.executionId); + context._setExecutionVariable(this, CACHE_EXEC_ID_NAME, context.executionId); this.output.setValue(calculatedValue, context); } }