@pikku/core 0.12.39 → 0.12.41
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 +29 -0
- package/dist/function/function-runner.d.ts +2 -2
- package/dist/function/functions.types.d.ts +6 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/services/credential-wire-service.d.ts +2 -2
- package/dist/services/in-memory-workflow-service.d.ts +1 -0
- package/dist/services/in-memory-workflow-service.js +3 -0
- package/dist/services/pikku-user-id.d.ts +2 -2
- package/dist/services/workflow-service.d.ts +1 -0
- package/dist/types/core.types.d.ts +24 -7
- package/dist/utils.d.ts +3 -1
- package/dist/utils.js +2 -0
- package/dist/wirings/channel/channel-middleware-runner.d.ts +2 -2
- package/dist/wirings/channel/local/local-eventhub-service.js +7 -4
- package/dist/wirings/rpc/rpc-runner.d.ts +4 -4
- package/dist/wirings/rpc/rpc-runner.js +0 -16
- package/dist/wirings/workflow/pikku-workflow-service.d.ts +5 -2
- package/dist/wirings/workflow/pikku-workflow-service.js +17 -17
- package/package.json +1 -1
- package/src/function/function-runner.ts +3 -2
- package/src/function/functions.types.ts +6 -2
- package/src/index.ts +7 -1
- package/src/services/credential-wire-service.ts +2 -2
- package/src/services/in-memory-workflow-service.test.ts +2 -2
- package/src/services/in-memory-workflow-service.ts +7 -1
- package/src/services/pikku-user-id.ts +2 -2
- package/src/services/workflow-service.ts +1 -0
- package/src/types/core.types.ts +28 -8
- package/src/utils.ts +12 -1
- package/src/wirings/ai-agent/ai-agent-prepare.ts +2 -2
- package/src/wirings/channel/channel-common.ts +8 -2
- package/src/wirings/channel/channel-middleware-runner.ts +3 -3
- package/src/wirings/channel/local/local-channel-runner.ts +7 -3
- package/src/wirings/channel/local/local-eventhub-service.ts +6 -3
- package/src/wirings/channel/serverless/serverless-channel-runner.ts +4 -4
- package/src/wirings/cli/cli-runner.ts +2 -2
- package/src/wirings/gateway/gateway-runner.ts +8 -2
- package/src/wirings/http/http-runner.ts +3 -2
- package/src/wirings/mcp/mcp-runner.ts +2 -2
- package/src/wirings/queue/queue-runner.ts +2 -2
- package/src/wirings/rpc/rpc-runner.ts +12 -24
- package/src/wirings/scheduler/scheduler-runner.ts +2 -2
- package/src/wirings/trigger/trigger-runner.ts +2 -2
- package/src/wirings/workflow/pikku-workflow-service.test.ts +16 -26
- package/src/wirings/workflow/pikku-workflow-service.ts +36 -24
- package/src/wirings/workflow/workflow-dispatch-durability.test.ts +3 -3
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -144,7 +144,10 @@ export class WorkflowDispatchException extends Error {
|
|
|
144
144
|
public readonly stepName: string,
|
|
145
145
|
options?: { cause?: unknown }
|
|
146
146
|
) {
|
|
147
|
-
super(
|
|
147
|
+
super(
|
|
148
|
+
`Failed to dispatch workflow step '${stepName}' (run ${runId})`,
|
|
149
|
+
options
|
|
150
|
+
)
|
|
148
151
|
this.name = 'WorkflowDispatchException'
|
|
149
152
|
}
|
|
150
153
|
}
|
|
@@ -184,6 +187,16 @@ addError(WorkflowRunFailedError, {
|
|
|
184
187
|
message: 'Workflow run failed.',
|
|
185
188
|
})
|
|
186
189
|
|
|
190
|
+
export class WorkflowRunCancelledError extends PikkuError {
|
|
191
|
+
constructor() {
|
|
192
|
+
super('Workflow was cancelled')
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
addError(WorkflowRunCancelledError, {
|
|
196
|
+
status: 409,
|
|
197
|
+
message: 'Workflow was cancelled.',
|
|
198
|
+
})
|
|
199
|
+
|
|
187
200
|
export class WorkflowServiceNotInitialized extends Error {}
|
|
188
201
|
export class WorkflowStepNameNotString extends Error {
|
|
189
202
|
constructor(stepName: any) {
|
|
@@ -237,16 +250,13 @@ export abstract class PikkuWorkflowService implements WorkflowService {
|
|
|
237
250
|
}
|
|
238
251
|
}
|
|
239
252
|
|
|
240
|
-
public rewireQueueWorkers(): void {
|
|
241
|
-
this.wireQueueWorkers()
|
|
242
|
-
}
|
|
243
|
-
|
|
244
253
|
/**
|
|
245
254
|
* Wire the queue-based orchestrator/step/sleeper workers.
|
|
246
255
|
* Subclasses that orchestrate without queues (e.g. Durable Objects) should
|
|
247
256
|
* pass `wireQueues: false` to the base constructor and skip this entirely.
|
|
257
|
+
* Call this explicitly after adding addons dynamically.
|
|
248
258
|
*/
|
|
249
|
-
|
|
259
|
+
public wireQueueWorkers(): void {
|
|
250
260
|
const functions = pikkuState(null, 'function', 'functions')
|
|
251
261
|
const functionsMeta = pikkuState(null, 'function', 'meta')
|
|
252
262
|
|
|
@@ -426,7 +436,12 @@ export abstract class PikkuWorkflowService implements WorkflowService {
|
|
|
426
436
|
// Build step summaries from history (latest attempt per step)
|
|
427
437
|
const stepMap = new Map<
|
|
428
438
|
string,
|
|
429
|
-
{
|
|
439
|
+
{
|
|
440
|
+
status: StepStatus
|
|
441
|
+
startedAt?: Date
|
|
442
|
+
completedAt?: Date
|
|
443
|
+
attempts: number
|
|
444
|
+
}
|
|
430
445
|
>()
|
|
431
446
|
for (const step of history) {
|
|
432
447
|
const existing = stepMap.get(step.stepName)
|
|
@@ -920,7 +935,9 @@ export abstract class PikkuWorkflowService implements WorkflowService {
|
|
|
920
935
|
const queueService = this.verifyQueueService()
|
|
921
936
|
await queueService.add(
|
|
922
937
|
this.getStepWorkerQueueName(rpcName),
|
|
923
|
-
JSON.parse(
|
|
938
|
+
JSON.parse(
|
|
939
|
+
JSON.stringify({ runId, stepName, rpcName, data, fromStepName })
|
|
940
|
+
),
|
|
924
941
|
this.resolveStepJobOptions(stepOptions)
|
|
925
942
|
)
|
|
926
943
|
}
|
|
@@ -982,29 +999,22 @@ export abstract class PikkuWorkflowService implements WorkflowService {
|
|
|
982
999
|
stepOptions?: WorkflowStepOptions,
|
|
983
1000
|
fromStepName?: string
|
|
984
1001
|
): Promise<boolean> {
|
|
985
|
-
// Step execution is decided purely by the function's `
|
|
986
|
-
//
|
|
987
|
-
// the queue.
|
|
988
|
-
//
|
|
989
|
-
// normally-started workflow executes its steps in one orchestrator-worker
|
|
990
|
-
// pass instead of one queue round-trip per step.
|
|
1002
|
+
// Step execution is decided purely by the function's `workflowQueued` flag
|
|
1003
|
+
// (default false). Only a function explicitly marked `workflowQueued: true`
|
|
1004
|
+
// dispatches via the queue. If the queue service is not configured that is
|
|
1005
|
+
// a hard error — there is no inline fallback.
|
|
991
1006
|
const functionsMeta = pikkuState(null, 'function', 'meta')
|
|
992
1007
|
const rpcFuncId = pikkuState(null, 'rpc', 'meta')[rpcName]
|
|
993
1008
|
const rpcMeta =
|
|
994
1009
|
typeof rpcFuncId === 'string' ? functionsMeta[rpcFuncId] : undefined
|
|
995
|
-
const forceQueue = rpcMeta?.
|
|
1010
|
+
const forceQueue = rpcMeta?.workflowQueued === true
|
|
996
1011
|
if (!forceQueue) {
|
|
997
1012
|
return false
|
|
998
1013
|
}
|
|
999
|
-
// The function opted out of inline execution (`inline: false`) but no queue
|
|
1000
|
-
// service is configured to dispatch it. Fall back to inline so the workflow
|
|
1001
|
-
// still progresses, but warn loudly — silently swallowing this hides a real
|
|
1002
|
-
// misconfiguration (the step won't get its own worker/retry isolation).
|
|
1003
1014
|
if (!getSingletonServices()?.queueService) {
|
|
1004
|
-
|
|
1005
|
-
`Workflow step '${stepName}' (function '${rpcName}') is marked '
|
|
1015
|
+
throw new Error(
|
|
1016
|
+
`Workflow step '${stepName}' (function '${rpcName}') is marked 'workflowQueued: true' but no queue service is configured.`
|
|
1006
1017
|
)
|
|
1007
|
-
return false
|
|
1008
1018
|
}
|
|
1009
1019
|
try {
|
|
1010
1020
|
await getSingletonServices()!.queueService!.add(
|
|
@@ -1192,7 +1202,7 @@ export abstract class PikkuWorkflowService implements WorkflowService {
|
|
|
1192
1202
|
throw new WorkflowRunFailedError(run.error?.message)
|
|
1193
1203
|
}
|
|
1194
1204
|
if (run.status === 'cancelled') {
|
|
1195
|
-
throw new
|
|
1205
|
+
throw new WorkflowRunCancelledError()
|
|
1196
1206
|
}
|
|
1197
1207
|
return run.output
|
|
1198
1208
|
}
|
|
@@ -1844,7 +1854,9 @@ export abstract class PikkuWorkflowService implements WorkflowService {
|
|
|
1844
1854
|
}
|
|
1845
1855
|
if (WORKFLOW_END_STATES.has(childRun.status)) {
|
|
1846
1856
|
if (childRun.status === 'failed') {
|
|
1847
|
-
throw new Error(
|
|
1857
|
+
throw new Error(
|
|
1858
|
+
childRun.error?.message || 'Sub-workflow failed'
|
|
1859
|
+
)
|
|
1848
1860
|
}
|
|
1849
1861
|
if (childRun.status === 'cancelled') {
|
|
1850
1862
|
throw new Error('Sub-workflow was cancelled')
|
|
@@ -5,13 +5,13 @@ import { InMemoryWorkflowService } from '../../services/in-memory-workflow-servi
|
|
|
5
5
|
import { pikkuState } from '../../pikku-state.js'
|
|
6
6
|
import { WorkflowDispatchException } from './pikku-workflow-service.js'
|
|
7
7
|
|
|
8
|
-
// Register
|
|
9
|
-
// through the queue (dispatchStep) instead of running it inline.
|
|
8
|
+
// Register a `workflowQueued: true` function so the workflow's `do()` routes
|
|
9
|
+
// the step through the queue (dispatchStep) instead of running it inline.
|
|
10
10
|
function registerDispatchedFn(rpcName: string): void {
|
|
11
11
|
const funcId = `fn:${rpcName}`
|
|
12
12
|
pikkuState(null, 'rpc', 'meta', { [rpcName]: funcId } as any)
|
|
13
13
|
pikkuState(null, 'function', 'meta', {
|
|
14
|
-
[funcId]: {
|
|
14
|
+
[funcId]: { workflowQueued: true },
|
|
15
15
|
} as any)
|
|
16
16
|
}
|
|
17
17
|
|