Skip to content

Commit

Permalink
Removes the cyclic dependency caused by Lambda (#188)
Browse files Browse the repository at this point in the history
The lambda node needs access to BoardRunner and BoardRunner loads Core.
Core requires Lambda, and boom. Cycle.
  • Loading branch information
PaulKinlan authored Nov 10, 2023
1 parent fefc7ba commit 3952344
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 74 deletions.
18 changes: 0 additions & 18 deletions seeds/breadboard/src/core.ts

This file was deleted.

5 changes: 4 additions & 1 deletion seeds/breadboard/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
export { Board } from "./board.js";
export { BoardRunner } from "./runner.js";
export { Node } from "./node.js";
export { SchemaBuilder } from "./schema.js";
export { LogProbe } from "./log.js";
export { DebugProbe } from "./debug.js";
export { RunResult } from "./run.js";
Expand Down Expand Up @@ -40,15 +41,17 @@ export type {
BreadboardSlotSpec,
BreadboardNode,
BreadboardCapability,
BreadboardRunner,
NodeHandlerContext,
OptionalIdConfiguration,
NodeConfigurationConstructor,
LambdaFunction,
LambdaNodeInputs,
ConfigOrLambda,
RunResultType,
KitConstructor,
GenericKit,
LambdaNodeOutputs,
LambdaNodeOutputs
} from "./types.js";
export { TraversalMachine } from "./traversal/machine.js";
export { MachineResult } from "./traversal/result.js";
Expand Down
50 changes: 0 additions & 50 deletions seeds/breadboard/src/nodes/lambda.ts

This file was deleted.

59 changes: 54 additions & 5 deletions seeds/breadboard/src/runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ import type {
NodeHandlerContext,
ProbeDetails,
BreadboardCapability,
LambdaNodeInputs,
LambdaNodeOutputs,
} from "./types.js";

import { TraversalMachine } from "./traversal/machine.js";
import { Core } from "./core.js";
import {
BeforeHandlerStageResult,
InputStageResult,
Expand All @@ -34,6 +35,7 @@ import { BoardLoader } from "./loader.js";
import { runRemote } from "./remote.js";
import { callHandler } from "./handler.js";
import { toMermaid } from "./mermaid.js";
import { SchemaBuilder } from "./schema.js";

class ProbeEvent extends CustomEvent<ProbeDetails> {
constructor(type: string, detail: ProbeDetails) {
Expand Down Expand Up @@ -184,8 +186,8 @@ export class BoardRunner implements BreadboardRunner {
shouldInvokeHandler
? callHandler(handler, inputs, newContext)
: beforehandlerDetail.outputs instanceof Promise
? beforehandlerDetail.outputs
: Promise.resolve(beforehandlerDetail.outputs)
? beforehandlerDetail.outputs
: Promise.resolve(beforehandlerDetail.outputs)
) as Promise<OutputValues>;

outputsPromise.then((outputs) => {
Expand Down Expand Up @@ -354,13 +356,14 @@ export class BoardRunner implements BreadboardRunner {

return runnableBoard;
}

static async handlersFromBoard(
board: BoardRunner,
upstreamKits: Kit[] = []
): Promise<NodeHandlers> {
const core = new Core();

const core = new Core()
const kits = [core, ...upstreamKits, ...board.kits];

return kits.reduce((handlers, kit) => {
// If multiple kits have the same handler, the kit earlier in the list
// gets precedence, including upstream kits getting precedence over kits
Expand All @@ -373,3 +376,49 @@ export class BoardRunner implements BreadboardRunner {

static runRemote = runRemote;
}

// HACK: Move the Core and Lambda logic into the same file as the BoardRunner to remove the cyclic module dependency (Lambda needs BoardRunner, BoardRunner needs Core).
class Core {
handlers: NodeHandlers;

constructor() {
this.handlers =
{
"lambda": {
describe: async (inputs?: InputValues) => ({
inputSchema: new SchemaBuilder()
.setAdditionalProperties(true)
.addInputs(inputs)
.addProperty("board", {
title: "board",
description: "The board to run.",
type: "object",
})
.build(),
outputSchema: new SchemaBuilder()
.addProperty("board", {
title: "board",
description: "The now-runnable board.",
type: "object",
})
.build(),
}),
invoke: async (inputs: InputValues): Promise<LambdaNodeOutputs> => {
const { board, ...args } = inputs as LambdaNodeInputs;
if (!board || board.kind !== "board" || !board.board)
throw new Error(
`Lambda node requires a BoardCapability as "board" input`
);
const runnableBoard = {
...(await BoardRunner.fromBreadboardCapability(board)),
args,
};

return {
board: { ...board, board: runnableBoard as GraphDescriptor },
};
},
}
};
}
}

0 comments on commit 3952344

Please sign in to comment.