@lunora/workflow 1.0.0-alpha.3 → 1.0.0-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/do/index.d.mts +1 -1
- package/dist/do/index.d.ts +1 -1
- package/dist/do/index.mjs +16 -4
- package/dist/index.d.mts +18 -3
- package/dist/index.d.ts +18 -3
- package/dist/index.mjs +2 -1
- package/dist/packem_shared/MAX_BRANCHES-C9MJIFii.mjs +108 -0
- package/dist/packem_shared/{createWorkflowRunContext-DJj_y0fa.mjs → createWorkflowRunContext-BsMyGuMR.mjs} +31 -0
- package/dist/packem_shared/{types.d-gNYxuUwu.d.mts → types.d-Fdeu2P2C.d.mts} +52 -2
- package/dist/packem_shared/{types.d-gNYxuUwu.d.ts → types.d-Fdeu2P2C.d.ts} +52 -2
- package/package.json +1 -1
package/dist/do/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { WorkflowEntrypoint, WorkflowEvent, WorkflowStep } from 'cloudflare:workers';
|
|
2
|
-
import { W as WorkflowDefinition } from "../packem_shared/types.d-
|
|
2
|
+
import { W as WorkflowDefinition } from "../packem_shared/types.d-Fdeu2P2C.mjs";
|
|
3
3
|
import '@lunora/values';
|
|
4
4
|
/**
|
|
5
5
|
* Base class for the generated `WorkflowEntrypoint` classes. Applies a
|
package/dist/do/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { WorkflowEntrypoint, WorkflowEvent, WorkflowStep } from 'cloudflare:workers';
|
|
2
|
-
import { W as WorkflowDefinition } from "../packem_shared/types.d-
|
|
2
|
+
import { W as WorkflowDefinition } from "../packem_shared/types.d-Fdeu2P2C.js";
|
|
3
3
|
import '@lunora/values';
|
|
4
4
|
/**
|
|
5
5
|
* Base class for the generated `WorkflowEntrypoint` classes. Applies a
|
package/dist/do/index.mjs
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { WorkflowEntrypoint } from 'cloudflare:workers';
|
|
2
2
|
import { NonRetryableError } from 'cloudflare:workflows';
|
|
3
3
|
import { convertNonRetryableError } from '../packem_shared/NonRetryableError-Dn2dTyBS.mjs';
|
|
4
|
-
import {
|
|
4
|
+
import { stripBranchMarker, signalBranchParent, extractBranchMarker, errorOutcome, okOutcome } from '../packem_shared/MAX_BRANCHES-C9MJIFii.mjs';
|
|
5
|
+
import { createWorkflowRunContext } from '../packem_shared/createWorkflowRunContext-BsMyGuMR.mjs';
|
|
5
6
|
|
|
6
7
|
class LunoraWorkflow extends WorkflowEntrypoint {
|
|
7
8
|
/** The `lunora/workflows.ts` export name, for log correlation. */
|
|
@@ -14,18 +15,29 @@ class LunoraWorkflow extends WorkflowEntrypoint {
|
|
|
14
15
|
this.#lunoraName = exportName ?? "workflow";
|
|
15
16
|
}
|
|
16
17
|
async run(event, step) {
|
|
18
|
+
const nativeStep = step;
|
|
19
|
+
const marker = extractBranchMarker(event.payload);
|
|
20
|
+
const handlerEvent = marker ? { ...event, payload: stripBranchMarker(event.payload) } : event;
|
|
17
21
|
const context = createWorkflowRunContext({
|
|
18
22
|
env: this.env,
|
|
19
|
-
event,
|
|
23
|
+
event: handlerEvent,
|
|
20
24
|
exportName: this.#lunoraName,
|
|
21
25
|
nonRetryableErrorClass: NonRetryableError,
|
|
22
|
-
step
|
|
26
|
+
step: nativeStep
|
|
23
27
|
});
|
|
28
|
+
let output;
|
|
24
29
|
try {
|
|
25
|
-
|
|
30
|
+
output = await this.#definition.handler(context);
|
|
26
31
|
} catch (error) {
|
|
32
|
+
if (marker) {
|
|
33
|
+
await signalBranchParent({ env: this.env, step: nativeStep }, marker, errorOutcome(error));
|
|
34
|
+
}
|
|
27
35
|
return convertNonRetryableError(error, NonRetryableError);
|
|
28
36
|
}
|
|
37
|
+
if (marker) {
|
|
38
|
+
await signalBranchParent({ env: this.env, step: nativeStep }, marker, okOutcome(output));
|
|
39
|
+
}
|
|
40
|
+
return output;
|
|
29
41
|
}
|
|
30
42
|
}
|
|
31
43
|
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as Workflows, L as LunoraWorkflowsOptions, S as StepArgsValidator, b as StepConfig, c as StepDefinition, d as WorkflowConfig, W as WorkflowDefinition, e as
|
|
2
|
-
export type { A as ArgsOf, F as FunctionReference, I as InferStepArgs, R as RunFunctionOptions,
|
|
1
|
+
import { a as Workflows, L as LunoraWorkflowsOptions, S as StepArgsValidator, b as StepConfig, c as StepDefinition, d as WorkflowConfig, W as WorkflowDefinition, e as WorkflowBranch, f as WorkflowInstanceStatus, g as WorkflowEventLike, h as WorkflowStepLike, i as WorkflowRunContext, j as WorkflowLogger, k as WorkflowRunFunction, l as WorkflowRunStepFunction } from "./packem_shared/types.d-Fdeu2P2C.mjs";
|
|
2
|
+
export type { A as ArgsOf, F as FunctionReference, I as InferStepArgs, R as RunFunctionOptions, m as RunStepOptions, n as StepHandler, o as StepRollbackContext, p as StepRollbackHandler, q as StepRunContext, r as WorkflowBindingLike, s as WorkflowBranchOutputs, t as WorkflowCreateOptions, u as WorkflowHandle, v as WorkflowHandler, w as WorkflowInstanceLike, x as WorkflowParallelFunction, y as WorkflowRollbackContextLike, z as WorkflowRollbackHandlerLike, B as WorkflowSpawnFunction, C as WorkflowSpawnOptions, D as WorkflowStatusResult, E as WorkflowStepConfigLike, G as WorkflowStepContextLike, H as WorkflowStepRollbackOptionsLike } from "./packem_shared/types.d-Fdeu2P2C.mjs";
|
|
3
3
|
import '@lunora/values';
|
|
4
4
|
/** Wiring info for one declared workflow, emitted by codegen into the generated shard. */
|
|
5
5
|
interface WorkflowBindingSpec {
|
|
@@ -131,6 +131,21 @@ declare const toNativeNonRetryableError: (error: NonRetryableError, NativeNonRet
|
|
|
131
131
|
* Always throws — the `never` return lets callers `return convertNonRetryableError(...)`.
|
|
132
132
|
*/
|
|
133
133
|
declare const convertNonRetryableError: (error: unknown, NativeNonRetryableError: NativeNonRetryableErrorConstructor | undefined) => never;
|
|
134
|
+
/** Hard cap on branches per `ctx.parallel` call — auto-scale, never silently spawn unbounded DOs. */
|
|
135
|
+
declare const MAX_BRANCHES = 100;
|
|
136
|
+
/** The params key the parent injects so a child knows to signal completion back. Stripped before the user handler sees `ctx.params`. */
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Build a single fan-out branch: a declared child workflow referenced by its
|
|
140
|
+
* `lunora/workflows.ts` export name, plus the params it is created with. Pass the
|
|
141
|
+
* output type as the generic argument so `ctx.parallel(...)` infers the result
|
|
142
|
+
* tuple — e.g. `branch("imageTag", { key })` typed as `branch` of `{ tags }`.
|
|
143
|
+
*/
|
|
144
|
+
declare const branch: <Output = unknown>(workflow: string, params?: Record<string, unknown>, options?: {
|
|
145
|
+
id?: string;
|
|
146
|
+
timeout?: number | string;
|
|
147
|
+
}) => WorkflowBranch<Output>;
|
|
148
|
+
/** Build the success outcome a completed branch reports to its parent. */
|
|
134
149
|
/** The lifecycle mutations the REST API exposes via `PATCH .../instances/{id}`. */
|
|
135
150
|
type WorkflowInstanceAction = "pause" | "resume" | "terminate";
|
|
136
151
|
/** Configuration for a {@link WorkflowsRestClient}. */
|
|
@@ -248,4 +263,4 @@ interface RunStepDeps {
|
|
|
248
263
|
* converted to the native one and any declared rollback forwarded to Cloudflare.
|
|
249
264
|
*/
|
|
250
265
|
declare const createRunStep: (deps: RunStepDeps) => WorkflowRunStepFunction;
|
|
251
|
-
export { type LunoraWorkflowsOptions, type NativeNonRetryableErrorConstructor, NonRetryableError, type StepArgsValidator, type StepConfig, type StepDefinition, type WorkflowBindingSpec, type WorkflowConfig, type WorkflowDefinition, type WorkflowEventLike, type WorkflowInstanceAction, type WorkflowInstanceDetail, type WorkflowInstancePage, type WorkflowInstanceStatus, type WorkflowInstanceSummary, type WorkflowLogger, type WorkflowRunContext, type WorkflowRunFunction, type WorkflowRunStepFunction, type WorkflowStepDetail, type WorkflowStepLike, type Workflows, type WorkflowsRestClient, type WorkflowsRestConfig, WorkflowsRestError, convertNonRetryableError, createRunStep, createWorkflowContext, createWorkflowRunContext, createWorkflows, createWorkflowsRestClient, defineStep, defineWorkflow, isNonRetryableError, isStepDefinition, isWorkflowDefinition, toNativeNonRetryableError, validateStepArgs, workflowBindingName, workflowClassName, workflowDefaultName };
|
|
266
|
+
export { type LunoraWorkflowsOptions, MAX_BRANCHES, type NativeNonRetryableErrorConstructor, NonRetryableError, type StepArgsValidator, type StepConfig, type StepDefinition, type WorkflowBindingSpec, type WorkflowBranch, type WorkflowConfig, type WorkflowDefinition, type WorkflowEventLike, type WorkflowInstanceAction, type WorkflowInstanceDetail, type WorkflowInstancePage, type WorkflowInstanceStatus, type WorkflowInstanceSummary, type WorkflowLogger, type WorkflowRunContext, type WorkflowRunFunction, type WorkflowRunStepFunction, type WorkflowStepDetail, type WorkflowStepLike, type Workflows, type WorkflowsRestClient, type WorkflowsRestConfig, WorkflowsRestError, branch, convertNonRetryableError, createRunStep, createWorkflowContext, createWorkflowRunContext, createWorkflows, createWorkflowsRestClient, defineStep, defineWorkflow, isNonRetryableError, isStepDefinition, isWorkflowDefinition, toNativeNonRetryableError, validateStepArgs, workflowBindingName, workflowClassName, workflowDefaultName };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as Workflows, L as LunoraWorkflowsOptions, S as StepArgsValidator, b as StepConfig, c as StepDefinition, d as WorkflowConfig, W as WorkflowDefinition, e as
|
|
2
|
-
export type { A as ArgsOf, F as FunctionReference, I as InferStepArgs, R as RunFunctionOptions,
|
|
1
|
+
import { a as Workflows, L as LunoraWorkflowsOptions, S as StepArgsValidator, b as StepConfig, c as StepDefinition, d as WorkflowConfig, W as WorkflowDefinition, e as WorkflowBranch, f as WorkflowInstanceStatus, g as WorkflowEventLike, h as WorkflowStepLike, i as WorkflowRunContext, j as WorkflowLogger, k as WorkflowRunFunction, l as WorkflowRunStepFunction } from "./packem_shared/types.d-Fdeu2P2C.js";
|
|
2
|
+
export type { A as ArgsOf, F as FunctionReference, I as InferStepArgs, R as RunFunctionOptions, m as RunStepOptions, n as StepHandler, o as StepRollbackContext, p as StepRollbackHandler, q as StepRunContext, r as WorkflowBindingLike, s as WorkflowBranchOutputs, t as WorkflowCreateOptions, u as WorkflowHandle, v as WorkflowHandler, w as WorkflowInstanceLike, x as WorkflowParallelFunction, y as WorkflowRollbackContextLike, z as WorkflowRollbackHandlerLike, B as WorkflowSpawnFunction, C as WorkflowSpawnOptions, D as WorkflowStatusResult, E as WorkflowStepConfigLike, G as WorkflowStepContextLike, H as WorkflowStepRollbackOptionsLike } from "./packem_shared/types.d-Fdeu2P2C.js";
|
|
3
3
|
import '@lunora/values';
|
|
4
4
|
/** Wiring info for one declared workflow, emitted by codegen into the generated shard. */
|
|
5
5
|
interface WorkflowBindingSpec {
|
|
@@ -131,6 +131,21 @@ declare const toNativeNonRetryableError: (error: NonRetryableError, NativeNonRet
|
|
|
131
131
|
* Always throws — the `never` return lets callers `return convertNonRetryableError(...)`.
|
|
132
132
|
*/
|
|
133
133
|
declare const convertNonRetryableError: (error: unknown, NativeNonRetryableError: NativeNonRetryableErrorConstructor | undefined) => never;
|
|
134
|
+
/** Hard cap on branches per `ctx.parallel` call — auto-scale, never silently spawn unbounded DOs. */
|
|
135
|
+
declare const MAX_BRANCHES = 100;
|
|
136
|
+
/** The params key the parent injects so a child knows to signal completion back. Stripped before the user handler sees `ctx.params`. */
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Build a single fan-out branch: a declared child workflow referenced by its
|
|
140
|
+
* `lunora/workflows.ts` export name, plus the params it is created with. Pass the
|
|
141
|
+
* output type as the generic argument so `ctx.parallel(...)` infers the result
|
|
142
|
+
* tuple — e.g. `branch("imageTag", { key })` typed as `branch` of `{ tags }`.
|
|
143
|
+
*/
|
|
144
|
+
declare const branch: <Output = unknown>(workflow: string, params?: Record<string, unknown>, options?: {
|
|
145
|
+
id?: string;
|
|
146
|
+
timeout?: number | string;
|
|
147
|
+
}) => WorkflowBranch<Output>;
|
|
148
|
+
/** Build the success outcome a completed branch reports to its parent. */
|
|
134
149
|
/** The lifecycle mutations the REST API exposes via `PATCH .../instances/{id}`. */
|
|
135
150
|
type WorkflowInstanceAction = "pause" | "resume" | "terminate";
|
|
136
151
|
/** Configuration for a {@link WorkflowsRestClient}. */
|
|
@@ -248,4 +263,4 @@ interface RunStepDeps {
|
|
|
248
263
|
* converted to the native one and any declared rollback forwarded to Cloudflare.
|
|
249
264
|
*/
|
|
250
265
|
declare const createRunStep: (deps: RunStepDeps) => WorkflowRunStepFunction;
|
|
251
|
-
export { type LunoraWorkflowsOptions, type NativeNonRetryableErrorConstructor, NonRetryableError, type StepArgsValidator, type StepConfig, type StepDefinition, type WorkflowBindingSpec, type WorkflowConfig, type WorkflowDefinition, type WorkflowEventLike, type WorkflowInstanceAction, type WorkflowInstanceDetail, type WorkflowInstancePage, type WorkflowInstanceStatus, type WorkflowInstanceSummary, type WorkflowLogger, type WorkflowRunContext, type WorkflowRunFunction, type WorkflowRunStepFunction, type WorkflowStepDetail, type WorkflowStepLike, type Workflows, type WorkflowsRestClient, type WorkflowsRestConfig, WorkflowsRestError, convertNonRetryableError, createRunStep, createWorkflowContext, createWorkflowRunContext, createWorkflows, createWorkflowsRestClient, defineStep, defineWorkflow, isNonRetryableError, isStepDefinition, isWorkflowDefinition, toNativeNonRetryableError, validateStepArgs, workflowBindingName, workflowClassName, workflowDefaultName };
|
|
266
|
+
export { type LunoraWorkflowsOptions, MAX_BRANCHES, type NativeNonRetryableErrorConstructor, NonRetryableError, type StepArgsValidator, type StepConfig, type StepDefinition, type WorkflowBindingSpec, type WorkflowBranch, type WorkflowConfig, type WorkflowDefinition, type WorkflowEventLike, type WorkflowInstanceAction, type WorkflowInstanceDetail, type WorkflowInstancePage, type WorkflowInstanceStatus, type WorkflowInstanceSummary, type WorkflowLogger, type WorkflowRunContext, type WorkflowRunFunction, type WorkflowRunStepFunction, type WorkflowStepDetail, type WorkflowStepLike, type Workflows, type WorkflowsRestClient, type WorkflowsRestConfig, WorkflowsRestError, branch, convertNonRetryableError, createRunStep, createWorkflowContext, createWorkflowRunContext, createWorkflows, createWorkflowsRestClient, defineStep, defineWorkflow, isNonRetryableError, isStepDefinition, isWorkflowDefinition, toNativeNonRetryableError, validateStepArgs, workflowBindingName, workflowClassName, workflowDefaultName };
|
package/dist/index.mjs
CHANGED
|
@@ -3,6 +3,7 @@ export { default as createWorkflows } from './packem_shared/createWorkflows-BoSY
|
|
|
3
3
|
export { defineStep, isStepDefinition } from './packem_shared/defineStep-DJQtLw7g.mjs';
|
|
4
4
|
export { defineWorkflow, isWorkflowDefinition, workflowBindingName, workflowClassName, workflowDefaultName } from './packem_shared/defineWorkflow-DbUC-oCN.mjs';
|
|
5
5
|
export { NonRetryableError, convertNonRetryableError, isNonRetryableError, toNativeNonRetryableError } from './packem_shared/NonRetryableError-Dn2dTyBS.mjs';
|
|
6
|
+
export { MAX_BRANCHES, branch } from './packem_shared/MAX_BRANCHES-C9MJIFii.mjs';
|
|
6
7
|
export { WorkflowsRestError, createWorkflowsRestClient } from './packem_shared/WorkflowsRestError-b06i7K5j.mjs';
|
|
7
|
-
export { createWorkflowRunContext } from './packem_shared/createWorkflowRunContext-
|
|
8
|
+
export { createWorkflowRunContext } from './packem_shared/createWorkflowRunContext-BsMyGuMR.mjs';
|
|
8
9
|
export { createRunStep, validateStepArgs } from './packem_shared/createRunStep-8jOXxP2o.mjs';
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { NonRetryableError } from './NonRetryableError-Dn2dTyBS.mjs';
|
|
2
|
+
|
|
3
|
+
const MAX_BRANCHES = 100;
|
|
4
|
+
const BRANCH_MARKER_KEY = "__lunoraBranch";
|
|
5
|
+
const SPAWN_STEP_PREFIX = "lunora:spawn:";
|
|
6
|
+
const AWAIT_STEP_PREFIX = "lunora:await:";
|
|
7
|
+
const SIGNAL_STEP_PREFIX = "lunora:signal:";
|
|
8
|
+
const BRANCH_EVENT_PREFIX = "lunora:branch:";
|
|
9
|
+
const branch = (workflow, params, options) => {
|
|
10
|
+
return { id: options?.id, params, timeout: options?.timeout, workflow };
|
|
11
|
+
};
|
|
12
|
+
const serializeError = (error) => {
|
|
13
|
+
if (error instanceof Error) {
|
|
14
|
+
return { message: error.message, name: error.name };
|
|
15
|
+
}
|
|
16
|
+
return { message: String(error), name: "Error" };
|
|
17
|
+
};
|
|
18
|
+
const okOutcome = (value) => {
|
|
19
|
+
return { status: "ok", value };
|
|
20
|
+
};
|
|
21
|
+
const errorOutcome = (error) => {
|
|
22
|
+
return { error: serializeError(error), status: "error" };
|
|
23
|
+
};
|
|
24
|
+
const createParallel = (deps) => {
|
|
25
|
+
const run = async (branches) => {
|
|
26
|
+
if (branches.length === 0) {
|
|
27
|
+
return [];
|
|
28
|
+
}
|
|
29
|
+
if (branches.length > MAX_BRANCHES) {
|
|
30
|
+
throw new NonRetryableError(
|
|
31
|
+
`ctx.parallel: ${String(branches.length)} branches exceeds the cap of ${String(MAX_BRANCHES)} — split the fan-out or raise the work into fewer child workflows`
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
const planned = branches.map((item, index) => {
|
|
35
|
+
const childId = deps.nextChildId(item.id);
|
|
36
|
+
return { childId, eventType: `${BRANCH_EVENT_PREFIX}${childId}`, index, item };
|
|
37
|
+
});
|
|
38
|
+
await Promise.all(
|
|
39
|
+
planned.map(
|
|
40
|
+
(plan) => deps.step.do(`${SPAWN_STEP_PREFIX}${plan.childId}`, async () => {
|
|
41
|
+
const binding = deps.resolveBinding(plan.item.workflow);
|
|
42
|
+
const marker = { eventType: plan.eventType, index: plan.index, parentBinding: deps.parentBinding, parentId: deps.instanceId };
|
|
43
|
+
await binding.create({ id: plan.childId, params: { ...plan.item.params, [BRANCH_MARKER_KEY]: marker } });
|
|
44
|
+
return plan.childId;
|
|
45
|
+
})
|
|
46
|
+
)
|
|
47
|
+
);
|
|
48
|
+
const results = [];
|
|
49
|
+
for (const plan of planned) {
|
|
50
|
+
const event = await deps.step.waitForEvent(`${AWAIT_STEP_PREFIX}${plan.childId}`, {
|
|
51
|
+
timeout: plan.item.timeout,
|
|
52
|
+
type: plan.eventType
|
|
53
|
+
});
|
|
54
|
+
const outcome = event.payload;
|
|
55
|
+
if (outcome.status === "error") {
|
|
56
|
+
throw new NonRetryableError(`ctx.parallel: branch "${plan.item.workflow}" (#${String(plan.index)}) failed: ${outcome.error.message}`);
|
|
57
|
+
}
|
|
58
|
+
results.push(outcome.value);
|
|
59
|
+
}
|
|
60
|
+
return results;
|
|
61
|
+
};
|
|
62
|
+
return run;
|
|
63
|
+
};
|
|
64
|
+
const createSpawn = (deps) => async (workflow, params, options) => {
|
|
65
|
+
const childId = deps.nextChildId(options?.id);
|
|
66
|
+
await deps.step.do(`${SPAWN_STEP_PREFIX}${childId}`, async () => {
|
|
67
|
+
const binding = deps.resolveBinding(workflow);
|
|
68
|
+
await binding.create({ id: childId, params });
|
|
69
|
+
return childId;
|
|
70
|
+
});
|
|
71
|
+
return deps.resolveBinding(workflow).get(childId);
|
|
72
|
+
};
|
|
73
|
+
const extractBranchMarker = (payload) => {
|
|
74
|
+
if (typeof payload !== "object" || payload === null) {
|
|
75
|
+
return void 0;
|
|
76
|
+
}
|
|
77
|
+
const marker = payload[BRANCH_MARKER_KEY];
|
|
78
|
+
if (typeof marker !== "object" || marker === null) {
|
|
79
|
+
return void 0;
|
|
80
|
+
}
|
|
81
|
+
const candidate = marker;
|
|
82
|
+
if (typeof candidate.eventType !== "string" || typeof candidate.parentBinding !== "string" || typeof candidate.parentId !== "string" || typeof candidate.index !== "number") {
|
|
83
|
+
return void 0;
|
|
84
|
+
}
|
|
85
|
+
return { eventType: candidate.eventType, index: candidate.index, parentBinding: candidate.parentBinding, parentId: candidate.parentId };
|
|
86
|
+
};
|
|
87
|
+
const stripBranchMarker = (payload) => {
|
|
88
|
+
if (typeof payload !== "object" || payload === null) {
|
|
89
|
+
return payload;
|
|
90
|
+
}
|
|
91
|
+
const rest = { ...payload };
|
|
92
|
+
Reflect.deleteProperty(rest, BRANCH_MARKER_KEY);
|
|
93
|
+
return rest;
|
|
94
|
+
};
|
|
95
|
+
const signalBranchParent = async (deps, marker, outcome) => {
|
|
96
|
+
const binding = deps.env[marker.parentBinding];
|
|
97
|
+
if (!binding || typeof binding.get !== "function") {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
const getParent = binding.get.bind(binding);
|
|
101
|
+
await deps.step.do(`${SIGNAL_STEP_PREFIX}${String(marker.index)}`, async () => {
|
|
102
|
+
const parent = await getParent(marker.parentId);
|
|
103
|
+
await parent.sendEvent({ payload: outcome, type: marker.eventType });
|
|
104
|
+
return marker.eventType;
|
|
105
|
+
});
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
export { BRANCH_MARKER_KEY, MAX_BRANCHES, branch, createParallel, createSpawn, errorOutcome, extractBranchMarker, okOutcome, signalBranchParent, stripBranchMarker };
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { workflowBindingName } from './defineWorkflow-DbUC-oCN.mjs';
|
|
2
|
+
import { createSpawn, createParallel } from './MAX_BRANCHES-C9MJIFii.mjs';
|
|
1
3
|
import { createRunStep } from './createRunStep-8jOXxP2o.mjs';
|
|
2
4
|
|
|
3
5
|
const createDispatchLogger = (prefix) => {
|
|
@@ -65,13 +67,42 @@ const createDispatchRunner = (options) => {
|
|
|
65
67
|
const createWorkflowRunContext = (options) => {
|
|
66
68
|
const log = createDispatchLogger(`[workflow:${options.exportName}]`);
|
|
67
69
|
const run = createDispatchRunner({ env: options.env, fetchImpl: options.fetchImpl, label: "@lunora/workflow" });
|
|
70
|
+
const resolveBinding = (workflow) => {
|
|
71
|
+
const bindingName = workflowBindingName(workflow);
|
|
72
|
+
const binding = options.env[bindingName];
|
|
73
|
+
if (!binding || typeof binding.create !== "function" || typeof binding.get !== "function") {
|
|
74
|
+
throw new Error(
|
|
75
|
+
`@lunora/workflow: cannot spawn child workflow "${workflow}" — no Workflow binding "${bindingName}" on env (is it declared in lunora/workflows.ts?)`
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
return binding;
|
|
79
|
+
};
|
|
80
|
+
let childCounter = 0;
|
|
81
|
+
const nextChildId = (explicit) => {
|
|
82
|
+
if (explicit !== void 0) {
|
|
83
|
+
return explicit;
|
|
84
|
+
}
|
|
85
|
+
const id = `${options.event.instanceId}-c${String(childCounter)}`;
|
|
86
|
+
childCounter += 1;
|
|
87
|
+
return id;
|
|
88
|
+
};
|
|
89
|
+
const fanOutDeps = {
|
|
90
|
+
env: options.env,
|
|
91
|
+
instanceId: options.event.instanceId,
|
|
92
|
+
nextChildId,
|
|
93
|
+
parentBinding: workflowBindingName(options.exportName),
|
|
94
|
+
resolveBinding,
|
|
95
|
+
step: options.step
|
|
96
|
+
};
|
|
68
97
|
return {
|
|
69
98
|
env: options.env,
|
|
70
99
|
event: options.event,
|
|
71
100
|
log,
|
|
101
|
+
parallel: createParallel(fanOutDeps),
|
|
72
102
|
params: options.event.payload,
|
|
73
103
|
run,
|
|
74
104
|
runStep: createRunStep({ env: options.env, log, nonRetryableErrorClass: options.nonRetryableErrorClass, run, step: options.step }),
|
|
105
|
+
spawn: createSpawn(fanOutDeps),
|
|
75
106
|
step: options.step
|
|
76
107
|
};
|
|
77
108
|
};
|
|
@@ -264,9 +264,55 @@ interface RunStepOptions {
|
|
|
264
264
|
*/
|
|
265
265
|
type WorkflowRunStepFunction = <A extends StepArgsValidator, Result>(step: StepDefinition<A, Result>, args: InferStepArgs<A>, options?: RunStepOptions) => Promise<Result>;
|
|
266
266
|
/**
|
|
267
|
+
* One branch of a {@link WorkflowParallelFunction} fan-out — a declared child
|
|
268
|
+
* workflow (referenced by its `lunora/workflows.ts` export name) plus the params
|
|
269
|
+
* it is created with. The phantom `Output` carries the child's result type into
|
|
270
|
+
* the `ctx.parallel(...)` result tuple. Build one with the `branch(...)` helper.
|
|
271
|
+
*/
|
|
272
|
+
interface WorkflowBranch<Output = unknown> {
|
|
273
|
+
/** Phantom marker for the branch output type — never present at runtime. */
|
|
274
|
+
readonly __output?: Output;
|
|
275
|
+
/** Optional explicit child instance id (defaults to a deterministic parent-derived id). */
|
|
276
|
+
readonly id?: string;
|
|
277
|
+
/** The params the child instance is created with — surfaced as the child's `ctx.params`. */
|
|
278
|
+
readonly params?: Record<string, unknown>;
|
|
279
|
+
/** Optional wait timeout for this branch (the parent's `waitForEvent` timeout). */
|
|
280
|
+
readonly timeout?: number | string;
|
|
281
|
+
/** The `lunora/workflows.ts` export name of the child workflow to run. */
|
|
282
|
+
readonly workflow: string;
|
|
283
|
+
}
|
|
284
|
+
/** Map a tuple of {@link WorkflowBranch}es to the tuple of their output types, preserving order. */
|
|
285
|
+
type WorkflowBranchOutputs<B extends ReadonlyArray<WorkflowBranch>> = { -readonly [K in keyof B]: B[K] extends WorkflowBranch<infer Output> ? Output : never };
|
|
286
|
+
/**
|
|
287
|
+
* Run branches as isolated child workflow instances and resolve with their
|
|
288
|
+
* outputs in declaration order. Each branch gets its own Durable Object (own
|
|
289
|
+
* memory / CPU / retry budget); the parent hibernates while they execute. Rejects
|
|
290
|
+
* (non-retryable) on the first branch that fails.
|
|
291
|
+
*
|
|
292
|
+
* ```ts
|
|
293
|
+
* const [tags, thumb] = await ctx.parallel([
|
|
294
|
+
* branch("imageTag", { key }),
|
|
295
|
+
* branch("thumbnail", { key }),
|
|
296
|
+
* ]);
|
|
297
|
+
* ```
|
|
298
|
+
*/
|
|
299
|
+
type WorkflowParallelFunction = <const B extends ReadonlyArray<WorkflowBranch>>(branches: B) => Promise<WorkflowBranchOutputs<B>>;
|
|
300
|
+
/** Per-call options for {@link WorkflowSpawnFunction}. */
|
|
301
|
+
interface WorkflowSpawnOptions {
|
|
302
|
+
/** Explicit child instance id (defaults to a deterministic parent-derived id). */
|
|
303
|
+
id?: string;
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Fire-and-forget start of a declared child workflow from inside a workflow body
|
|
307
|
+
* — replay-safe (idempotent create), returns a live handle to the child. Use
|
|
308
|
+
* {@link WorkflowParallelFunction} instead when you need to await results.
|
|
309
|
+
*/
|
|
310
|
+
type WorkflowSpawnFunction = (workflow: string, params?: Record<string, unknown>, options?: WorkflowSpawnOptions) => Promise<WorkflowInstanceLike>;
|
|
311
|
+
/**
|
|
267
312
|
* The context object passed to a `defineWorkflow` handler. Bundles the native
|
|
268
313
|
* Cloudflare durability primitives (`step`, `event`) with the Lunora runner
|
|
269
|
-
* (`run`), the reusable-step runner (`runStep`), the
|
|
314
|
+
* (`run`), the reusable-step runner (`runStep`), the fan-out primitives
|
|
315
|
+
* (`parallel` / `spawn`), the Worker `env`, and a logger.
|
|
270
316
|
*/
|
|
271
317
|
interface WorkflowRunContext<Params = Record<string, unknown>> {
|
|
272
318
|
/** The Worker environment bindings. */
|
|
@@ -275,12 +321,16 @@ interface WorkflowRunContext<Params = Record<string, unknown>> {
|
|
|
275
321
|
readonly event: WorkflowEventLike<Params>;
|
|
276
322
|
/** Structured logger surfaced in `wrangler tail` / Studio logs. */
|
|
277
323
|
readonly log: WorkflowLogger;
|
|
324
|
+
/** Run branches as isolated child workflow instances and await their outputs (declaration-ordered tuple). */
|
|
325
|
+
readonly parallel: WorkflowParallelFunction;
|
|
278
326
|
/** Convenience alias for `event.payload`. */
|
|
279
327
|
readonly params: Readonly<Params>;
|
|
280
328
|
/** Invoke a Lunora function; wrap in `step.do(...)` for durability. */
|
|
281
329
|
readonly run: WorkflowRunFunction;
|
|
282
330
|
/** Run a reusable, schema-validated {@link StepDefinition} as a durable step. */
|
|
283
331
|
readonly runStep: WorkflowRunStepFunction;
|
|
332
|
+
/** Fire-and-forget start of a declared child workflow (replay-safe; returns a live handle). */
|
|
333
|
+
readonly spawn: WorkflowSpawnFunction;
|
|
284
334
|
/** The native Cloudflare Workflows durable-step API. */
|
|
285
335
|
readonly step: WorkflowStepLike;
|
|
286
336
|
}
|
|
@@ -341,4 +391,4 @@ interface LunoraWorkflowsOptions {
|
|
|
341
391
|
*/
|
|
342
392
|
bindings: Record<string, WorkflowBindingLike>;
|
|
343
393
|
}
|
|
344
|
-
export { ArgsOf as A,
|
|
394
|
+
export { ArgsOf as A, WorkflowSpawnFunction as B, WorkflowSpawnOptions as C, WorkflowStatusResult as D, WorkflowStepConfigLike as E, FunctionReference as F, WorkflowStepContextLike as G, WorkflowStepRollbackOptionsLike as H, InferStepArgs as I, LunoraWorkflowsOptions as L, RunFunctionOptions as R, StepArgsValidator as S, WorkflowDefinition as W, Workflows as a, StepConfig as b, StepDefinition as c, WorkflowConfig as d, WorkflowBranch as e, WorkflowInstanceStatus as f, WorkflowEventLike as g, WorkflowStepLike as h, WorkflowRunContext as i, WorkflowLogger as j, WorkflowRunFunction as k, WorkflowRunStepFunction as l, RunStepOptions as m, StepHandler as n, StepRollbackContext as o, StepRollbackHandler as p, StepRunContext as q, WorkflowBindingLike as r, WorkflowBranchOutputs as s, WorkflowCreateOptions as t, WorkflowHandle as u, WorkflowHandler as v, WorkflowInstanceLike as w, WorkflowParallelFunction as x, WorkflowRollbackContextLike as y, WorkflowRollbackHandlerLike as z };
|
|
@@ -264,9 +264,55 @@ interface RunStepOptions {
|
|
|
264
264
|
*/
|
|
265
265
|
type WorkflowRunStepFunction = <A extends StepArgsValidator, Result>(step: StepDefinition<A, Result>, args: InferStepArgs<A>, options?: RunStepOptions) => Promise<Result>;
|
|
266
266
|
/**
|
|
267
|
+
* One branch of a {@link WorkflowParallelFunction} fan-out — a declared child
|
|
268
|
+
* workflow (referenced by its `lunora/workflows.ts` export name) plus the params
|
|
269
|
+
* it is created with. The phantom `Output` carries the child's result type into
|
|
270
|
+
* the `ctx.parallel(...)` result tuple. Build one with the `branch(...)` helper.
|
|
271
|
+
*/
|
|
272
|
+
interface WorkflowBranch<Output = unknown> {
|
|
273
|
+
/** Phantom marker for the branch output type — never present at runtime. */
|
|
274
|
+
readonly __output?: Output;
|
|
275
|
+
/** Optional explicit child instance id (defaults to a deterministic parent-derived id). */
|
|
276
|
+
readonly id?: string;
|
|
277
|
+
/** The params the child instance is created with — surfaced as the child's `ctx.params`. */
|
|
278
|
+
readonly params?: Record<string, unknown>;
|
|
279
|
+
/** Optional wait timeout for this branch (the parent's `waitForEvent` timeout). */
|
|
280
|
+
readonly timeout?: number | string;
|
|
281
|
+
/** The `lunora/workflows.ts` export name of the child workflow to run. */
|
|
282
|
+
readonly workflow: string;
|
|
283
|
+
}
|
|
284
|
+
/** Map a tuple of {@link WorkflowBranch}es to the tuple of their output types, preserving order. */
|
|
285
|
+
type WorkflowBranchOutputs<B extends ReadonlyArray<WorkflowBranch>> = { -readonly [K in keyof B]: B[K] extends WorkflowBranch<infer Output> ? Output : never };
|
|
286
|
+
/**
|
|
287
|
+
* Run branches as isolated child workflow instances and resolve with their
|
|
288
|
+
* outputs in declaration order. Each branch gets its own Durable Object (own
|
|
289
|
+
* memory / CPU / retry budget); the parent hibernates while they execute. Rejects
|
|
290
|
+
* (non-retryable) on the first branch that fails.
|
|
291
|
+
*
|
|
292
|
+
* ```ts
|
|
293
|
+
* const [tags, thumb] = await ctx.parallel([
|
|
294
|
+
* branch("imageTag", { key }),
|
|
295
|
+
* branch("thumbnail", { key }),
|
|
296
|
+
* ]);
|
|
297
|
+
* ```
|
|
298
|
+
*/
|
|
299
|
+
type WorkflowParallelFunction = <const B extends ReadonlyArray<WorkflowBranch>>(branches: B) => Promise<WorkflowBranchOutputs<B>>;
|
|
300
|
+
/** Per-call options for {@link WorkflowSpawnFunction}. */
|
|
301
|
+
interface WorkflowSpawnOptions {
|
|
302
|
+
/** Explicit child instance id (defaults to a deterministic parent-derived id). */
|
|
303
|
+
id?: string;
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Fire-and-forget start of a declared child workflow from inside a workflow body
|
|
307
|
+
* — replay-safe (idempotent create), returns a live handle to the child. Use
|
|
308
|
+
* {@link WorkflowParallelFunction} instead when you need to await results.
|
|
309
|
+
*/
|
|
310
|
+
type WorkflowSpawnFunction = (workflow: string, params?: Record<string, unknown>, options?: WorkflowSpawnOptions) => Promise<WorkflowInstanceLike>;
|
|
311
|
+
/**
|
|
267
312
|
* The context object passed to a `defineWorkflow` handler. Bundles the native
|
|
268
313
|
* Cloudflare durability primitives (`step`, `event`) with the Lunora runner
|
|
269
|
-
* (`run`), the reusable-step runner (`runStep`), the
|
|
314
|
+
* (`run`), the reusable-step runner (`runStep`), the fan-out primitives
|
|
315
|
+
* (`parallel` / `spawn`), the Worker `env`, and a logger.
|
|
270
316
|
*/
|
|
271
317
|
interface WorkflowRunContext<Params = Record<string, unknown>> {
|
|
272
318
|
/** The Worker environment bindings. */
|
|
@@ -275,12 +321,16 @@ interface WorkflowRunContext<Params = Record<string, unknown>> {
|
|
|
275
321
|
readonly event: WorkflowEventLike<Params>;
|
|
276
322
|
/** Structured logger surfaced in `wrangler tail` / Studio logs. */
|
|
277
323
|
readonly log: WorkflowLogger;
|
|
324
|
+
/** Run branches as isolated child workflow instances and await their outputs (declaration-ordered tuple). */
|
|
325
|
+
readonly parallel: WorkflowParallelFunction;
|
|
278
326
|
/** Convenience alias for `event.payload`. */
|
|
279
327
|
readonly params: Readonly<Params>;
|
|
280
328
|
/** Invoke a Lunora function; wrap in `step.do(...)` for durability. */
|
|
281
329
|
readonly run: WorkflowRunFunction;
|
|
282
330
|
/** Run a reusable, schema-validated {@link StepDefinition} as a durable step. */
|
|
283
331
|
readonly runStep: WorkflowRunStepFunction;
|
|
332
|
+
/** Fire-and-forget start of a declared child workflow (replay-safe; returns a live handle). */
|
|
333
|
+
readonly spawn: WorkflowSpawnFunction;
|
|
284
334
|
/** The native Cloudflare Workflows durable-step API. */
|
|
285
335
|
readonly step: WorkflowStepLike;
|
|
286
336
|
}
|
|
@@ -341,4 +391,4 @@ interface LunoraWorkflowsOptions {
|
|
|
341
391
|
*/
|
|
342
392
|
bindings: Record<string, WorkflowBindingLike>;
|
|
343
393
|
}
|
|
344
|
-
export { ArgsOf as A,
|
|
394
|
+
export { ArgsOf as A, WorkflowSpawnFunction as B, WorkflowSpawnOptions as C, WorkflowStatusResult as D, WorkflowStepConfigLike as E, FunctionReference as F, WorkflowStepContextLike as G, WorkflowStepRollbackOptionsLike as H, InferStepArgs as I, LunoraWorkflowsOptions as L, RunFunctionOptions as R, StepArgsValidator as S, WorkflowDefinition as W, Workflows as a, StepConfig as b, StepDefinition as c, WorkflowConfig as d, WorkflowBranch as e, WorkflowInstanceStatus as f, WorkflowEventLike as g, WorkflowStepLike as h, WorkflowRunContext as i, WorkflowLogger as j, WorkflowRunFunction as k, WorkflowRunStepFunction as l, RunStepOptions as m, StepHandler as n, StepRollbackContext as o, StepRollbackHandler as p, StepRunContext as q, WorkflowBindingLike as r, WorkflowBranchOutputs as s, WorkflowCreateOptions as t, WorkflowHandle as u, WorkflowHandler as v, WorkflowInstanceLike as w, WorkflowParallelFunction as x, WorkflowRollbackContextLike as y, WorkflowRollbackHandlerLike as z };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lunora/workflow",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.4",
|
|
4
4
|
"description": "Durable workflows for Lunora: defineWorkflow over Cloudflare Workflows, generated WorkflowEntrypoint classes, and the ctx.workflows surface",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cloudflare",
|