Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 71 additions & 9 deletions apps/sidecar/src/workflow-substrate-factory/child-runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,27 @@ import {
type SourcesSnapshotRef,
} from "@intx/workflow-host";
import type { MailPartReader } from "@intx/types/runtime";
import { reportError } from "@corbits/error-sink";

import {
parseStepInferenceSources,
type StepInferenceSourceTable,
} from "./config";

function fireAndForget(
work: Promise<unknown>,
operation: string,
childRunId: string,
report: typeof reportError,
): void {
void work.catch((error: unknown) => {
report(error, {
operation,
extra: { childRunId },
});
});
}

/**
* Real per-step invoker for an onTrigger BODY child, distinct from the
* `StepInvoker` stub the shared `SidecarRunChildDeps.invokeStep` carries for
Expand Down Expand Up @@ -154,6 +169,27 @@ export interface SidecarRunChildDeps {
* a monotonic counter combined with a random suffix.
*/
newId?: (prefix: string) => string;
/**
* Test seam only — no production caller ever sets this. Defaults to
* `@intx/workflow`'s `runtimeRun`. Exists because bun's `mock.module`
* replaces a module process-wide and cannot be undone for later files
* in the same `bun test` process.
*/
runtimeRun?: typeof runtimeRun;
/**
* Test seam only — no production caller ever sets this. Defaults to
* `@corbits/error-sink`'s `reportError`. Paired with `runtimeRun` so a
* cancel-rejection test can observe reports without a process-wide
* module swap.
*/
reportError?: typeof reportError;
/**
* Test seam only — no production caller ever sets this. Defaults to
* `@intx/workflow-host`'s `createWorkflowHostSignalChannel`. Paired with
* `reportError` so a stop-rejection test can observe reports without a
* process-wide module swap.
*/
createSignalChannel?: typeof createWorkflowHostSignalChannel;
}

/**
Expand Down Expand Up @@ -184,6 +220,8 @@ export function createSidecarRunChild(
const directors = deps.directors ?? createDefaultDirectorRegistry();
const clock = deps.clock ?? defaultClock;
const newId = deps.newId ?? defaultNewId;
const startRun = deps.runtimeRun ?? runtimeRun;
const report = deps.reportError ?? reportError;
// The in-process child runs under real supervisor authority; its
// control-plane cancel (`CancelRequested`) must be signed by a supervisor
// principal, which the kind handler requires and the substrate authorizes
Expand Down Expand Up @@ -234,7 +272,7 @@ export function createSidecarRunChild(
childRunId,
});
try {
const handle = runtimeRun(rewrittenDefinition, env, {
const handle = startRun(rewrittenDefinition, env, {
runId: childRunId,
triggerPayload: input,
});
Expand All @@ -245,7 +283,12 @@ export function createSidecarRunChild(
// workflow-process-signed cancel would be refused and a parent abort
// would surface as a failed rather than cancelled child.
const cancelOnAbort = (): void => {
void handle.cancel("supervisor-operator", "parent cancelled");
fireAndForget(
handle.cancel("supervisor-operator", "parent cancelled"),
"sidecar.child-runtime.cancel",
childRunId,
report,
);
};
if (signal.aborted) {
cancelOnAbort();
Expand Down Expand Up @@ -303,6 +346,8 @@ export function createSidecarSpawnSuspendableChild(
const directors = deps.directors ?? createDefaultDirectorRegistry();
const clock = deps.clock ?? defaultClock;
const newId = deps.newId ?? defaultNewId;
const startRun = deps.runtimeRun ?? runtimeRun;
const report = deps.reportError ?? reportError;
// The in-process body child runs under real supervisor authority; its
// control-plane cancel (`CancelRequested`) must be signed by a supervisor
// principal, which the kind handler requires and the substrate authorizes
Expand Down Expand Up @@ -455,7 +500,7 @@ export function createSidecarSpawnSuspendableChild(
// silently (a re-park does not re-fire onPark), and the caller relays
// the grant via resume on the correlation it recovered from its own
// log. On a fresh spawn, seed the run with the event's trigger payload.
const handle = runtimeRun(
const handle = startRun(
rewrittenDefinition,
env,
resumeFromEvents !== undefined
Expand All @@ -470,7 +515,12 @@ export function createSidecarSpawnSuspendableChild(
// cancel would be refused and a parent abort would surface as a failed
// rather than cancelled child.
const cancelOnAbort = (): void => {
void handle.cancel("supervisor-operator", "parent cancelled");
fireAndForget(
handle.cancel("supervisor-operator", "parent cancelled"),
"sidecar.child-runtime.cancel",
childRunId,
report,
);
};
if (signal.aborted) {
cancelOnAbort();
Expand All @@ -491,7 +541,12 @@ export function createSidecarSpawnSuspendableChild(
})
.finally(() => {
signal.removeEventListener("abort", cancelOnAbort);
void signalChannel.stop();
fireAndForget(
signalChannel.stop(),
"sidecar.child-runtime.signal-channel-stop",
childRunId,
report,
);
notify();
});

Expand All @@ -505,9 +560,14 @@ export function createSidecarSpawnSuspendableChild(
// Cancel the child so its terminal (and the channel teardown
// tied to it) fires, then surface the error: the throw lands
// the section run's terminal via `runOnTrigger`.
void handle.cancel(
"supervisor-operator",
"onTrigger body re-armed an unsupported input park",
fireAndForget(
handle.cancel(
"supervisor-operator",
"onTrigger body re-armed an unsupported input park",
),
"sidecar.child-runtime.cancel",
childRunId,
report,
);
throw event.error;
}
Expand Down Expand Up @@ -582,7 +642,9 @@ function buildChildRunEnv(args: {
runId: childRunId,
ref: deps.workflowRunRef,
});
const signalChannel = createWorkflowHostSignalChannel({
const startChannel =
deps.createSignalChannel ?? createWorkflowHostSignalChannel;
const signalChannel = startChannel({
repoStore: deps.substrate,
principal: deps.principal,
repoId: deps.workflowRunRepoId,
Expand Down
Loading
Loading