@pikku/core 0.11.0 → 0.11.2
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/CHANGELOG.md +35 -1
- package/dist/errors/error-handler.js +3 -3
- package/dist/errors/errors.d.ts +1 -1
- package/dist/errors/errors.js +3 -3
- package/dist/function/function-runner.d.ts +8 -8
- package/dist/function/function-runner.js +88 -23
- package/dist/function/functions.types.d.ts +104 -33
- package/dist/function/functions.types.js +50 -7
- package/dist/handle-error.d.ts +1 -1
- package/dist/handle-error.js +1 -1
- package/dist/index.d.ts +6 -2
- package/dist/index.js +5 -2
- package/dist/middleware/auth-apikey.d.ts +1 -1
- package/dist/middleware/auth-apikey.js +3 -3
- package/dist/middleware/auth-bearer.d.ts +1 -1
- package/dist/middleware/auth-bearer.js +3 -3
- package/dist/middleware/auth-cookie.d.ts +1 -1
- package/dist/middleware/auth-cookie.js +5 -5
- package/dist/middleware/timeout.d.ts +1 -1
- package/dist/middleware/timeout.js +3 -2
- package/dist/middleware-runner.d.ts +6 -20
- package/dist/middleware-runner.js +19 -20
- package/dist/permissions.d.ts +6 -89
- package/dist/permissions.js +24 -81
- package/dist/pikku-state.d.ts +32 -104
- package/dist/pikku-state.js +140 -66
- package/dist/schema.d.ts +8 -6
- package/dist/schema.js +25 -13
- package/dist/services/user-session-service.d.ts +7 -3
- package/dist/services/user-session-service.js +8 -1
- package/dist/services/workflow-service.d.ts +38 -0
- package/dist/services/workflow-service.js +1 -0
- package/dist/types/core.types.d.ts +40 -41
- package/dist/types/core.types.js +4 -15
- package/dist/types/state.types.d.ts +135 -0
- package/dist/types/state.types.js +1 -0
- package/dist/utils.d.ts +9 -1
- package/dist/utils.js +48 -3
- package/dist/wirings/channel/channel-common.js +2 -3
- package/dist/wirings/channel/channel-handler.d.ts +3 -2
- package/dist/wirings/channel/channel-handler.js +7 -10
- package/dist/wirings/channel/channel-runner.d.ts +2 -2
- package/dist/wirings/channel/channel-runner.js +5 -5
- package/dist/wirings/channel/channel.types.d.ts +10 -5
- package/dist/wirings/channel/local/local-channel-runner.d.ts +1 -1
- package/dist/wirings/channel/local/local-channel-runner.js +19 -26
- package/dist/wirings/channel/log-channels.js +1 -1
- package/dist/wirings/channel/serverless/serverless-channel-runner.d.ts +1 -1
- package/dist/wirings/channel/serverless/serverless-channel-runner.js +43 -48
- package/dist/wirings/cli/channel/cli-channel-runner.js +3 -2
- package/dist/wirings/cli/cli-runner.d.ts +5 -5
- package/dist/wirings/cli/cli-runner.js +20 -38
- package/dist/wirings/cli/cli.types.d.ts +16 -11
- package/dist/wirings/forge-node/forge-node.types.d.ts +120 -0
- package/dist/wirings/forge-node/forge-node.types.js +38 -0
- package/dist/wirings/forge-node/index.d.ts +1 -0
- package/dist/wirings/forge-node/index.js +1 -0
- package/dist/wirings/http/http-runner.d.ts +8 -8
- package/dist/wirings/http/http-runner.js +46 -51
- package/dist/wirings/http/http.types.d.ts +19 -11
- package/dist/wirings/http/log-http-routes.js +1 -1
- package/dist/wirings/http/routers/path-to-regex.js +2 -2
- package/dist/wirings/mcp/mcp-runner.d.ts +2 -2
- package/dist/wirings/mcp/mcp-runner.js +33 -40
- package/dist/wirings/mcp/mcp.types.d.ts +6 -0
- package/dist/wirings/queue/queue-runner.d.ts +3 -3
- package/dist/wirings/queue/queue-runner.js +13 -23
- package/dist/wirings/queue/queue.types.d.ts +4 -11
- package/dist/wirings/rpc/index.d.ts +1 -1
- package/dist/wirings/rpc/index.js +1 -1
- package/dist/wirings/rpc/rpc-runner.d.ts +17 -16
- package/dist/wirings/rpc/rpc-runner.js +98 -61
- package/dist/wirings/rpc/rpc-types.d.ts +7 -0
- package/dist/wirings/scheduler/log-schedulers.js +1 -1
- package/dist/wirings/scheduler/scheduler-runner.d.ts +3 -3
- package/dist/wirings/scheduler/scheduler-runner.js +18 -29
- package/dist/wirings/scheduler/scheduler.types.d.ts +3 -8
- package/dist/wirings/trigger/index.d.ts +2 -0
- package/dist/wirings/trigger/index.js +2 -0
- package/dist/wirings/trigger/trigger-runner.d.ts +29 -0
- package/dist/wirings/trigger/trigger-runner.js +57 -0
- package/dist/wirings/trigger/trigger.types.d.ts +42 -0
- package/dist/wirings/trigger/trigger.types.js +1 -0
- package/dist/wirings/workflow/dsl/index.d.ts +5 -0
- package/dist/wirings/workflow/dsl/index.js +4 -0
- package/dist/wirings/workflow/dsl/workflow-dsl.types.d.ts +286 -0
- package/dist/wirings/workflow/dsl/workflow-dsl.types.js +5 -0
- package/dist/wirings/workflow/dsl/workflow-runner.d.ts +5 -0
- package/dist/wirings/workflow/dsl/workflow-runner.js +22 -0
- package/dist/wirings/workflow/graph/graph-node.d.ts +122 -0
- package/dist/wirings/workflow/graph/graph-node.js +58 -0
- package/dist/wirings/workflow/graph/graph-runner.d.ts +35 -0
- package/dist/wirings/workflow/graph/graph-runner.js +452 -0
- package/dist/wirings/workflow/graph/index.d.ts +3 -0
- package/dist/wirings/workflow/graph/index.js +3 -0
- package/dist/wirings/workflow/graph/workflow-graph.types.d.ts +95 -0
- package/dist/wirings/workflow/graph/workflow-graph.types.js +15 -0
- package/dist/wirings/workflow/index.d.ts +7 -3
- package/dist/wirings/workflow/index.js +6 -3
- package/dist/wirings/workflow/pikku-workflow-service.d.ts +108 -10
- package/dist/wirings/workflow/pikku-workflow-service.js +274 -165
- package/dist/wirings/workflow/wire-workflow.d.ts +42 -0
- package/dist/wirings/workflow/wire-workflow.js +53 -0
- package/dist/wirings/workflow/workflow-utils.d.ts +23 -0
- package/dist/wirings/workflow/workflow-utils.js +66 -0
- package/dist/wirings/workflow/workflow.types.d.ts +135 -128
- package/package.json +11 -2
- package/src/errors/error-handler.ts +3 -3
- package/src/errors/errors.ts +3 -3
- package/src/factory-functions.test.ts +9 -36
- package/src/function/function-runner.test.ts +58 -69
- package/src/function/function-runner.ts +130 -37
- package/src/function/functions.types.ts +193 -54
- package/src/handle-error.ts +1 -1
- package/src/index.ts +10 -5
- package/src/middleware/auth-apikey.test.ts +360 -0
- package/src/middleware/auth-apikey.ts +3 -7
- package/src/middleware/auth-bearer.test.ts +447 -0
- package/src/middleware/auth-bearer.ts +27 -33
- package/src/middleware/auth-cookie.test.ts +525 -0
- package/src/middleware/auth-cookie.ts +6 -6
- package/src/middleware/timeout.ts +4 -2
- package/src/middleware-runner.test.ts +58 -127
- package/src/middleware-runner.ts +29 -25
- package/src/permissions.test.ts +68 -130
- package/src/permissions.ts +41 -100
- package/src/pikku-state.ts +156 -201
- package/src/schema.ts +42 -13
- package/src/services/user-session-service.ts +14 -4
- package/src/services/workflow-service.ts +74 -0
- package/src/types/core.types.ts +79 -58
- package/src/types/state.types.ts +195 -0
- package/src/utils.ts +59 -4
- package/src/wirings/channel/channel-common.ts +4 -7
- package/src/wirings/channel/channel-handler.ts +17 -23
- package/src/wirings/channel/channel-runner.ts +7 -7
- package/src/wirings/channel/channel.types.ts +14 -11
- package/src/wirings/channel/local/local-channel-runner.test.ts +8 -4
- package/src/wirings/channel/local/local-channel-runner.ts +23 -38
- package/src/wirings/channel/log-channels.ts +1 -1
- package/src/wirings/channel/serverless/serverless-channel-runner.ts +53 -79
- package/src/wirings/cli/channel/cli-channel-runner.ts +4 -3
- package/src/wirings/cli/cli-runner.test.ts +26 -26
- package/src/wirings/cli/cli-runner.ts +34 -71
- package/src/wirings/cli/cli.types.ts +23 -16
- package/src/wirings/forge-node/forge-node.types.ts +135 -0
- package/src/wirings/forge-node/index.ts +1 -0
- package/src/wirings/http/http-runner.test.ts +10 -10
- package/src/wirings/http/http-runner.ts +56 -66
- package/src/wirings/http/http.types.ts +19 -14
- package/src/wirings/http/log-http-routes.ts +1 -1
- package/src/wirings/http/routers/path-to-regex.test.ts +30 -19
- package/src/wirings/http/routers/path-to-regex.ts +2 -2
- package/src/wirings/mcp/mcp-runner.ts +44 -69
- package/src/wirings/mcp/mcp.types.ts +6 -0
- package/src/wirings/queue/queue-runner.test.ts +641 -0
- package/src/wirings/queue/queue-runner.ts +16 -38
- package/src/wirings/queue/queue.types.ts +4 -11
- package/src/wirings/rpc/index.ts +1 -1
- package/src/wirings/rpc/rpc-runner.ts +129 -77
- package/src/wirings/rpc/rpc-types.ts +8 -0
- package/src/wirings/scheduler/log-schedulers.ts +1 -1
- package/src/wirings/scheduler/scheduler-runner.test.ts +627 -0
- package/src/wirings/scheduler/scheduler-runner.ts +29 -55
- package/src/wirings/scheduler/scheduler.types.ts +3 -9
- package/src/wirings/trigger/index.ts +2 -0
- package/src/wirings/trigger/trigger-runner.ts +96 -0
- package/src/wirings/trigger/trigger.types.ts +56 -0
- package/src/wirings/workflow/dsl/index.ts +30 -0
- package/src/wirings/workflow/dsl/workflow-dsl.types.ts +312 -0
- package/src/wirings/workflow/dsl/workflow-runner.ts +27 -0
- package/src/wirings/workflow/graph/graph-node.ts +227 -0
- package/src/wirings/workflow/graph/graph-runner.ts +694 -0
- package/src/wirings/workflow/graph/index.ts +3 -0
- package/src/wirings/workflow/graph/workflow-graph.types.ts +126 -0
- package/src/wirings/workflow/index.ts +60 -12
- package/src/wirings/workflow/pikku-workflow-service.ts +401 -195
- package/src/wirings/workflow/wire-workflow.ts +94 -0
- package/src/wirings/workflow/workflow-utils.ts +120 -0
- package/src/wirings/workflow/workflow.types.ts +167 -188
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/wirings/workflow/workflow-runner.d.ts +0 -35
- package/dist/wirings/workflow/workflow-runner.js +0 -68
- package/src/wirings/workflow/workflow-runner.ts +0 -85
|
@@ -3,28 +3,67 @@ import { pikkuState } from '../../pikku-state.js'
|
|
|
3
3
|
import { getDurationInMilliseconds } from '../../time-utils.js'
|
|
4
4
|
import {
|
|
5
5
|
CoreConfig,
|
|
6
|
-
CoreServices,
|
|
7
6
|
CoreSingletonServices,
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
CreateWireServices,
|
|
8
|
+
PikkuWire,
|
|
10
9
|
SerializedError,
|
|
11
10
|
} from '../../types/core.types.js'
|
|
12
11
|
import { QueueService } from '../queue/queue.types.js'
|
|
13
|
-
import {
|
|
14
|
-
WorkflowAsyncException,
|
|
15
|
-
WorkflowCancelledException,
|
|
16
|
-
WorkflowNotFoundError,
|
|
17
|
-
WorkflowRunNotFound,
|
|
18
|
-
} from './workflow-runner.js'
|
|
19
12
|
import type {
|
|
20
|
-
|
|
13
|
+
PikkuWorkflowWire,
|
|
21
14
|
StepState,
|
|
22
15
|
WorkflowRun,
|
|
23
16
|
WorkflowStatus,
|
|
24
|
-
WorkflowService,
|
|
25
17
|
WorkflowServiceConfig,
|
|
26
18
|
WorkflowStepOptions,
|
|
27
19
|
} from './workflow.types.js'
|
|
20
|
+
import { executeGraphStep, runWorkflowGraph } from './graph/graph-runner.js'
|
|
21
|
+
import { WorkflowService } from '../../services/workflow-service.js'
|
|
22
|
+
import { PikkuError } from '../../errors/error-handler.js'
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Exception thrown when workflow needs to pause for async step
|
|
26
|
+
*/
|
|
27
|
+
export class WorkflowAsyncException extends Error {
|
|
28
|
+
constructor(
|
|
29
|
+
public readonly runId: string,
|
|
30
|
+
public readonly stepName: string
|
|
31
|
+
) {
|
|
32
|
+
super(`Workflow paused at step: ${stepName}`)
|
|
33
|
+
this.name = 'WorkflowAsyncException'
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Exception thrown when workflow is cancelled
|
|
39
|
+
*/
|
|
40
|
+
export class WorkflowCancelledException extends Error {
|
|
41
|
+
constructor(
|
|
42
|
+
public readonly runId: string,
|
|
43
|
+
public readonly reason?: string
|
|
44
|
+
) {
|
|
45
|
+
super(reason || 'Workflow cancelled')
|
|
46
|
+
this.name = 'WorkflowCancelledException'
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Error class for workflow not found
|
|
52
|
+
*/
|
|
53
|
+
export class WorkflowNotFoundError extends PikkuError {
|
|
54
|
+
constructor(name: string) {
|
|
55
|
+
super(`Workflow not found: ${name}`)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Error class for workflow not found
|
|
61
|
+
*/
|
|
62
|
+
export class WorkflowRunNotFound extends PikkuError {
|
|
63
|
+
constructor(runId: string) {
|
|
64
|
+
super(`Workflow run not found: ${runId}`)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
28
67
|
|
|
29
68
|
export class WorkflowServiceNotInitialized extends Error {}
|
|
30
69
|
export class WorkflowStepNameNotString extends Error {
|
|
@@ -41,17 +80,39 @@ export class WorkflowStepNameNotString extends Error {
|
|
|
41
80
|
export abstract class PikkuWorkflowService implements WorkflowService {
|
|
42
81
|
private config: WorkflowServiceConfig | undefined
|
|
43
82
|
private singletonServices: CoreSingletonServices | undefined
|
|
44
|
-
private
|
|
83
|
+
private createWireServices: CreateWireServices | undefined
|
|
84
|
+
private inlineRuns = new Set<string>()
|
|
45
85
|
|
|
46
86
|
constructor() {}
|
|
47
87
|
|
|
88
|
+
/**
|
|
89
|
+
* Check if a run is executing inline (without queues)
|
|
90
|
+
*/
|
|
91
|
+
protected isInline(runId: string): boolean {
|
|
92
|
+
return this.inlineRuns.has(runId)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Register a run as inline (for graph-runner to use)
|
|
97
|
+
*/
|
|
98
|
+
public registerInlineRun(runId: string): void {
|
|
99
|
+
this.inlineRuns.add(runId)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Unregister a run from inline tracking
|
|
104
|
+
*/
|
|
105
|
+
public unregisterInlineRun(runId: string): void {
|
|
106
|
+
this.inlineRuns.delete(runId)
|
|
107
|
+
}
|
|
108
|
+
|
|
48
109
|
public setServices(
|
|
49
110
|
singletonServices: CoreSingletonServices,
|
|
50
|
-
|
|
111
|
+
createWireServices: CreateWireServices,
|
|
51
112
|
{ workflow }: CoreConfig
|
|
52
113
|
) {
|
|
53
114
|
this.singletonServices = singletonServices
|
|
54
|
-
this.
|
|
115
|
+
this.createWireServices = createWireServices
|
|
55
116
|
this.config = {
|
|
56
117
|
retries: workflow?.retries ?? 0,
|
|
57
118
|
retryDelay: workflow?.retryDelay ?? 0,
|
|
@@ -59,7 +120,7 @@ export abstract class PikkuWorkflowService implements WorkflowService {
|
|
|
59
120
|
workflow?.orchestratorQueueName ?? 'pikku-workflow-orchestrator',
|
|
60
121
|
stepWorkerQueueName:
|
|
61
122
|
workflow?.stepWorkerQueueName ?? 'pikku-workflow-step-worker',
|
|
62
|
-
sleeperRPCName: workflow?.sleeperRPCName ?? '
|
|
123
|
+
sleeperRPCName: workflow?.sleeperRPCName ?? 'pikkuWorkflowSleeper',
|
|
63
124
|
}
|
|
64
125
|
}
|
|
65
126
|
|
|
@@ -69,7 +130,11 @@ export abstract class PikkuWorkflowService implements WorkflowService {
|
|
|
69
130
|
* @param input - Input data for the workflow
|
|
70
131
|
* @returns Run ID
|
|
71
132
|
*/
|
|
72
|
-
abstract createRun(
|
|
133
|
+
abstract createRun(
|
|
134
|
+
workflowName: string,
|
|
135
|
+
input: any,
|
|
136
|
+
inline?: boolean
|
|
137
|
+
): Promise<string>
|
|
73
138
|
|
|
74
139
|
/**
|
|
75
140
|
* Get a workflow run by ID
|
|
@@ -176,11 +241,86 @@ export abstract class PikkuWorkflowService implements WorkflowService {
|
|
|
176
241
|
*/
|
|
177
242
|
abstract withRunLock<T>(id: string, fn: () => Promise<T>): Promise<T>
|
|
178
243
|
|
|
244
|
+
/**
|
|
245
|
+
* Execute function within a step lock to prevent concurrent step execution
|
|
246
|
+
* @param runId - Run ID
|
|
247
|
+
* @param stepName - Step name
|
|
248
|
+
* @param fn - Function to execute
|
|
249
|
+
* @returns Function result
|
|
250
|
+
*/
|
|
251
|
+
abstract withStepLock<T>(
|
|
252
|
+
runId: string,
|
|
253
|
+
stepName: string,
|
|
254
|
+
fn: () => Promise<T>
|
|
255
|
+
): Promise<T>
|
|
256
|
+
|
|
179
257
|
/**
|
|
180
258
|
* Close any open connections
|
|
181
259
|
*/
|
|
182
260
|
abstract close(): Promise<void>
|
|
183
261
|
|
|
262
|
+
// ============================================================================
|
|
263
|
+
// Workflow Graph Methods
|
|
264
|
+
// ============================================================================
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Get completed graph state (lightweight - no results)
|
|
268
|
+
* @param runId - Run ID
|
|
269
|
+
* @returns Completed node IDs and their branch keys
|
|
270
|
+
*/
|
|
271
|
+
abstract getCompletedGraphState(runId: string): Promise<{
|
|
272
|
+
completedNodeIds: string[]
|
|
273
|
+
branchKeys: Record<string, string>
|
|
274
|
+
}>
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Filter candidate nodes to only those without existing steps
|
|
278
|
+
* @param runId - Run ID
|
|
279
|
+
* @param nodeIds - Candidate node IDs to check
|
|
280
|
+
* @returns Node IDs that don't have a step yet
|
|
281
|
+
*/
|
|
282
|
+
abstract getNodesWithoutSteps(
|
|
283
|
+
runId: string,
|
|
284
|
+
nodeIds: string[]
|
|
285
|
+
): Promise<string[]>
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Get results for specific nodes
|
|
289
|
+
* @param runId - Run ID
|
|
290
|
+
* @param nodeIds - Node IDs to fetch results for
|
|
291
|
+
* @returns Map of nodeId to result
|
|
292
|
+
*/
|
|
293
|
+
abstract getNodeResults(
|
|
294
|
+
runId: string,
|
|
295
|
+
nodeIds: string[]
|
|
296
|
+
): Promise<Record<string, any>>
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Set the branch key for a graph node step
|
|
300
|
+
* @param stepId - Step ID
|
|
301
|
+
* @param branchKey - Branch key selected by graph.branch()
|
|
302
|
+
*/
|
|
303
|
+
abstract setBranchTaken(stepId: string, branchKey: string): Promise<void>
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Update a state variable in the workflow run's state
|
|
307
|
+
* @param runId - Run ID
|
|
308
|
+
* @param name - Variable name
|
|
309
|
+
* @param value - Value to store
|
|
310
|
+
*/
|
|
311
|
+
abstract updateRunState(
|
|
312
|
+
runId: string,
|
|
313
|
+
name: string,
|
|
314
|
+
value: unknown
|
|
315
|
+
): Promise<void>
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Get the entire state object for a workflow run
|
|
319
|
+
* @param runId - Run ID
|
|
320
|
+
* @returns The state object with all variables
|
|
321
|
+
*/
|
|
322
|
+
abstract getRunState(runId: string): Promise<Record<string, unknown>>
|
|
323
|
+
|
|
184
324
|
// ============================================================================
|
|
185
325
|
// Workflow Lifecycle Methods
|
|
186
326
|
// ============================================================================
|
|
@@ -199,7 +339,7 @@ export abstract class PikkuWorkflowService implements WorkflowService {
|
|
|
199
339
|
* Sets the step result to null and resumes the workflow
|
|
200
340
|
* @param data - Sleeper input data
|
|
201
341
|
*/
|
|
202
|
-
public async
|
|
342
|
+
public async executeWorkflowSleepCompleted(
|
|
203
343
|
runId: string,
|
|
204
344
|
stepId: string
|
|
205
345
|
): Promise<void> {
|
|
@@ -226,13 +366,39 @@ export abstract class PikkuWorkflowService implements WorkflowService {
|
|
|
226
366
|
|
|
227
367
|
/**
|
|
228
368
|
* Start a new workflow run
|
|
369
|
+
* Automatically detects workflow type (DSL or graph) from meta and executes accordingly
|
|
370
|
+
* @param options.inline - If true, execute workflow directly without queue service
|
|
371
|
+
* @param options.startNode - Starting node ID for graph workflows (from wire config)
|
|
229
372
|
*/
|
|
230
373
|
public async startWorkflow<I>(
|
|
231
374
|
name: string,
|
|
232
375
|
input: I,
|
|
233
|
-
rpcService: any
|
|
376
|
+
rpcService: any,
|
|
377
|
+
options?: { inline?: boolean; startNode?: string }
|
|
234
378
|
): Promise<{ runId: string }> {
|
|
235
|
-
|
|
379
|
+
// Check meta to determine workflow type
|
|
380
|
+
const meta = pikkuState(null, 'workflows', 'meta')
|
|
381
|
+
const workflowMeta = meta[name]
|
|
382
|
+
|
|
383
|
+
if (!workflowMeta) {
|
|
384
|
+
throw new WorkflowNotFoundError(name)
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// Check if this is a graph workflow (source === 'graph')
|
|
388
|
+
if (workflowMeta.source === 'graph') {
|
|
389
|
+
// Graph workflows use the graph scheduler
|
|
390
|
+
return runWorkflowGraph(
|
|
391
|
+
this,
|
|
392
|
+
name,
|
|
393
|
+
input,
|
|
394
|
+
rpcService,
|
|
395
|
+
options?.inline,
|
|
396
|
+
options?.startNode
|
|
397
|
+
)
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// DSL workflow - check registration exists
|
|
401
|
+
const registrations = pikkuState(null, 'workflows', 'registrations')
|
|
236
402
|
const workflow = registrations.get(name)
|
|
237
403
|
|
|
238
404
|
if (!workflow) {
|
|
@@ -240,82 +406,68 @@ export abstract class PikkuWorkflowService implements WorkflowService {
|
|
|
240
406
|
}
|
|
241
407
|
|
|
242
408
|
// Create workflow run in state
|
|
243
|
-
const runId = await this.createRun(name, input)
|
|
409
|
+
const runId = await this.createRun(name, input, options?.inline)
|
|
244
410
|
|
|
245
|
-
//
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
// Queue orchestrator to start the workflow
|
|
249
|
-
await this.resumeWorkflow(runId)
|
|
250
|
-
} else {
|
|
251
|
-
// No queue service - execute directly via runWorkflowJob
|
|
252
|
-
await this.runWorkflowJob(runId, rpcService)
|
|
411
|
+
// Register inline run for fast lookup
|
|
412
|
+
if (options?.inline) {
|
|
413
|
+
this.inlineRuns.add(runId)
|
|
253
414
|
}
|
|
254
415
|
|
|
255
|
-
|
|
416
|
+
try {
|
|
417
|
+
// If inline mode or no queue service, execute directly
|
|
418
|
+
// Otherwise, use remote execution (queue-based)
|
|
419
|
+
if (options?.inline || !this.singletonServices?.queueService) {
|
|
420
|
+
await this.runWorkflowJob(runId, rpcService)
|
|
421
|
+
} else {
|
|
422
|
+
await this.resumeWorkflow(runId)
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
return { runId }
|
|
426
|
+
} finally {
|
|
427
|
+
// Clean up inline tracking
|
|
428
|
+
if (options?.inline) {
|
|
429
|
+
this.inlineRuns.delete(runId)
|
|
430
|
+
}
|
|
431
|
+
}
|
|
256
432
|
}
|
|
257
433
|
|
|
258
434
|
public async runWorkflowJob(runId: string, rpcService: any): Promise<void> {
|
|
259
|
-
// Get the run
|
|
260
435
|
const run = await this.getRun(runId)
|
|
261
436
|
if (!run) {
|
|
262
437
|
throw new WorkflowRunNotFound(runId)
|
|
263
438
|
}
|
|
264
439
|
|
|
265
|
-
|
|
266
|
-
const registrations = pikkuState('workflows', 'registrations')
|
|
440
|
+
const registrations = pikkuState(null, 'workflows', 'registrations')
|
|
267
441
|
const workflow = registrations.get(run.workflow)
|
|
268
442
|
if (!workflow) {
|
|
269
443
|
throw new WorkflowNotFoundError(run.workflow)
|
|
270
444
|
}
|
|
271
445
|
|
|
272
|
-
// Use lock to prevent concurrent execution
|
|
273
446
|
await this.withRunLock(runId, async () => {
|
|
274
|
-
|
|
275
|
-
const
|
|
447
|
+
const meta = pikkuState(null, 'workflows', 'meta')
|
|
448
|
+
const workflowMeta = meta[run.workflow]
|
|
449
|
+
|
|
450
|
+
const workflowWire = this.createWorkflowWire(
|
|
276
451
|
run.workflow,
|
|
277
452
|
runId,
|
|
278
453
|
rpcService
|
|
279
454
|
)
|
|
280
|
-
|
|
281
|
-
// Get function metadata
|
|
282
|
-
const meta = pikkuState('workflows', 'meta')
|
|
283
|
-
const workflowMeta = meta[run.workflow]
|
|
284
|
-
|
|
285
|
-
// Execute workflow function with workflow interaction
|
|
455
|
+
const wire: PikkuWire = { workflow: workflowWire }
|
|
286
456
|
try {
|
|
287
|
-
const getAllServices = () => {
|
|
288
|
-
let sessionServices = {}
|
|
289
|
-
const interaction = { workflow: workflowInteraction }
|
|
290
|
-
if (this.createSessionServices) {
|
|
291
|
-
sessionServices = this.createSessionServices(
|
|
292
|
-
this.singletonServices!,
|
|
293
|
-
interaction,
|
|
294
|
-
undefined
|
|
295
|
-
)
|
|
296
|
-
}
|
|
297
|
-
return {
|
|
298
|
-
...this.singletonServices,
|
|
299
|
-
...sessionServices,
|
|
300
|
-
...interaction,
|
|
301
|
-
} as CoreServices
|
|
302
|
-
}
|
|
303
457
|
const result = await runPikkuFunc(
|
|
304
|
-
|
|
305
|
-
workflowMeta.
|
|
458
|
+
'workflow',
|
|
459
|
+
workflowMeta.name,
|
|
306
460
|
workflowMeta.pikkuFuncName,
|
|
307
461
|
{
|
|
308
462
|
singletonServices: this.singletonServices!,
|
|
309
|
-
|
|
310
|
-
|
|
463
|
+
wire,
|
|
464
|
+
createWireServices: this.createWireServices,
|
|
311
465
|
data: () => run.input,
|
|
312
466
|
}
|
|
313
467
|
)
|
|
314
468
|
|
|
315
|
-
// Workflow completed successfully
|
|
316
469
|
await this.updateRunStatus(runId, 'completed', result)
|
|
317
470
|
} catch (error: any) {
|
|
318
|
-
// Check if it's a WorkflowAsyncException
|
|
319
471
|
if (error instanceof WorkflowAsyncException) {
|
|
320
472
|
// Normal - workflow paused for step execution
|
|
321
473
|
throw error
|
|
@@ -323,11 +475,15 @@ export abstract class PikkuWorkflowService implements WorkflowService {
|
|
|
323
475
|
|
|
324
476
|
// Check if it's a WorkflowCancelledException
|
|
325
477
|
if (error instanceof WorkflowCancelledException) {
|
|
326
|
-
// Workflow was cancelled - status
|
|
478
|
+
// Workflow was cancelled - update status and rethrow
|
|
479
|
+
await this.updateRunStatus(runId, 'cancelled', undefined, {
|
|
480
|
+
message: error.message || 'Workflow cancelled',
|
|
481
|
+
stack: '',
|
|
482
|
+
code: 'WORKFLOW_CANCELLED',
|
|
483
|
+
})
|
|
327
484
|
throw error
|
|
328
485
|
}
|
|
329
486
|
|
|
330
|
-
// Real error - mark as failed
|
|
331
487
|
await this.updateRunStatus(runId, 'failed', undefined, {
|
|
332
488
|
message: error.message,
|
|
333
489
|
stack: error.stack,
|
|
@@ -350,64 +506,87 @@ export abstract class PikkuWorkflowService implements WorkflowService {
|
|
|
350
506
|
data: any,
|
|
351
507
|
rpcService: any
|
|
352
508
|
): Promise<void> {
|
|
353
|
-
//
|
|
354
|
-
|
|
509
|
+
// Use step-level lock to prevent concurrent execution of same step
|
|
510
|
+
await this.withStepLock(runId, stepName, async () => {
|
|
511
|
+
// Get step state
|
|
512
|
+
let stepState = await this.getStepState(runId, stepName)
|
|
355
513
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
514
|
+
// Idempotency - if already succeeded, resume orchestrator and return
|
|
515
|
+
if (stepState.status === 'succeeded') {
|
|
516
|
+
await this.resumeWorkflow(runId)
|
|
517
|
+
return
|
|
518
|
+
}
|
|
361
519
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
520
|
+
// Log warning if already running (race condition)
|
|
521
|
+
if (stepState.status === 'running') {
|
|
522
|
+
return
|
|
523
|
+
}
|
|
366
524
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
525
|
+
// If status is 'failed', this is a retry - create new attempt history
|
|
526
|
+
if (stepState.status === 'failed') {
|
|
527
|
+
stepState = await this.createRetryAttempt(stepState.stepId, 'running')
|
|
528
|
+
}
|
|
371
529
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
530
|
+
if (stepState.status !== 'pending') {
|
|
531
|
+
// Mark step as running (pending or failed status)
|
|
532
|
+
await this.setStepRunning(stepState.stepId)
|
|
533
|
+
}
|
|
376
534
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
535
|
+
try {
|
|
536
|
+
let result: any
|
|
537
|
+
|
|
538
|
+
// Check if this is a graph node step (step name starts with 'node:')
|
|
539
|
+
if (stepName.startsWith('node:')) {
|
|
540
|
+
// Get the graph name from the workflow run
|
|
541
|
+
const run = await this.getRun(runId)
|
|
542
|
+
if (!run) {
|
|
543
|
+
throw new Error(`Workflow run not found: ${runId}`)
|
|
544
|
+
}
|
|
545
|
+
const graphName = run.workflow
|
|
386
546
|
|
|
387
|
-
|
|
388
|
-
|
|
547
|
+
// Execute as graph step with graph wire context
|
|
548
|
+
result = await executeGraphStep(
|
|
549
|
+
this,
|
|
550
|
+
rpcService,
|
|
551
|
+
runId,
|
|
552
|
+
stepState.stepId,
|
|
553
|
+
stepName,
|
|
554
|
+
rpcName,
|
|
555
|
+
data,
|
|
556
|
+
graphName
|
|
557
|
+
)
|
|
558
|
+
} else {
|
|
559
|
+
// Execute RPC with workflow step context (regular workflow)
|
|
560
|
+
result = await rpcService.rpcWithWire(rpcName, data, {
|
|
561
|
+
workflowStep: {
|
|
562
|
+
runId,
|
|
563
|
+
stepId: stepState.stepId,
|
|
564
|
+
attemptCount: stepState.attemptCount,
|
|
565
|
+
},
|
|
566
|
+
})
|
|
567
|
+
}
|
|
389
568
|
|
|
390
|
-
|
|
391
|
-
|
|
569
|
+
// Store result and mark succeeded
|
|
570
|
+
await this.setStepResult(stepState.stepId, result)
|
|
571
|
+
|
|
572
|
+
// Resume orchestrator to continue workflow
|
|
392
573
|
await this.resumeWorkflow(runId)
|
|
393
|
-
} catch (
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
} catch (error: any) {
|
|
397
|
-
// Store error and mark failed
|
|
398
|
-
await this.setStepError(stepState.stepId, error)
|
|
574
|
+
} catch (error: any) {
|
|
575
|
+
// Store error and mark failed
|
|
576
|
+
await this.setStepError(stepState.stepId, error)
|
|
399
577
|
|
|
400
|
-
|
|
401
|
-
|
|
578
|
+
const maxAttempts = (stepState.retries ?? 0) + 1
|
|
579
|
+
const retriesExhausted = stepState.attemptCount >= maxAttempts
|
|
402
580
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
581
|
+
if (retriesExhausted) {
|
|
582
|
+
// No more retries - resume orchestrator to mark workflow as failed
|
|
583
|
+
await this.resumeWorkflow(runId)
|
|
584
|
+
}
|
|
407
585
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
586
|
+
// Always throw so queue knows the job failed and can retry if needed
|
|
587
|
+
throw error
|
|
588
|
+
}
|
|
589
|
+
})
|
|
411
590
|
}
|
|
412
591
|
|
|
413
592
|
/**
|
|
@@ -461,7 +640,7 @@ export abstract class PikkuWorkflowService implements WorkflowService {
|
|
|
461
640
|
let stepState: StepState
|
|
462
641
|
try {
|
|
463
642
|
stepState = await this.getStepState(runId, stepName)
|
|
464
|
-
} catch
|
|
643
|
+
} catch {
|
|
465
644
|
// Step doesn't exist - create it
|
|
466
645
|
stepState = await this.insertStepState(
|
|
467
646
|
runId,
|
|
@@ -498,8 +677,8 @@ export abstract class PikkuWorkflowService implements WorkflowService {
|
|
|
498
677
|
// Step is pending - schedule it
|
|
499
678
|
await this.setStepScheduled(stepState.stepId)
|
|
500
679
|
|
|
501
|
-
// Enqueue step worker
|
|
502
|
-
if (this.singletonServices!.queueService) {
|
|
680
|
+
// Enqueue step worker (unless inline mode)
|
|
681
|
+
if (!this.isInline(runId) && this.singletonServices!.queueService) {
|
|
503
682
|
// Map step retry options to queue job options
|
|
504
683
|
const retries = stepOptions?.retries ?? 0
|
|
505
684
|
const retryDelay = stepOptions?.retryDelay
|
|
@@ -524,45 +703,52 @@ export abstract class PikkuWorkflowService implements WorkflowService {
|
|
|
524
703
|
: undefined,
|
|
525
704
|
}
|
|
526
705
|
)
|
|
706
|
+
// Pause workflow - step will callback when done
|
|
707
|
+
throw new WorkflowAsyncException(runId, stepName)
|
|
527
708
|
} else {
|
|
528
|
-
//
|
|
709
|
+
// Inline or no queue service - execute locally with retry loop
|
|
529
710
|
const retries = stepOptions?.retries ?? 0
|
|
530
711
|
const retryDelay = stepOptions?.retryDelay
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
//
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
712
|
+
let currentStepState = stepState
|
|
713
|
+
|
|
714
|
+
while (true) {
|
|
715
|
+
try {
|
|
716
|
+
await this.setStepRunning(currentStepState.stepId)
|
|
717
|
+
const result = await rpcService.rpcWithWire(rpcName, data, {
|
|
718
|
+
workflowStep: {
|
|
719
|
+
runId,
|
|
720
|
+
stepId: currentStepState.stepId,
|
|
721
|
+
attemptCount: currentStepState.attemptCount,
|
|
722
|
+
},
|
|
723
|
+
})
|
|
724
|
+
await this.setStepResult(currentStepState.stepId, result)
|
|
725
|
+
return result
|
|
726
|
+
} catch (error: any) {
|
|
727
|
+
// Record the error (marks step as failed)
|
|
728
|
+
await this.setStepError(currentStepState.stepId, error)
|
|
729
|
+
|
|
730
|
+
// Check if we should retry
|
|
731
|
+
if (currentStepState.attemptCount < retries) {
|
|
732
|
+
// Create a new pending retry attempt
|
|
733
|
+
currentStepState = await this.createRetryAttempt(
|
|
734
|
+
currentStepState.stepId,
|
|
735
|
+
'pending'
|
|
736
|
+
)
|
|
554
737
|
|
|
555
|
-
|
|
556
|
-
|
|
738
|
+
// Wait for retry delay if specified
|
|
739
|
+
if (retryDelay) {
|
|
740
|
+
await new Promise((resolve) =>
|
|
741
|
+
setTimeout(resolve, getDurationInMilliseconds(retryDelay))
|
|
742
|
+
)
|
|
743
|
+
}
|
|
744
|
+
// Continue loop to retry
|
|
745
|
+
} else {
|
|
746
|
+
// No more retries, fail the workflow
|
|
747
|
+
throw error
|
|
748
|
+
}
|
|
557
749
|
}
|
|
558
|
-
|
|
559
|
-
// No more retries, fail the workflow
|
|
560
|
-
throw error
|
|
561
750
|
}
|
|
562
751
|
}
|
|
563
|
-
|
|
564
|
-
// Pause workflow - step will callback when done
|
|
565
|
-
throw new WorkflowAsyncException(runId, stepName)
|
|
566
752
|
}
|
|
567
753
|
|
|
568
754
|
private async inlineStep(
|
|
@@ -575,7 +761,7 @@ export abstract class PikkuWorkflowService implements WorkflowService {
|
|
|
575
761
|
let stepState: StepState
|
|
576
762
|
try {
|
|
577
763
|
stepState = await this.getStepState(runId, stepName)
|
|
578
|
-
} catch
|
|
764
|
+
} catch {
|
|
579
765
|
// Step doesn't exist - create it (inline, no RPC)
|
|
580
766
|
stepState = await this.insertStepState(
|
|
581
767
|
runId,
|
|
@@ -594,30 +780,68 @@ export abstract class PikkuWorkflowService implements WorkflowService {
|
|
|
594
780
|
// Execute inline function
|
|
595
781
|
const retries = stepOptions?.retries ?? this.getConfig().retries
|
|
596
782
|
const retryDelay = stepOptions?.retryDelay ?? this.getConfig().retryDelay
|
|
597
|
-
|
|
783
|
+
let currentStepState = stepState
|
|
784
|
+
|
|
785
|
+
// Check if we're running inline (in-memory) or remote (queue-based)
|
|
786
|
+
if (this.isInline(runId)) {
|
|
787
|
+
// Inline mode - execute with retry loop
|
|
788
|
+
while (true) {
|
|
789
|
+
try {
|
|
790
|
+
await this.setStepRunning(currentStepState.stepId)
|
|
791
|
+
const result = await fn()
|
|
792
|
+
await this.setStepResult(currentStepState.stepId, result)
|
|
793
|
+
return result
|
|
794
|
+
} catch (error: any) {
|
|
795
|
+
// Record the error (marks step as failed)
|
|
796
|
+
await this.setStepError(currentStepState.stepId, error)
|
|
797
|
+
|
|
798
|
+
// Check if we should retry
|
|
799
|
+
if (currentStepState.attemptCount < retries) {
|
|
800
|
+
// Create a new pending retry attempt
|
|
801
|
+
currentStepState = await this.createRetryAttempt(
|
|
802
|
+
currentStepState.stepId,
|
|
803
|
+
'pending'
|
|
804
|
+
)
|
|
598
805
|
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
806
|
+
// Wait for retry delay if specified
|
|
807
|
+
if (retryDelay) {
|
|
808
|
+
await new Promise((resolve) =>
|
|
809
|
+
setTimeout(resolve, getDurationInMilliseconds(retryDelay))
|
|
810
|
+
)
|
|
811
|
+
}
|
|
812
|
+
// Continue loop to retry
|
|
813
|
+
} else {
|
|
814
|
+
// No more retries, fail the workflow
|
|
815
|
+
throw error
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
} else {
|
|
820
|
+
// Remote mode - use queue-based retry
|
|
821
|
+
try {
|
|
822
|
+
await this.setStepRunning(currentStepState.stepId)
|
|
823
|
+
const result = await fn()
|
|
824
|
+
await this.setStepResult(currentStepState.stepId, result)
|
|
825
|
+
return result
|
|
826
|
+
} catch (error: any) {
|
|
827
|
+
// Record the error (marks step as failed)
|
|
828
|
+
await this.setStepError(currentStepState.stepId, error)
|
|
606
829
|
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
830
|
+
// Check if we should retry
|
|
831
|
+
if (currentStepState.attemptCount < retries) {
|
|
832
|
+
// Create a new pending retry attempt (copies metadata from failed step)
|
|
833
|
+
await this.createRetryAttempt(currentStepState.stepId, 'pending')
|
|
611
834
|
|
|
612
|
-
|
|
613
|
-
|
|
835
|
+
// Schedule orchestrator to retry after delay
|
|
836
|
+
await this.scheduleOrchestratorRetry(runId, retryDelay)
|
|
614
837
|
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
838
|
+
// Pause workflow - orchestrator will replay and pick up new attempt
|
|
839
|
+
throw new WorkflowAsyncException(runId, stepName)
|
|
840
|
+
}
|
|
618
841
|
|
|
619
|
-
|
|
620
|
-
|
|
842
|
+
// No more retries, fail the workflow
|
|
843
|
+
throw error
|
|
844
|
+
}
|
|
621
845
|
}
|
|
622
846
|
}
|
|
623
847
|
|
|
@@ -626,7 +850,7 @@ export abstract class PikkuWorkflowService implements WorkflowService {
|
|
|
626
850
|
let stepState: StepState
|
|
627
851
|
try {
|
|
628
852
|
stepState = await this.getStepState(runId, stepName)
|
|
629
|
-
} catch
|
|
853
|
+
} catch {
|
|
630
854
|
// Step doesn't exist - create it (sleep step, no RPC)
|
|
631
855
|
stepState = await this.insertStepState(
|
|
632
856
|
runId,
|
|
@@ -650,9 +874,9 @@ export abstract class PikkuWorkflowService implements WorkflowService {
|
|
|
650
874
|
// Step is pending - schedule it
|
|
651
875
|
await this.setStepScheduled(stepState.stepId)
|
|
652
876
|
|
|
653
|
-
// Check if
|
|
654
|
-
if (this.singletonServices!.schedulerService) {
|
|
655
|
-
// Remote mode -
|
|
877
|
+
// Check if inline mode or no scheduler service
|
|
878
|
+
if (!this.isInline(runId) && this.singletonServices!.schedulerService) {
|
|
879
|
+
// Remote mode - schedule sleep via scheduler service
|
|
656
880
|
await this.singletonServices!.schedulerService.scheduleRPC(
|
|
657
881
|
duration,
|
|
658
882
|
this.getConfig().sleeperRPCName,
|
|
@@ -661,6 +885,8 @@ export abstract class PikkuWorkflowService implements WorkflowService {
|
|
|
661
885
|
stepId: stepState.stepId,
|
|
662
886
|
}
|
|
663
887
|
)
|
|
888
|
+
// Pause workflow - sleep will callback when done
|
|
889
|
+
throw new WorkflowAsyncException(runId, stepName)
|
|
664
890
|
} else {
|
|
665
891
|
// Inline mode - use setTimeout with actual duration
|
|
666
892
|
await new Promise((resolve) =>
|
|
@@ -669,29 +895,14 @@ export abstract class PikkuWorkflowService implements WorkflowService {
|
|
|
669
895
|
await this.setStepResult(stepState.stepId, null)
|
|
670
896
|
return
|
|
671
897
|
}
|
|
672
|
-
|
|
673
|
-
// Pause workflow - sleep will callback when done
|
|
674
|
-
throw new WorkflowAsyncException(runId, stepName)
|
|
675
898
|
}
|
|
676
899
|
|
|
677
|
-
private
|
|
678
|
-
// Update workflow run status to cancelled
|
|
679
|
-
await this.updateRunStatus(runId, 'cancelled', undefined, {
|
|
680
|
-
message: reason || 'Workflow cancelled by user',
|
|
681
|
-
stack: '',
|
|
682
|
-
code: 'WORKFLOW_CANCELLED',
|
|
683
|
-
})
|
|
684
|
-
|
|
685
|
-
// Throw cancellation exception to stop workflow execution
|
|
686
|
-
throw new WorkflowCancelledException(runId, reason)
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
private createWorkflowInteraction(
|
|
900
|
+
private createWorkflowWire(
|
|
690
901
|
workflowName: string,
|
|
691
902
|
runId: string,
|
|
692
903
|
rpcService: any
|
|
693
|
-
):
|
|
694
|
-
const
|
|
904
|
+
): PikkuWorkflowWire {
|
|
905
|
+
const workflowWire: PikkuWorkflowWire = {
|
|
695
906
|
workflowName,
|
|
696
907
|
runId,
|
|
697
908
|
getRun: async () => (await this.getRun(runId)) as WorkflowRun,
|
|
@@ -732,13 +943,8 @@ export abstract class PikkuWorkflowService implements WorkflowService {
|
|
|
732
943
|
getDurationInMilliseconds(duration)
|
|
733
944
|
)
|
|
734
945
|
},
|
|
735
|
-
|
|
736
|
-
// Implement workflow.cancel()
|
|
737
|
-
cancel: async (reason?: string): Promise<void> => {
|
|
738
|
-
await this.cancelWorkflow(runId, reason)
|
|
739
|
-
},
|
|
740
946
|
}
|
|
741
|
-
return
|
|
947
|
+
return workflowWire
|
|
742
948
|
}
|
|
743
949
|
|
|
744
950
|
private verifyStepName(stepName: string) {
|