@superdurable/dex 0.1.5 → 0.1.6
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/README.md +102 -6
- package/dist/src/client.d.ts +18 -23
- package/dist/src/client.js +94 -65
- package/dist/src/client.js.map +1 -1
- package/dist/src/codec.d.ts +1 -1
- package/dist/src/context.d.ts +7 -0
- package/dist/src/errors.d.ts +2 -33
- package/dist/src/errors.js +2 -45
- package/dist/src/errors.js.map +1 -1
- package/dist/src/flow-result.d.ts +47 -0
- package/dist/src/flow-result.js +82 -0
- package/dist/src/flow-result.js.map +1 -0
- package/dist/src/flow.d.ts +13 -1
- package/dist/src/flow.js +1 -0
- package/dist/src/flow.js.map +1 -1
- package/dist/src/gen/dex.d.ts +209 -33
- package/dist/src/gen/dex.js +1619 -213
- package/dist/src/gen/dex.js.map +1 -1
- package/dist/src/grpc-status.js +6 -5
- package/dist/src/grpc-status.js.map +1 -1
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/invocation-context.d.ts +5 -1
- package/dist/src/invocation-context.js +23 -1
- package/dist/src/invocation-context.js.map +1 -1
- package/dist/src/options.d.ts +42 -19
- package/dist/src/options.js +20 -4
- package/dist/src/options.js.map +1 -1
- package/dist/src/rpc.d.ts +3 -1
- package/dist/src/rpc.js.map +1 -1
- package/dist/src/step.d.ts +32 -2
- package/dist/src/step.js +37 -0
- package/dist/src/step.js.map +1 -1
- package/dist/src/subflow.d.ts +62 -0
- package/dist/src/subflow.js +62 -0
- package/dist/src/subflow.js.map +1 -0
- package/dist/src/wait.d.ts +10 -2
- package/dist/src/wait.js.map +1 -1
- package/dist/src/worker-dispatcher.d.ts +4 -3
- package/dist/src/worker-dispatcher.js +256 -28
- package/dist/src/worker-dispatcher.js.map +1 -1
- package/dist/src/worker.js +21 -5
- package/dist/src/worker.js.map +1 -1
- package/native/linux-aarch64/dex_blob_cache_node.node +0 -0
- package/native/linux-x86_64/dex_blob_cache_node.node +0 -0
- package/native/macos-aarch64/dex_blob_cache_node.node +0 -0
- package/native/macos-x86_64/dex_blob_cache_node.node +0 -0
- package/native/windows-x86_64/dex_blob_cache_node.node +0 -0
- package/package.json +1 -1
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// Copyright (c) 2026 Super Durable, Inc.
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Super Durable Source License 1.0.
|
|
4
|
+
// You may not use this file except in compliance with the License.
|
|
5
|
+
// See the LICENSE file in the repository root.
|
|
6
|
+
//
|
|
7
|
+
// SPDX-License-Identifier: LicenseRef-Super-Durable-1.0
|
|
8
|
+
import { InvocationContext } from "./invocation-context.js";
|
|
9
|
+
/** Controls how a generated SubFlow Flow ID resolves an existing execution. */
|
|
10
|
+
export const SubFlowReusePolicy = Object.freeze({
|
|
11
|
+
/** Attaches to a running execution or returns its existing terminal result. */
|
|
12
|
+
ATTACH: "attach",
|
|
13
|
+
/** Restarts abnormal executions, attaches while running, and returns completed results. */
|
|
14
|
+
RESTART_IF_PREVIOUS_EXITS_ABNORMALLY: "restartIfPreviousExitsAbnormally",
|
|
15
|
+
/** Replaces any different existing execution, including a running one. */
|
|
16
|
+
ALWAYS_RESTART: "alwaysRestart",
|
|
17
|
+
});
|
|
18
|
+
/** Creates durable SubFlow conditions and reads their Execute results. */
|
|
19
|
+
export const SubFlow = Object.freeze({
|
|
20
|
+
/**
|
|
21
|
+
* Creates a condition that starts or reuses a registered Flow and awaits completion.
|
|
22
|
+
* @typeParam Input - Target starting Step input type.
|
|
23
|
+
* @param flow - Exact target Flow instance registered by the Worker.
|
|
24
|
+
* @param input - Input accepted by its starting Step.
|
|
25
|
+
* @param options - Optional timing, retry, Attribute, configuration, reuse, and ID settings.
|
|
26
|
+
* @returns A durable SubFlow condition accepted by Wait factories.
|
|
27
|
+
*/
|
|
28
|
+
run(flow, input, options = {}) {
|
|
29
|
+
return Object.freeze({
|
|
30
|
+
kind: "subFlow",
|
|
31
|
+
subFlow: flow,
|
|
32
|
+
subFlowInput: input,
|
|
33
|
+
subFlowOptions: options,
|
|
34
|
+
...(options.conditionId === undefined ? {} : { conditionId: options.conditionId }),
|
|
35
|
+
});
|
|
36
|
+
},
|
|
37
|
+
/**
|
|
38
|
+
* Returns one stable-indexed SubFlow result during Step execute.
|
|
39
|
+
* @param context - Current Dex Execute context.
|
|
40
|
+
* @param index - Zero-based SubFlow order; defaults to zero.
|
|
41
|
+
* @returns A terminal result or an AnyOf loser's running snapshot.
|
|
42
|
+
*/
|
|
43
|
+
getConditionResults(context, index = 0) {
|
|
44
|
+
return invocation(context).subFlowResult(index);
|
|
45
|
+
},
|
|
46
|
+
/**
|
|
47
|
+
* Returns one generated SubFlow Flow ID during Step execute.
|
|
48
|
+
* @param context - Current Dex Execute context.
|
|
49
|
+
* @param index - Zero-based SubFlow order; defaults to zero.
|
|
50
|
+
* @returns An addressable Flow ID suitable for `Client.stopFlow`.
|
|
51
|
+
*/
|
|
52
|
+
getFlowId(context, index = 0) {
|
|
53
|
+
return invocation(context).subFlowId(index);
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
function invocation(context) {
|
|
57
|
+
if (!(context instanceof InvocationContext)) {
|
|
58
|
+
throw new TypeError("SubFlow access requires a Dex invocation Context");
|
|
59
|
+
}
|
|
60
|
+
return context;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=subflow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subflow.js","sourceRoot":"","sources":["../../src/subflow.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,EAAE;AACF,uDAAuD;AACvD,mEAAmE;AACnE,+CAA+C;AAC/C,EAAE;AACF,wDAAwD;AAKxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAK5D,+EAA+E;AAC/E,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,CAAC;IAC9C,+EAA+E;IAC/E,MAAM,EAAE,QAAQ;IAChB,2FAA2F;IAC3F,oCAAoC,EAAE,kCAAkC;IACxE,0EAA0E;IAC1E,cAAc,EAAE,eAAe;CACvB,CAAC,CAAC;AA0BZ,0EAA0E;AAC1E,MAAM,CAAC,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC;IACnC;;;;;;;OAOG;IACH,GAAG,CAAQ,IAAiB,EAAE,KAAY,EAAE,UAA0B,EAAE;QACtE,OAAO,MAAM,CAAC,MAAM,CAAC;YACnB,IAAI,EAAE,SAAkB;YACxB,OAAO,EAAE,IAAI;YACb,YAAY,EAAE,KAAK;YACnB,cAAc,EAAE,OAAO;YACvB,GAAG,CAAC,OAAO,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC;SACnF,CAAC,CAAC;IACL,CAAC;IACD;;;;;OAKG;IACH,mBAAmB,CAAC,OAAgB,EAAE,KAAK,GAAG,CAAC;QAC7C,OAAO,UAAU,CAAC,OAAO,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAClD,CAAC;IACD;;;;;OAKG;IACH,SAAS,CAAC,OAAgB,EAAE,KAAK,GAAG,CAAC;QACnC,OAAO,UAAU,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC9C,CAAC;CACF,CAAC,CAAC;AAEH,SAAS,UAAU,CAAC,OAAgB;IAClC,IAAI,CAAC,CAAC,OAAO,YAAY,iBAAiB,CAAC,EAAE,CAAC;QAC5C,MAAM,IAAI,SAAS,CAAC,kDAAkD,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
package/dist/src/wait.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type { Codec } from "./codec.js";
|
|
2
2
|
import type { Context } from "./context.js";
|
|
3
|
-
|
|
3
|
+
import type { Flow } from "./flow.js";
|
|
4
|
+
import type { SubFlowOptions } from "./subflow.js";
|
|
5
|
+
/** Describes one durable Timer, Channel, or SubFlow readiness condition. */
|
|
4
6
|
export interface Condition {
|
|
5
7
|
/** Condition family interpreted by Dex. */
|
|
6
|
-
readonly kind: "timer" | "channel";
|
|
8
|
+
readonly kind: "timer" | "channel" | "subFlow";
|
|
7
9
|
/** Optional stable ID unique within the Wait tree. */
|
|
8
10
|
readonly conditionId?: string;
|
|
9
11
|
/** Timer delay in non-negative milliseconds. */
|
|
@@ -16,6 +18,12 @@ export interface Condition {
|
|
|
16
18
|
readonly atLeast?: number;
|
|
17
19
|
/** Inclusive upper queued-value bound. */
|
|
18
20
|
readonly atMost?: number;
|
|
21
|
+
/** Exact registered Flow instance targeted by a SubFlow condition. */
|
|
22
|
+
readonly subFlow?: Flow<any>;
|
|
23
|
+
/** Starting Step input for a SubFlow condition. */
|
|
24
|
+
readonly subFlowInput?: unknown;
|
|
25
|
+
/** Start, reuse, and condition options for a SubFlow condition. */
|
|
26
|
+
readonly subFlowOptions?: SubFlowOptions;
|
|
19
27
|
}
|
|
20
28
|
/** Groups Conditions that must become ready together. */
|
|
21
29
|
export interface ConditionCombination {
|
package/dist/src/wait.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wait.js","sourceRoot":"","sources":["../../src/wait.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,EAAE;AACF,uDAAuD;AACvD,mEAAmE;AACnE,+CAA+C;AAC/C,EAAE;AACF,wDAAwD;
|
|
1
|
+
{"version":3,"file":"wait.js","sourceRoot":"","sources":["../../src/wait.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,9 +5,10 @@ export declare class WorkerDispatcher {
|
|
|
5
5
|
private readonly registry;
|
|
6
6
|
private readonly hydrator;
|
|
7
7
|
constructor(registry: Registry, hydrator: ValueHydrator);
|
|
8
|
-
invokeWaitFor(original: InvokeWaitForMethodRequest): Promise<InvokeWaitForMethodResponse>;
|
|
9
|
-
invokeExecute(original: InvokeExecuteMethodRequest): Promise<InvokeExecuteMethodResponse>;
|
|
10
|
-
|
|
8
|
+
invokeWaitFor(original: InvokeWaitForMethodRequest, cancellationSignal?: AbortSignal): Promise<InvokeWaitForMethodResponse>;
|
|
9
|
+
invokeExecute(original: InvokeExecuteMethodRequest, cancellationSignal?: AbortSignal): Promise<InvokeExecuteMethodResponse>;
|
|
10
|
+
private invokeTimeoutHandler;
|
|
11
|
+
invokeRPC(original: InvokeWorkerRPCRequest, cancellationSignal?: AbortSignal): Promise<InvokeWorkerRPCResponse>;
|
|
11
12
|
private hydrateWaitFor;
|
|
12
13
|
private hydrateExecute;
|
|
13
14
|
private hydrateRPC;
|
|
@@ -5,12 +5,17 @@
|
|
|
5
5
|
// See the LICENSE file in the repository root.
|
|
6
6
|
//
|
|
7
7
|
// SPDX-License-Identifier: LicenseRef-Super-Durable-1.0
|
|
8
|
-
import { ChannelCondition, CloseDecision, CloseDecisionType, ConditionCombination as ProtoConditionCombination, ExecuteMethodFailurePolicy, InvokeExecuteMethodResponse, InvokeWaitForMethodResponse, InvokeWorkerRPCResponse, StepDecision as ProtoStepDecision, StepMovement as ProtoStepMovement, StepOptions as ProtoStepOptions, TimerCondition, WaitForMethodFailurePolicy, WaitingCondition, WaitingConditionType, } from "./gen/dex.js";
|
|
8
|
+
import { ChannelCondition, CloseDecision, CloseDecisionType, ConditionCombination as ProtoConditionCombination, ExecuteMethodFailurePolicy, InvokeExecuteMethodResponse, InvokeWaitForMethodResponse, InvokeWorkerRPCResponse, StepDecision as ProtoStepDecision, StepMovement as ProtoStepMovement, StepOptions as ProtoStepOptions, TimerCondition, SubFlowCondition as ProtoSubFlowCondition, SubFlowOptions as ProtoSubFlowOptions, SubFlowReusePolicy as ProtoSubFlowReusePolicy, FlowRetryPolicy, FlowTimeoutPolicy as ProtoFlowTimeoutPolicy, FlowConfig as ProtoFlowConfig, ActiveStepSearchMode as ProtoActiveStepSearchMode, StepDurability as ProtoStepDurability, IndexType as ProtoIndexType, WaitForMethodFailurePolicy, WaitingCondition, WaitingConditionType, } from "./gen/dex.js";
|
|
9
9
|
import { InvalidStepResultError, ValueMappingError } from "./errors.js";
|
|
10
|
-
import { registeredFlowByName, registeredRPCByName, registeredStep, } from "./flow.js";
|
|
10
|
+
import { registeredFlowByName, registeredFlow, registeredRPCByName, registeredStep, } from "./flow.js";
|
|
11
11
|
import { InvocationContext } from "./invocation-context.js";
|
|
12
|
+
import { AttributeMap, IndexType } from "./persistence.js";
|
|
13
|
+
import { mapAttributeStoreName, mapAttributeStoreSync } from "./attribute-store-sync.js";
|
|
14
|
+
import { ActiveStepSearchMode, FlowTimeoutPolicy } from "./options.js";
|
|
15
|
+
import { SubFlowReusePolicy } from "./subflow.js";
|
|
12
16
|
import { decodeValue, encodeUnknown, encodeValue, } from "./value-mapper.js";
|
|
13
17
|
import { Channel, ChannelMap } from "./wait.js";
|
|
18
|
+
const timeoutHandlerStepType = "sys:timeout_handler";
|
|
14
19
|
export class WorkerDispatcher {
|
|
15
20
|
registry;
|
|
16
21
|
hydrator;
|
|
@@ -18,11 +23,12 @@ export class WorkerDispatcher {
|
|
|
18
23
|
this.registry = registry;
|
|
19
24
|
this.hydrator = hydrator;
|
|
20
25
|
}
|
|
21
|
-
async invokeWaitFor(original) {
|
|
26
|
+
async invokeWaitFor(original, cancellationSignal = new AbortController().signal) {
|
|
22
27
|
const request = await this.hydrateWaitFor(original);
|
|
28
|
+
cancellationSignal.throwIfAborted();
|
|
23
29
|
const flow = registeredFlowByName(this.registry, request.flowType);
|
|
24
30
|
const step = registeredStep(flow, request.stepType);
|
|
25
|
-
const context = new InvocationContext("waitFor", flow, request.context, request.attributes);
|
|
31
|
+
const context = new InvocationContext("waitFor", flow, request.context, request.attributes, [], undefined, {}, cancellationSignal);
|
|
26
32
|
const input = decodeValue(step.step.inputCodec, requireValue(request.stepInput, "Step input"));
|
|
27
33
|
if (step.step.waitFor === undefined) {
|
|
28
34
|
throw new TypeError(`Step ${step.name} does not implement waitFor`);
|
|
@@ -31,7 +37,7 @@ export class WorkerDispatcher {
|
|
|
31
37
|
try {
|
|
32
38
|
return InvokeWaitForMethodResponse.create({
|
|
33
39
|
upsertAttributes: [...context.getAttributeWrites()],
|
|
34
|
-
waitingCondition: mapWait(flow, wait),
|
|
40
|
+
waitingCondition: mapWait(this.registry, flow, wait),
|
|
35
41
|
upsertStepExeLocals: [...context.getLocalWrites()],
|
|
36
42
|
recordEvents: [...context.getEvents()],
|
|
37
43
|
publishToChannel: [...context.getPublications()],
|
|
@@ -41,11 +47,15 @@ export class WorkerDispatcher {
|
|
|
41
47
|
throw invalidStepResult(flow.name, step.name, "waitFor", failure);
|
|
42
48
|
}
|
|
43
49
|
}
|
|
44
|
-
async invokeExecute(original) {
|
|
50
|
+
async invokeExecute(original, cancellationSignal = new AbortController().signal) {
|
|
45
51
|
const request = await this.hydrateExecute(original);
|
|
52
|
+
cancellationSignal.throwIfAborted();
|
|
46
53
|
const flow = registeredFlowByName(this.registry, request.flowType);
|
|
54
|
+
if (request.stepType === timeoutHandlerStepType) {
|
|
55
|
+
return this.invokeTimeoutHandler(request, flow, cancellationSignal);
|
|
56
|
+
}
|
|
47
57
|
const step = registeredStep(flow, request.stepType);
|
|
48
|
-
const context = new InvocationContext("execute", flow, request.context, request.attributes, request.stepExeLocals, request.conditionResults);
|
|
58
|
+
const context = new InvocationContext("execute", flow, request.context, request.attributes, request.stepExeLocals, request.conditionResults, {}, cancellationSignal);
|
|
49
59
|
const input = decodeValue(step.step.inputCodec, requireValue(request.stepInput, "Step input"));
|
|
50
60
|
const decision = await step.step.execute(context, input);
|
|
51
61
|
try {
|
|
@@ -61,11 +71,34 @@ export class WorkerDispatcher {
|
|
|
61
71
|
throw invalidStepResult(flow.name, step.name, "execute", failure);
|
|
62
72
|
}
|
|
63
73
|
}
|
|
64
|
-
async
|
|
74
|
+
async invokeTimeoutHandler(request, flow, cancellationSignal) {
|
|
75
|
+
try {
|
|
76
|
+
if (request.stepInput !== undefined) {
|
|
77
|
+
throw new TypeError("timeout handler input must be absent");
|
|
78
|
+
}
|
|
79
|
+
if (flow.flow.handleTimeout === undefined) {
|
|
80
|
+
throw new TypeError(`Flow ${flow.name} does not implement handleTimeout`);
|
|
81
|
+
}
|
|
82
|
+
const context = new InvocationContext("execute", flow, request.context, request.attributes, request.stepExeLocals, request.conditionResults, {}, cancellationSignal);
|
|
83
|
+
const decision = await flow.flow.handleTimeout(context);
|
|
84
|
+
return InvokeExecuteMethodResponse.create({
|
|
85
|
+
stepDecision: mapDecision(flow, decision),
|
|
86
|
+
upsertAttributes: [...context.getAttributeWrites()],
|
|
87
|
+
recordEvents: [...context.getEvents()],
|
|
88
|
+
upsertStepExeLocals: [...context.getLocalWrites()],
|
|
89
|
+
publishToChannel: [...context.getPublications()],
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
catch (failure) {
|
|
93
|
+
throw invalidStepResult(flow.name, timeoutHandlerStepType, "execute", failure);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
async invokeRPC(original, cancellationSignal = new AbortController().signal) {
|
|
65
97
|
const request = await this.hydrateRPC(original);
|
|
98
|
+
cancellationSignal.throwIfAborted();
|
|
66
99
|
const flow = registeredFlowByName(this.registry, request.flowType);
|
|
67
100
|
const rpc = registeredRPCByName(flow, request.rpcName);
|
|
68
|
-
const context = new InvocationContext("rpc", flow, request.context, request.attributes, [], undefined, request.channelInfos);
|
|
101
|
+
const context = new InvocationContext("rpc", flow, request.context, request.attributes, [], undefined, request.channelInfos, cancellationSignal);
|
|
69
102
|
const returned = await invokeRPC(flow, rpc, context, request.input);
|
|
70
103
|
try {
|
|
71
104
|
const result = rpcResult(rpc, returned);
|
|
@@ -73,9 +106,7 @@ export class WorkerDispatcher {
|
|
|
73
106
|
output: rpc.options.outputCodec === undefined
|
|
74
107
|
? encodeUnknown(undefined)
|
|
75
108
|
: encodeValue(rpc.options.outputCodec, result?.output),
|
|
76
|
-
stepDecision:
|
|
77
|
-
? undefined
|
|
78
|
-
: ProtoStepDecision.create({ nextSteps: mapMovements(flow, result.nextSteps) }),
|
|
109
|
+
stepDecision: rpcDecision(flow, result),
|
|
79
110
|
upsertAttributes: [...context.getAttributeWrites()],
|
|
80
111
|
recordEvents: [...context.getEvents()],
|
|
81
112
|
publishToChannel: [...context.getPublications()],
|
|
@@ -98,17 +129,26 @@ export class WorkerDispatcher {
|
|
|
98
129
|
}
|
|
99
130
|
async hydrateExecute(request) {
|
|
100
131
|
const channelValues = request.conditionResults?.channelResults.flatMap((result) => result.values) ?? [];
|
|
132
|
+
const subFlowValues = request.conditionResults?.subFlowResults.flatMap((result) => result.results.map((completion) => completion.completedStepOutput)) ?? [];
|
|
133
|
+
const hasInput = request.stepInput !== undefined;
|
|
101
134
|
const values = await this.hydrator.hydrateAll([
|
|
102
|
-
request.stepInput,
|
|
135
|
+
...(hasInput ? [request.stepInput] : []),
|
|
103
136
|
...request.attributes.map((entry) => entry.value),
|
|
104
137
|
...request.stepExeLocals.map((entry) => entry.value),
|
|
105
138
|
...channelValues,
|
|
139
|
+
...subFlowValues,
|
|
106
140
|
]);
|
|
107
|
-
let offset = 1;
|
|
141
|
+
let offset = hasInput ? 1 : 0;
|
|
108
142
|
const attributes = replaceEntryValues(request.attributes, values.slice(offset, (offset += request.attributes.length)));
|
|
109
143
|
const stepExeLocals = replaceEntryValues(request.stepExeLocals, values.slice(offset, (offset += request.stepExeLocals.length)));
|
|
110
144
|
const conditionResults = replaceConditionValues(request.conditionResults, values.slice(offset));
|
|
111
|
-
return {
|
|
145
|
+
return {
|
|
146
|
+
...request,
|
|
147
|
+
stepInput: hasInput ? values[0] : undefined,
|
|
148
|
+
attributes,
|
|
149
|
+
stepExeLocals,
|
|
150
|
+
conditionResults,
|
|
151
|
+
};
|
|
112
152
|
}
|
|
113
153
|
async hydrateRPC(request) {
|
|
114
154
|
const hasInput = request.input !== undefined;
|
|
@@ -141,14 +181,14 @@ function rpcResult(rpc, returned) {
|
|
|
141
181
|
}
|
|
142
182
|
return returned;
|
|
143
183
|
}
|
|
144
|
-
function mapWait(flow, wait) {
|
|
184
|
+
function mapWait(registry, flow, wait) {
|
|
145
185
|
if (wait === undefined) {
|
|
146
186
|
throw new TypeError("waitFor returned undefined");
|
|
147
187
|
}
|
|
148
188
|
if (wait.kind === "skipImmediately") {
|
|
149
189
|
return undefined;
|
|
150
190
|
}
|
|
151
|
-
const mapper = new ConditionMapper(flow);
|
|
191
|
+
const mapper = new ConditionMapper(registry, flow);
|
|
152
192
|
let waitingConditionType;
|
|
153
193
|
const combinations = [];
|
|
154
194
|
if (wait.kind === "allOf" || wait.kind === "anyOf") {
|
|
@@ -176,6 +216,7 @@ function mapWait(flow, wait) {
|
|
|
176
216
|
waitingConditionType,
|
|
177
217
|
timerConditions: mapper.timers,
|
|
178
218
|
channelConditions: mapper.channels,
|
|
219
|
+
subFlowConditions: mapper.subFlows,
|
|
179
220
|
conditionCombinations: combinations,
|
|
180
221
|
});
|
|
181
222
|
}
|
|
@@ -187,14 +228,14 @@ function mapDecision(flow, decision) {
|
|
|
187
228
|
if (decision.movements.length === 0) {
|
|
188
229
|
throw new TypeError("goToMulti requires a movement");
|
|
189
230
|
}
|
|
190
|
-
return ProtoStepDecision.create({ nextSteps: mapMovements(flow, decision.movements) });
|
|
231
|
+
return withCancellationSelection(flow, decision, ProtoStepDecision.create({ nextSteps: mapMovements(flow, decision.movements) }));
|
|
191
232
|
}
|
|
192
233
|
if (decision.kind === "deadEnd") {
|
|
193
|
-
return ProtoStepDecision.create({
|
|
234
|
+
return withCancellationSelection(flow, decision, ProtoStepDecision.create({
|
|
194
235
|
closeDecision: CloseDecision.create({
|
|
195
236
|
closeDecisionType: CloseDecisionType.CLOSE_DECISION_TYPE_DEAD_END,
|
|
196
237
|
}),
|
|
197
|
-
});
|
|
238
|
+
}));
|
|
198
239
|
}
|
|
199
240
|
if (decision.kind === "forceCompleteIfChannelsEmpty") {
|
|
200
241
|
const channels = decision.channels.map((channel) => {
|
|
@@ -203,26 +244,64 @@ function mapDecision(flow, decision) {
|
|
|
203
244
|
}
|
|
204
245
|
return channel.name;
|
|
205
246
|
});
|
|
206
|
-
return ProtoStepDecision.create({
|
|
247
|
+
return withCancellationSelection(flow, decision, ProtoStepDecision.create({
|
|
207
248
|
nextSteps: [mapMovement(flow, decision.fallback)],
|
|
208
249
|
closeDecision: CloseDecision.create({
|
|
209
250
|
closeDecisionType: CloseDecisionType.CLOSE_DECISION_TYPE_FORCE_COMPLETE_ON_CHANNELS_EMPTY,
|
|
210
251
|
conditionalChannelNames: channels,
|
|
211
252
|
closeInput: encodeUnknown(decision.output),
|
|
212
253
|
}),
|
|
213
|
-
});
|
|
254
|
+
}));
|
|
214
255
|
}
|
|
215
256
|
const closeTypes = {
|
|
216
257
|
gracefulComplete: CloseDecisionType.CLOSE_DECISION_TYPE_GRACEFUL_COMPLETE,
|
|
217
258
|
forceComplete: CloseDecisionType.CLOSE_DECISION_TYPE_FORCE_COMPLETE,
|
|
218
259
|
forceFail: CloseDecisionType.CLOSE_DECISION_TYPE_FORCE_FAIL,
|
|
219
260
|
};
|
|
220
|
-
|
|
261
|
+
const closeInput = decision.kind === "forceFail"
|
|
262
|
+
? encodeUnknown(decision.reason)
|
|
263
|
+
: decision.output === undefined
|
|
264
|
+
? undefined
|
|
265
|
+
: encodeUnknown(decision.output);
|
|
266
|
+
return withCancellationSelection(flow, decision, ProtoStepDecision.create({
|
|
221
267
|
closeDecision: CloseDecision.create({
|
|
222
268
|
closeDecisionType: closeTypes[decision.kind],
|
|
223
|
-
closeInput
|
|
269
|
+
closeInput,
|
|
224
270
|
}),
|
|
225
|
-
});
|
|
271
|
+
}));
|
|
272
|
+
}
|
|
273
|
+
function withCancellationSelection(flow, decision, mapped) {
|
|
274
|
+
mapped.cancelStepTypes = mapCancellationSteps(flow, decision.cancelingSteps);
|
|
275
|
+
const globalTypes = new Set(mapped.cancelStepTypes);
|
|
276
|
+
mapped.cancelSiblingStepTypes = mapCancellationSteps(flow, decision.cancelingSiblingSteps).filter((stepType) => !globalTypes.has(stepType));
|
|
277
|
+
return mapped;
|
|
278
|
+
}
|
|
279
|
+
function mapCancellationSteps(flow, steps) {
|
|
280
|
+
const stepTypes = [];
|
|
281
|
+
const seen = new Set();
|
|
282
|
+
for (const step of steps ?? []) {
|
|
283
|
+
const target = flow.steps.find((candidate) => candidate.step === step);
|
|
284
|
+
if (target === undefined) {
|
|
285
|
+
throw new TypeError("cancellation Step must belong to the Flow");
|
|
286
|
+
}
|
|
287
|
+
if (seen.has(target.name)) {
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
seen.add(target.name);
|
|
291
|
+
stepTypes.push(target.name);
|
|
292
|
+
}
|
|
293
|
+
return stepTypes;
|
|
294
|
+
}
|
|
295
|
+
function rpcDecision(flow, result) {
|
|
296
|
+
if (result === undefined) {
|
|
297
|
+
return undefined;
|
|
298
|
+
}
|
|
299
|
+
const nextSteps = mapMovements(flow, result.nextSteps ?? []);
|
|
300
|
+
const cancelStepTypes = mapCancellationSteps(flow, result.cancelingSteps);
|
|
301
|
+
if (nextSteps.length === 0 && cancelStepTypes.length === 0) {
|
|
302
|
+
return undefined;
|
|
303
|
+
}
|
|
304
|
+
return ProtoStepDecision.create({ nextSteps, cancelStepTypes });
|
|
226
305
|
}
|
|
227
306
|
function mapMovements(flow, movements) {
|
|
228
307
|
return movements.map((movement) => mapMovement(flow, movement));
|
|
@@ -250,6 +329,7 @@ function mapStepOptions(flow, options, skipWaitFor) {
|
|
|
250
329
|
return ProtoStepOptions.create({
|
|
251
330
|
waitForTimeoutSeconds: seconds(options?.waitForMethodTimeoutMs),
|
|
252
331
|
executeTimeoutSeconds: seconds(options?.executeMethodTimeoutMs),
|
|
332
|
+
heartbeatTimeoutSeconds: heartbeatSeconds(options?.heartbeatTimeoutMs),
|
|
253
333
|
waitForRetryPolicy: mapRetry(options?.waitForRetry),
|
|
254
334
|
executeRetryPolicy: mapRetry(options?.executeRetry),
|
|
255
335
|
waitForFailurePolicy: options?.waitForFailure === "proceed"
|
|
@@ -296,12 +376,15 @@ function mapRetry(retry) {
|
|
|
296
376
|
};
|
|
297
377
|
}
|
|
298
378
|
class ConditionMapper {
|
|
379
|
+
registry;
|
|
299
380
|
flow;
|
|
300
381
|
timers = [];
|
|
301
382
|
channels = [];
|
|
383
|
+
subFlows = [];
|
|
302
384
|
ids = new Map();
|
|
303
385
|
used = new Set();
|
|
304
|
-
constructor(flow) {
|
|
386
|
+
constructor(registry, flow) {
|
|
387
|
+
this.registry = registry;
|
|
305
388
|
this.flow = flow;
|
|
306
389
|
}
|
|
307
390
|
add(condition, idRequired) {
|
|
@@ -328,7 +411,7 @@ class ConditionMapper {
|
|
|
328
411
|
durationSeconds: BigInt(seconds(condition.durationMs)),
|
|
329
412
|
}));
|
|
330
413
|
}
|
|
331
|
-
else {
|
|
414
|
+
else if (condition.kind === "channel") {
|
|
332
415
|
const registered = this.flow.persistence.get(condition.channelName ?? "");
|
|
333
416
|
if (!(registered instanceof Channel) && !(registered instanceof ChannelMap)) {
|
|
334
417
|
throw new TypeError(`Channel is not registered: ${condition.channelName ?? ""}`);
|
|
@@ -343,10 +426,141 @@ class ConditionMapper {
|
|
|
343
426
|
atMost: condition.atMost,
|
|
344
427
|
}));
|
|
345
428
|
}
|
|
429
|
+
else {
|
|
430
|
+
const targetFlow = condition.subFlow;
|
|
431
|
+
if (targetFlow === undefined) {
|
|
432
|
+
throw new TypeError("SubFlow requires a target Flow");
|
|
433
|
+
}
|
|
434
|
+
const target = registeredFlow(this.registry, targetFlow);
|
|
435
|
+
const start = target.startStep;
|
|
436
|
+
if (start === undefined) {
|
|
437
|
+
throw new TypeError(`SubFlow ${target.name} has no starting Step`);
|
|
438
|
+
}
|
|
439
|
+
const options = condition.subFlowOptions ?? {};
|
|
440
|
+
this.subFlows.push(ProtoSubFlowCondition.create({
|
|
441
|
+
conditionId: id,
|
|
442
|
+
subFlowType: target.name,
|
|
443
|
+
startStepType: start.name,
|
|
444
|
+
stepInput: encodeValue(start.step.inputCodec, condition.subFlowInput),
|
|
445
|
+
stepOptions: mapStepOptions(target, start.step.getStepOptions?.(), start.step.waitFor === undefined),
|
|
446
|
+
options: mapSubFlowOptions(target, options),
|
|
447
|
+
subFlowIndex: this.subFlows.length,
|
|
448
|
+
}));
|
|
449
|
+
}
|
|
346
450
|
this.ids.set(condition, id);
|
|
347
451
|
return id;
|
|
348
452
|
}
|
|
349
453
|
}
|
|
454
|
+
function mapSubFlowOptions(target, options) {
|
|
455
|
+
const timeoutSeconds = seconds(options.timeoutMs);
|
|
456
|
+
const attributes = (options.attributes ?? []).map((initial) => {
|
|
457
|
+
if (target.persistence.get(initial.attribute.name) !== initial.attribute) {
|
|
458
|
+
throw new TypeError(`SubFlow Attribute does not belong to ${target.name}`);
|
|
459
|
+
}
|
|
460
|
+
let key;
|
|
461
|
+
if (initial.attribute instanceof AttributeMap) {
|
|
462
|
+
key = physicalName(initial.attribute.name, initial.instance);
|
|
463
|
+
}
|
|
464
|
+
else {
|
|
465
|
+
if (initial.instance !== undefined) {
|
|
466
|
+
throw new TypeError("static Attribute cannot use an instance");
|
|
467
|
+
}
|
|
468
|
+
key = initial.attribute.name;
|
|
469
|
+
}
|
|
470
|
+
return {
|
|
471
|
+
key,
|
|
472
|
+
value: encodeValue(initial.attribute.codec, initial.value),
|
|
473
|
+
indexConfig: mapIndex(initial.attribute.index),
|
|
474
|
+
syncConfig: mapAttributeStoreSync(initial.attribute),
|
|
475
|
+
};
|
|
476
|
+
});
|
|
477
|
+
const reusePolicy = options.reusePolicy === SubFlowReusePolicy.ATTACH
|
|
478
|
+
? ProtoSubFlowReusePolicy.SUB_FLOW_REUSE_POLICY_ATTACH
|
|
479
|
+
: options.reusePolicy === SubFlowReusePolicy.ALWAYS_RESTART
|
|
480
|
+
? ProtoSubFlowReusePolicy.SUB_FLOW_REUSE_POLICY_ALWAYS_RESTART
|
|
481
|
+
: ProtoSubFlowReusePolicy.SUB_FLOW_REUSE_POLICY_RESTART_IF_PREVIOUS_EXITS_ABNORMALLY;
|
|
482
|
+
return ProtoSubFlowOptions.create({
|
|
483
|
+
reusePolicy,
|
|
484
|
+
flowTimeoutSeconds: timeoutSeconds,
|
|
485
|
+
flowTimeoutPolicy: resolveFlowTimeoutPolicy(target, timeoutSeconds, options.timeoutPolicy),
|
|
486
|
+
flowStartDelaySeconds: seconds(options.startDelayMs),
|
|
487
|
+
retryPolicy: mapFlowRetry(options.retryPolicy),
|
|
488
|
+
attributes,
|
|
489
|
+
flowConfigOverride: mapSubFlowConfig(options.configOverride),
|
|
490
|
+
});
|
|
491
|
+
}
|
|
492
|
+
function resolveFlowTimeoutPolicy(flow, timeoutSeconds, policy) {
|
|
493
|
+
const requested = policy ?? FlowTimeoutPolicy.DEFAULT;
|
|
494
|
+
if (timeoutSeconds === 0) {
|
|
495
|
+
if (requested !== FlowTimeoutPolicy.DEFAULT) {
|
|
496
|
+
throw new RangeError("Flow timeout policy requires a positive timeout");
|
|
497
|
+
}
|
|
498
|
+
return ProtoFlowTimeoutPolicy.FLOW_TIMEOUT_POLICY_UNSPECIFIED;
|
|
499
|
+
}
|
|
500
|
+
const resolved = requested === FlowTimeoutPolicy.DEFAULT
|
|
501
|
+
? flow.hasTimeoutHandler
|
|
502
|
+
? FlowTimeoutPolicy.HANDLER
|
|
503
|
+
: FlowTimeoutPolicy.FAIL
|
|
504
|
+
: requested;
|
|
505
|
+
if (resolved === FlowTimeoutPolicy.HANDLER && !flow.hasTimeoutHandler) {
|
|
506
|
+
throw new TypeError(`Flow ${flow.name} does not implement handleTimeout`);
|
|
507
|
+
}
|
|
508
|
+
return {
|
|
509
|
+
[FlowTimeoutPolicy.DEFAULT]: ProtoFlowTimeoutPolicy.FLOW_TIMEOUT_POLICY_UNSPECIFIED,
|
|
510
|
+
[FlowTimeoutPolicy.FAIL]: ProtoFlowTimeoutPolicy.FLOW_TIMEOUT_POLICY_FAIL,
|
|
511
|
+
[FlowTimeoutPolicy.CANCEL]: ProtoFlowTimeoutPolicy.FLOW_TIMEOUT_POLICY_CANCEL,
|
|
512
|
+
[FlowTimeoutPolicy.HANDLER]: ProtoFlowTimeoutPolicy.FLOW_TIMEOUT_POLICY_HANDLER,
|
|
513
|
+
}[resolved];
|
|
514
|
+
}
|
|
515
|
+
function mapFlowRetry(retry) {
|
|
516
|
+
if (retry === undefined)
|
|
517
|
+
return undefined;
|
|
518
|
+
return FlowRetryPolicy.create({
|
|
519
|
+
initialIntervalSeconds: seconds(retry.initialIntervalMs),
|
|
520
|
+
backoffCoefficient: retry.backoffCoefficient ?? 0,
|
|
521
|
+
maximumIntervalSeconds: seconds(retry.maximumIntervalMs),
|
|
522
|
+
maximumAttempts: retry.maximumAttempts ?? 0,
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
function mapSubFlowConfig(config) {
|
|
526
|
+
if (config === undefined)
|
|
527
|
+
return undefined;
|
|
528
|
+
return ProtoFlowConfig.create({
|
|
529
|
+
activeStepSearchMode: config.activeStepSearchMode === ActiveStepSearchMode.ALL
|
|
530
|
+
? ProtoActiveStepSearchMode.ACTIVE_STEP_SEARCH_MODE_ENABLED_FOR_ALL
|
|
531
|
+
: config.activeStepSearchMode === undefined
|
|
532
|
+
? undefined
|
|
533
|
+
: ProtoActiveStepSearchMode.ACTIVE_STEP_SEARCH_MODE_UNSPECIFIED,
|
|
534
|
+
attributeSyncConfigName: mapAttributeStoreName(config),
|
|
535
|
+
continueAsNewThreshold: config.continueAsNewThreshold,
|
|
536
|
+
continueAsNewPageSizeInBytes: config.continueAsNewPageSizeBytes,
|
|
537
|
+
stepDurability: config.stepDurability === "sync"
|
|
538
|
+
? ProtoStepDurability.STEP_DURABILITY_SYNC
|
|
539
|
+
: config.stepDurability === "async"
|
|
540
|
+
? ProtoStepDurability.STEP_DURABILITY_ASYNC
|
|
541
|
+
: undefined,
|
|
542
|
+
workerTarget: config.workerTarget === undefined
|
|
543
|
+
? undefined
|
|
544
|
+
: {
|
|
545
|
+
address: config.workerTarget.address,
|
|
546
|
+
isHeadlessAddress: config.workerTarget.headless ?? false,
|
|
547
|
+
},
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
function mapIndex(index) {
|
|
551
|
+
if (index === undefined)
|
|
552
|
+
return undefined;
|
|
553
|
+
const types = {
|
|
554
|
+
[IndexType.KEYWORD]: ProtoIndexType.INDEX_TYPE_KEYWORD,
|
|
555
|
+
[IndexType.FULL_TEXT]: ProtoIndexType.INDEX_TYPE_TEXT,
|
|
556
|
+
[IndexType.KEYWORD_ARRAY]: ProtoIndexType.INDEX_TYPE_KEYWORD_ARRAY,
|
|
557
|
+
[IndexType.INT]: ProtoIndexType.INDEX_TYPE_INT,
|
|
558
|
+
[IndexType.DOUBLE]: ProtoIndexType.INDEX_TYPE_DOUBLE,
|
|
559
|
+
[IndexType.BOOL]: ProtoIndexType.INDEX_TYPE_BOOL,
|
|
560
|
+
[IndexType.DATETIME]: ProtoIndexType.INDEX_TYPE_DATETIME,
|
|
561
|
+
};
|
|
562
|
+
return { enable: true, type: types[index.type], indexKey: index.indexKey ?? "" };
|
|
563
|
+
}
|
|
350
564
|
function replaceEntryValues(entries, values) {
|
|
351
565
|
if (entries.length !== values.length) {
|
|
352
566
|
throw new TypeError("hydrated entry count does not match request");
|
|
@@ -367,10 +581,17 @@ function replaceConditionValues(results, values) {
|
|
|
367
581
|
offset = next;
|
|
368
582
|
return replaced;
|
|
369
583
|
});
|
|
584
|
+
const subFlowResults = results.subFlowResults.map((result) => ({
|
|
585
|
+
...result,
|
|
586
|
+
results: result.results.map((completion) => ({
|
|
587
|
+
...completion,
|
|
588
|
+
completedStepOutput: values[offset++],
|
|
589
|
+
})),
|
|
590
|
+
}));
|
|
370
591
|
if (offset !== values.length) {
|
|
371
592
|
throw new TypeError("hydrated Condition value count does not match request");
|
|
372
593
|
}
|
|
373
|
-
return { ...results, channelResults };
|
|
594
|
+
return { ...results, channelResults, subFlowResults };
|
|
374
595
|
}
|
|
375
596
|
function requireValue(value, kind) {
|
|
376
597
|
if (value?.kind === undefined) {
|
|
@@ -393,6 +614,13 @@ function seconds(milliseconds) {
|
|
|
393
614
|
}
|
|
394
615
|
return milliseconds / 1_000;
|
|
395
616
|
}
|
|
617
|
+
function heartbeatSeconds(milliseconds) {
|
|
618
|
+
const value = seconds(milliseconds);
|
|
619
|
+
if (value > 2_147_483_647) {
|
|
620
|
+
throw new RangeError("heartbeat timeout exceeds int32 seconds");
|
|
621
|
+
}
|
|
622
|
+
return value;
|
|
623
|
+
}
|
|
396
624
|
function invalidStepResult(flowType, stepType, method, failure) {
|
|
397
625
|
if (failure instanceof ValueMappingError) {
|
|
398
626
|
return failure;
|