@pikku/kysely 0.12.11 → 0.12.13
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 +20 -0
- package/dist/src/create-audited-kysely.d.ts +10 -0
- package/dist/src/create-audited-kysely.js +167 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +2 -0
- package/dist/src/kysely-ai-agent-run-service.d.ts +1 -0
- package/dist/src/kysely-ai-agent-run-service.js +4 -1
- package/dist/src/kysely-channel-store.d.ts +3 -0
- package/dist/src/kysely-channel-store.js +25 -0
- package/dist/src/kysely-secret-service.d.ts +2 -3
- package/dist/src/kysely-secret-service.js +2 -7
- package/dist/src/kysely-tables.d.ts +2 -0
- package/dist/src/kysely-workflow-mirror.d.ts +60 -0
- package/dist/src/kysely-workflow-mirror.js +329 -0
- package/dist/src/kysely-workflow-service.d.ts +13 -13
- package/dist/src/kysely-workflow-service.js +13 -13
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/src/create-audited-kysely.test.ts +560 -0
- package/src/create-audited-kysely.ts +254 -0
- package/src/index.ts +5 -0
- package/src/kysely-ai-agent-run-service.ts +6 -1
- package/src/kysely-ai-run-state-service.ts +6 -2
- package/src/kysely-channel-store.ts +27 -0
- package/src/kysely-secret-service.ts +4 -17
- package/src/kysely-services.test.ts +2 -2
- package/src/kysely-session-store.ts +1 -3
- package/src/kysely-tables.ts +2 -0
- package/src/kysely-workflow-mirror.test.ts +246 -0
- package/src/kysely-workflow-mirror.ts +438 -0
- package/src/kysely-workflow-service.ts +25 -13
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
import type { SerializedError } from '@pikku/core'
|
|
2
|
+
import type {
|
|
3
|
+
StepState,
|
|
4
|
+
WorkflowRunMirror,
|
|
5
|
+
WorkflowRunWire,
|
|
6
|
+
WorkflowStatus,
|
|
7
|
+
WorkflowPlannedStep,
|
|
8
|
+
WorkflowVersionStatus,
|
|
9
|
+
} from '@pikku/core/workflow'
|
|
10
|
+
import type { Kysely } from 'kysely'
|
|
11
|
+
import { sql } from 'kysely'
|
|
12
|
+
import type { KyselyPikkuDB } from './kysely-tables.js'
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Kysely-backed `WorkflowRunMirror`.
|
|
16
|
+
*
|
|
17
|
+
* Forwards executor writes to the same `workflow_runs` / `workflow_step` /
|
|
18
|
+
* `workflow_step_history` / `workflow_versions` tables that
|
|
19
|
+
* `KyselyWorkflowService` uses, so a `KyselyWorkflowRunService` reading
|
|
20
|
+
* those tables will see runs driven by any executor (Cloudflare Durable
|
|
21
|
+
* Object, Redis, MongoDB, in-memory) — not just kysely-driven runs.
|
|
22
|
+
*
|
|
23
|
+
* Errors thrown here are caught by the executor's `safeMirror` wrapper
|
|
24
|
+
* and logged, so a mirror outage cannot break a running workflow.
|
|
25
|
+
*/
|
|
26
|
+
export class KyselyWorkflowMirror implements WorkflowRunMirror {
|
|
27
|
+
private initialized = false
|
|
28
|
+
|
|
29
|
+
constructor(protected db: Kysely<KyselyPikkuDB>) {}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Create the underlying tables if they don't exist. Safe to call from
|
|
33
|
+
* either the mirror or `KyselyWorkflowService.init()` — schema is the
|
|
34
|
+
* same and uses `ifNotExists`.
|
|
35
|
+
*/
|
|
36
|
+
public async init(): Promise<void> {
|
|
37
|
+
if (this.initialized) return
|
|
38
|
+
|
|
39
|
+
await this.db.schema
|
|
40
|
+
.createTable('workflow_runs')
|
|
41
|
+
.ifNotExists()
|
|
42
|
+
.addColumn('workflow_run_id', 'text', (col) => col.primaryKey())
|
|
43
|
+
.addColumn('workflow', 'text', (col) => col.notNull())
|
|
44
|
+
.addColumn('status', 'text', (col) => col.notNull())
|
|
45
|
+
.addColumn('input', 'text', (col) => col.notNull())
|
|
46
|
+
.addColumn('output', 'text')
|
|
47
|
+
.addColumn('error', 'text')
|
|
48
|
+
.addColumn('state', 'text', (col) => col.defaultTo('{}'))
|
|
49
|
+
.addColumn('inline', 'boolean', (col) => col.defaultTo(false))
|
|
50
|
+
.addColumn('graph_hash', 'text')
|
|
51
|
+
.addColumn('deterministic', 'boolean', (col) => col.defaultTo(false))
|
|
52
|
+
.addColumn('planned_steps', 'text')
|
|
53
|
+
.addColumn('wire', 'text')
|
|
54
|
+
.addColumn('created_at', 'timestamp', (col) =>
|
|
55
|
+
col.defaultTo(sql`CURRENT_TIMESTAMP`).notNull()
|
|
56
|
+
)
|
|
57
|
+
.addColumn('updated_at', 'timestamp', (col) =>
|
|
58
|
+
col.defaultTo(sql`CURRENT_TIMESTAMP`).notNull()
|
|
59
|
+
)
|
|
60
|
+
.execute()
|
|
61
|
+
|
|
62
|
+
await this.db.schema
|
|
63
|
+
.createTable('workflow_step')
|
|
64
|
+
.ifNotExists()
|
|
65
|
+
.addColumn('workflow_step_id', 'text', (col) => col.primaryKey())
|
|
66
|
+
.addColumn('workflow_run_id', 'text', (col) =>
|
|
67
|
+
col
|
|
68
|
+
.notNull()
|
|
69
|
+
.references('workflow_runs.workflow_run_id')
|
|
70
|
+
.onDelete('cascade')
|
|
71
|
+
)
|
|
72
|
+
.addColumn('step_name', 'text', (col) => col.notNull())
|
|
73
|
+
.addColumn('rpc_name', 'text')
|
|
74
|
+
.addColumn('data', 'text')
|
|
75
|
+
.addColumn('status', 'text', (col) => col.notNull().defaultTo('pending'))
|
|
76
|
+
.addColumn('result', 'text')
|
|
77
|
+
.addColumn('error', 'text')
|
|
78
|
+
.addColumn('child_run_id', 'text')
|
|
79
|
+
.addColumn('branch_taken', 'text')
|
|
80
|
+
.addColumn('retries', 'integer')
|
|
81
|
+
.addColumn('retry_delay', 'text')
|
|
82
|
+
.addColumn('created_at', 'timestamp', (col) =>
|
|
83
|
+
col.defaultTo(sql`CURRENT_TIMESTAMP`).notNull()
|
|
84
|
+
)
|
|
85
|
+
.addColumn('updated_at', 'timestamp', (col) =>
|
|
86
|
+
col.defaultTo(sql`CURRENT_TIMESTAMP`).notNull()
|
|
87
|
+
)
|
|
88
|
+
.addUniqueConstraint('workflow_step_run_name_unique', [
|
|
89
|
+
'workflow_run_id',
|
|
90
|
+
'step_name',
|
|
91
|
+
])
|
|
92
|
+
.execute()
|
|
93
|
+
|
|
94
|
+
await this.db.schema
|
|
95
|
+
.createTable('workflow_step_history')
|
|
96
|
+
.ifNotExists()
|
|
97
|
+
.addColumn('history_id', 'text', (col) => col.primaryKey())
|
|
98
|
+
.addColumn('workflow_step_id', 'text', (col) =>
|
|
99
|
+
col
|
|
100
|
+
.notNull()
|
|
101
|
+
.references('workflow_step.workflow_step_id')
|
|
102
|
+
.onDelete('cascade')
|
|
103
|
+
)
|
|
104
|
+
.addColumn('status', 'text', (col) => col.notNull())
|
|
105
|
+
.addColumn('result', 'text')
|
|
106
|
+
.addColumn('error', 'text')
|
|
107
|
+
.addColumn('created_at', 'timestamp', (col) =>
|
|
108
|
+
col.defaultTo(sql`CURRENT_TIMESTAMP`).notNull()
|
|
109
|
+
)
|
|
110
|
+
.addColumn('running_at', 'timestamp')
|
|
111
|
+
.addColumn('scheduled_at', 'timestamp')
|
|
112
|
+
.addColumn('succeeded_at', 'timestamp')
|
|
113
|
+
.addColumn('failed_at', 'timestamp')
|
|
114
|
+
.execute()
|
|
115
|
+
|
|
116
|
+
await this.db.schema
|
|
117
|
+
.createTable('workflow_versions')
|
|
118
|
+
.ifNotExists()
|
|
119
|
+
.addColumn('workflow_name', 'text', (col) => col.notNull())
|
|
120
|
+
.addColumn('graph_hash', 'text', (col) => col.notNull())
|
|
121
|
+
.addColumn('graph', 'text', (col) => col.notNull())
|
|
122
|
+
.addColumn('source', 'text', (col) => col.notNull())
|
|
123
|
+
.addColumn('status', 'text', (col) => col.notNull().defaultTo('active'))
|
|
124
|
+
.addColumn('created_at', 'timestamp', (col) =>
|
|
125
|
+
col.defaultTo(sql`CURRENT_TIMESTAMP`).notNull()
|
|
126
|
+
)
|
|
127
|
+
.addPrimaryKeyConstraint('workflow_versions_pk', [
|
|
128
|
+
'workflow_name',
|
|
129
|
+
'graph_hash',
|
|
130
|
+
])
|
|
131
|
+
.execute()
|
|
132
|
+
|
|
133
|
+
this.initialized = true
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
async createRun(
|
|
137
|
+
runId: string,
|
|
138
|
+
workflowName: string,
|
|
139
|
+
input: any,
|
|
140
|
+
inline: boolean,
|
|
141
|
+
graphHash: string,
|
|
142
|
+
wire: WorkflowRunWire,
|
|
143
|
+
options?: {
|
|
144
|
+
deterministic?: boolean
|
|
145
|
+
plannedSteps?: WorkflowPlannedStep[]
|
|
146
|
+
}
|
|
147
|
+
): Promise<void> {
|
|
148
|
+
await this.db
|
|
149
|
+
.insertInto('workflowRuns')
|
|
150
|
+
.values({
|
|
151
|
+
workflowRunId: runId,
|
|
152
|
+
workflow: workflowName,
|
|
153
|
+
status: 'running',
|
|
154
|
+
input: JSON.stringify(input),
|
|
155
|
+
inline,
|
|
156
|
+
graphHash: graphHash ?? null,
|
|
157
|
+
deterministic: options?.deterministic ?? false,
|
|
158
|
+
plannedSteps: options?.plannedSteps
|
|
159
|
+
? JSON.stringify(options.plannedSteps)
|
|
160
|
+
: null,
|
|
161
|
+
wire: wire ? JSON.stringify(wire) : null,
|
|
162
|
+
})
|
|
163
|
+
.execute()
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
async updateRunStatus(
|
|
167
|
+
id: string,
|
|
168
|
+
status: WorkflowStatus,
|
|
169
|
+
output?: any,
|
|
170
|
+
error?: SerializedError
|
|
171
|
+
): Promise<void> {
|
|
172
|
+
await this.db
|
|
173
|
+
.updateTable('workflowRuns')
|
|
174
|
+
.set({
|
|
175
|
+
status,
|
|
176
|
+
output: output !== undefined ? JSON.stringify(output) : null,
|
|
177
|
+
error: error !== undefined ? JSON.stringify(error) : null,
|
|
178
|
+
updatedAt: new Date(),
|
|
179
|
+
})
|
|
180
|
+
.where('workflowRunId', '=', id)
|
|
181
|
+
.execute()
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
async insertStepState(
|
|
185
|
+
runId: string,
|
|
186
|
+
step: StepState & {
|
|
187
|
+
stepName: string
|
|
188
|
+
rpcName: string | null
|
|
189
|
+
data: any
|
|
190
|
+
}
|
|
191
|
+
): Promise<void> {
|
|
192
|
+
const now = step.createdAt ?? new Date()
|
|
193
|
+
|
|
194
|
+
await this.db
|
|
195
|
+
.insertInto('workflowStep')
|
|
196
|
+
.values({
|
|
197
|
+
workflowStepId: step.stepId,
|
|
198
|
+
workflowRunId: runId,
|
|
199
|
+
stepName: step.stepName,
|
|
200
|
+
rpcName: step.rpcName,
|
|
201
|
+
data: step.data != null ? JSON.stringify(step.data) : null,
|
|
202
|
+
status: step.status,
|
|
203
|
+
retries: step.retries ?? null,
|
|
204
|
+
retryDelay: step.retryDelay?.toString() ?? null,
|
|
205
|
+
createdAt: now,
|
|
206
|
+
updatedAt: now,
|
|
207
|
+
})
|
|
208
|
+
.execute()
|
|
209
|
+
|
|
210
|
+
await this.insertHistoryRecord(step.stepId, step.status)
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
async setStepRunning(stepId: string): Promise<void> {
|
|
214
|
+
await this.updateStepStatus(stepId, 'running')
|
|
215
|
+
await this.appendOrUpdateLatestHistory(stepId, 'running')
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
async setStepScheduled(stepId: string): Promise<void> {
|
|
219
|
+
await this.updateStepStatus(stepId, 'scheduled')
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
async setStepResult(stepId: string, result: any): Promise<void> {
|
|
223
|
+
const resultJson = JSON.stringify(result)
|
|
224
|
+
await this.db
|
|
225
|
+
.updateTable('workflowStep')
|
|
226
|
+
.set({
|
|
227
|
+
status: 'succeeded',
|
|
228
|
+
result: resultJson,
|
|
229
|
+
error: null,
|
|
230
|
+
updatedAt: new Date(),
|
|
231
|
+
})
|
|
232
|
+
.where('workflowStepId', '=', stepId)
|
|
233
|
+
.execute()
|
|
234
|
+
await this.appendOrUpdateLatestHistory(stepId, 'succeeded', resultJson)
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
async setStepChildRunId(stepId: string, childRunId: string): Promise<void> {
|
|
238
|
+
await this.db
|
|
239
|
+
.updateTable('workflowStep')
|
|
240
|
+
.set({ childRunId, updatedAt: new Date() })
|
|
241
|
+
.where('workflowStepId', '=', stepId)
|
|
242
|
+
.execute()
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
async setStepError(stepId: string, error: SerializedError): Promise<void> {
|
|
246
|
+
const errorJson = JSON.stringify(error)
|
|
247
|
+
await this.db
|
|
248
|
+
.updateTable('workflowStep')
|
|
249
|
+
.set({
|
|
250
|
+
status: 'failed',
|
|
251
|
+
error: errorJson,
|
|
252
|
+
result: null,
|
|
253
|
+
updatedAt: new Date(),
|
|
254
|
+
})
|
|
255
|
+
.where('workflowStepId', '=', stepId)
|
|
256
|
+
.execute()
|
|
257
|
+
await this.appendOrUpdateLatestHistory(
|
|
258
|
+
stepId,
|
|
259
|
+
'failed',
|
|
260
|
+
undefined,
|
|
261
|
+
errorJson
|
|
262
|
+
)
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
async createRetryAttempt(
|
|
266
|
+
failedStepId: string,
|
|
267
|
+
newStep: StepState & { stepName: string }
|
|
268
|
+
): Promise<void> {
|
|
269
|
+
await this.db
|
|
270
|
+
.updateTable('workflowStep')
|
|
271
|
+
.set({
|
|
272
|
+
status: newStep.status,
|
|
273
|
+
result: null,
|
|
274
|
+
error: null,
|
|
275
|
+
updatedAt: new Date(),
|
|
276
|
+
})
|
|
277
|
+
.where('workflowStepId', '=', failedStepId)
|
|
278
|
+
.execute()
|
|
279
|
+
await this.insertHistoryRecord(failedStepId, newStep.status)
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
async setBranchTaken(stepId: string, branchKey: string): Promise<void> {
|
|
283
|
+
await this.db
|
|
284
|
+
.updateTable('workflowStep')
|
|
285
|
+
.set({ branchTaken: branchKey, updatedAt: new Date() })
|
|
286
|
+
.where('workflowStepId', '=', stepId)
|
|
287
|
+
.execute()
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
async updateRunState(
|
|
291
|
+
runId: string,
|
|
292
|
+
name: string,
|
|
293
|
+
value: unknown
|
|
294
|
+
): Promise<void> {
|
|
295
|
+
const row = await this.db
|
|
296
|
+
.selectFrom('workflowRuns')
|
|
297
|
+
.select('state')
|
|
298
|
+
.where('workflowRunId', '=', runId)
|
|
299
|
+
.executeTakeFirst()
|
|
300
|
+
|
|
301
|
+
const state: Record<string, unknown> =
|
|
302
|
+
row?.state != null
|
|
303
|
+
? typeof row.state === 'string'
|
|
304
|
+
? JSON.parse(row.state)
|
|
305
|
+
: row.state
|
|
306
|
+
: {}
|
|
307
|
+
state[name] = value
|
|
308
|
+
|
|
309
|
+
await this.db
|
|
310
|
+
.updateTable('workflowRuns')
|
|
311
|
+
.set({ state: JSON.stringify(state), updatedAt: new Date() })
|
|
312
|
+
.where('workflowRunId', '=', runId)
|
|
313
|
+
.execute()
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
async upsertWorkflowVersion(
|
|
317
|
+
name: string,
|
|
318
|
+
graphHash: string,
|
|
319
|
+
graph: any,
|
|
320
|
+
source: string,
|
|
321
|
+
status: WorkflowVersionStatus = 'active'
|
|
322
|
+
): Promise<void> {
|
|
323
|
+
await this.db
|
|
324
|
+
.insertInto('workflowVersions')
|
|
325
|
+
.values({
|
|
326
|
+
workflowName: name,
|
|
327
|
+
graphHash,
|
|
328
|
+
graph: JSON.stringify(graph),
|
|
329
|
+
source,
|
|
330
|
+
status,
|
|
331
|
+
})
|
|
332
|
+
.onConflict((oc) => oc.columns(['workflowName', 'graphHash']).doNothing())
|
|
333
|
+
.execute()
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
async updateWorkflowVersionStatus(
|
|
337
|
+
name: string,
|
|
338
|
+
graphHash: string,
|
|
339
|
+
status: WorkflowVersionStatus
|
|
340
|
+
): Promise<void> {
|
|
341
|
+
await this.db
|
|
342
|
+
.updateTable('workflowVersions')
|
|
343
|
+
.set({ status })
|
|
344
|
+
.where('workflowName', '=', name)
|
|
345
|
+
.where('graphHash', '=', graphHash)
|
|
346
|
+
.execute()
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// ─── internals ────────────────────────────────────────────────────
|
|
350
|
+
|
|
351
|
+
private async updateStepStatus(
|
|
352
|
+
stepId: string,
|
|
353
|
+
status: StepState['status']
|
|
354
|
+
): Promise<void> {
|
|
355
|
+
await this.db
|
|
356
|
+
.updateTable('workflowStep')
|
|
357
|
+
.set({ status, updatedAt: new Date() })
|
|
358
|
+
.where('workflowStepId', '=', stepId)
|
|
359
|
+
.execute()
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
private async insertHistoryRecord(
|
|
363
|
+
stepId: string,
|
|
364
|
+
status: string,
|
|
365
|
+
resultJson?: string | null,
|
|
366
|
+
errorJson?: string | null
|
|
367
|
+
): Promise<void> {
|
|
368
|
+
const now = new Date()
|
|
369
|
+
const values: Record<string, any> = {
|
|
370
|
+
historyId: crypto.randomUUID(),
|
|
371
|
+
workflowStepId: stepId,
|
|
372
|
+
status,
|
|
373
|
+
result: resultJson ?? null,
|
|
374
|
+
error: errorJson ?? null,
|
|
375
|
+
createdAt: now,
|
|
376
|
+
}
|
|
377
|
+
const tsField = timestampFieldFor(status)
|
|
378
|
+
if (tsField) values[tsField] = now
|
|
379
|
+
|
|
380
|
+
await this.db
|
|
381
|
+
.insertInto('workflowStepHistory')
|
|
382
|
+
.values(values as any)
|
|
383
|
+
.execute()
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* The executor pattern is: `insertStepState` writes a 'pending' history
|
|
388
|
+
* row, then later transitions UPDATE that latest row in place rather
|
|
389
|
+
* than appending a new one — except for retry attempts which append.
|
|
390
|
+
*
|
|
391
|
+
* We mirror the same shape so `KyselyWorkflowRunService.getRunHistory`
|
|
392
|
+
* returns the same sequence the executor would have produced.
|
|
393
|
+
*/
|
|
394
|
+
private async appendOrUpdateLatestHistory(
|
|
395
|
+
stepId: string,
|
|
396
|
+
status: string,
|
|
397
|
+
resultJson?: string,
|
|
398
|
+
errorJson?: string
|
|
399
|
+
): Promise<void> {
|
|
400
|
+
const latest = await this.db
|
|
401
|
+
.selectFrom('workflowStepHistory')
|
|
402
|
+
.select('historyId')
|
|
403
|
+
.where('workflowStepId', '=', stepId)
|
|
404
|
+
.orderBy('createdAt', 'desc')
|
|
405
|
+
.limit(1)
|
|
406
|
+
.executeTakeFirst()
|
|
407
|
+
|
|
408
|
+
if (latest) {
|
|
409
|
+
const update: Record<string, any> = { status }
|
|
410
|
+
if (resultJson !== undefined) update.result = resultJson
|
|
411
|
+
if (errorJson !== undefined) update.error = errorJson
|
|
412
|
+
const tsField = timestampFieldFor(status)
|
|
413
|
+
if (tsField) update[tsField] = new Date()
|
|
414
|
+
await this.db
|
|
415
|
+
.updateTable('workflowStepHistory')
|
|
416
|
+
.set(update)
|
|
417
|
+
.where('historyId', '=', latest.historyId)
|
|
418
|
+
.execute()
|
|
419
|
+
} else {
|
|
420
|
+
await this.insertHistoryRecord(stepId, status, resultJson, errorJson)
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
function timestampFieldFor(status: string): string | null {
|
|
426
|
+
switch (status) {
|
|
427
|
+
case 'running':
|
|
428
|
+
return 'runningAt'
|
|
429
|
+
case 'scheduled':
|
|
430
|
+
return 'scheduledAt'
|
|
431
|
+
case 'succeeded':
|
|
432
|
+
return 'succeededAt'
|
|
433
|
+
case 'failed':
|
|
434
|
+
return 'failedAt'
|
|
435
|
+
default:
|
|
436
|
+
return null
|
|
437
|
+
}
|
|
438
|
+
}
|
|
@@ -137,7 +137,7 @@ export class KyselyWorkflowService extends PikkuWorkflowService {
|
|
|
137
137
|
this.initialized = true
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
-
async
|
|
140
|
+
protected async createRunImpl(
|
|
141
141
|
workflowName: string,
|
|
142
142
|
input: any,
|
|
143
143
|
inline: boolean,
|
|
@@ -173,7 +173,7 @@ export class KyselyWorkflowService extends PikkuWorkflowService {
|
|
|
173
173
|
return this.runService.getRun(id)
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
-
async
|
|
176
|
+
protected async updateRunStatusImpl(
|
|
177
177
|
id: string,
|
|
178
178
|
status: WorkflowStatus,
|
|
179
179
|
output?: any,
|
|
@@ -191,7 +191,7 @@ export class KyselyWorkflowService extends PikkuWorkflowService {
|
|
|
191
191
|
.execute()
|
|
192
192
|
}
|
|
193
193
|
|
|
194
|
-
async
|
|
194
|
+
protected async insertStepStateImpl(
|
|
195
195
|
runId: string,
|
|
196
196
|
stepName: string,
|
|
197
197
|
rpcName: string | null,
|
|
@@ -285,7 +285,7 @@ export class KyselyWorkflowService extends PikkuWorkflowService {
|
|
|
285
285
|
return this.runService.getRunHistory(runId)
|
|
286
286
|
}
|
|
287
287
|
|
|
288
|
-
async
|
|
288
|
+
protected async setStepRunningImpl(stepId: string): Promise<void> {
|
|
289
289
|
await this.db
|
|
290
290
|
.updateTable('workflowStep')
|
|
291
291
|
.set({ status: 'running', updatedAt: new Date() })
|
|
@@ -309,7 +309,7 @@ export class KyselyWorkflowService extends PikkuWorkflowService {
|
|
|
309
309
|
}
|
|
310
310
|
}
|
|
311
311
|
|
|
312
|
-
async
|
|
312
|
+
protected async setStepScheduledImpl(stepId: string): Promise<void> {
|
|
313
313
|
await this.db
|
|
314
314
|
.updateTable('workflowStep')
|
|
315
315
|
.set({ status: 'scheduled', updatedAt: new Date() })
|
|
@@ -359,7 +359,10 @@ export class KyselyWorkflowService extends PikkuWorkflowService {
|
|
|
359
359
|
}
|
|
360
360
|
}
|
|
361
361
|
|
|
362
|
-
async
|
|
362
|
+
protected async setStepChildRunIdImpl(
|
|
363
|
+
stepId: string,
|
|
364
|
+
childRunId: string
|
|
365
|
+
): Promise<void> {
|
|
363
366
|
await this.db
|
|
364
367
|
.updateTable('workflowStep')
|
|
365
368
|
.set({
|
|
@@ -370,7 +373,10 @@ export class KyselyWorkflowService extends PikkuWorkflowService {
|
|
|
370
373
|
.execute()
|
|
371
374
|
}
|
|
372
375
|
|
|
373
|
-
async
|
|
376
|
+
protected async setStepResultImpl(
|
|
377
|
+
stepId: string,
|
|
378
|
+
result: any
|
|
379
|
+
): Promise<void> {
|
|
374
380
|
const resultJson = JSON.stringify(result)
|
|
375
381
|
|
|
376
382
|
await this.db
|
|
@@ -401,7 +407,10 @@ export class KyselyWorkflowService extends PikkuWorkflowService {
|
|
|
401
407
|
}
|
|
402
408
|
}
|
|
403
409
|
|
|
404
|
-
async
|
|
410
|
+
protected async setStepErrorImpl(
|
|
411
|
+
stepId: string,
|
|
412
|
+
error: Error
|
|
413
|
+
): Promise<void> {
|
|
405
414
|
const serializedError: SerializedError = {
|
|
406
415
|
message: error.message,
|
|
407
416
|
stack: error.stack,
|
|
@@ -437,7 +446,7 @@ export class KyselyWorkflowService extends PikkuWorkflowService {
|
|
|
437
446
|
}
|
|
438
447
|
}
|
|
439
448
|
|
|
440
|
-
async
|
|
449
|
+
protected async createRetryAttemptImpl(
|
|
441
450
|
stepId: string,
|
|
442
451
|
status: 'pending' | 'running'
|
|
443
452
|
): Promise<StepState> {
|
|
@@ -580,7 +589,10 @@ export class KyselyWorkflowService extends PikkuWorkflowService {
|
|
|
580
589
|
return results
|
|
581
590
|
}
|
|
582
591
|
|
|
583
|
-
async
|
|
592
|
+
protected async setBranchTakenImpl(
|
|
593
|
+
stepId: string,
|
|
594
|
+
branchKey: string
|
|
595
|
+
): Promise<void> {
|
|
584
596
|
await this.db
|
|
585
597
|
.updateTable('workflowStep')
|
|
586
598
|
.set({ branchTaken: branchKey, updatedAt: new Date() })
|
|
@@ -588,7 +600,7 @@ export class KyselyWorkflowService extends PikkuWorkflowService {
|
|
|
588
600
|
.execute()
|
|
589
601
|
}
|
|
590
602
|
|
|
591
|
-
async
|
|
603
|
+
protected async updateRunStateImpl(
|
|
592
604
|
runId: string,
|
|
593
605
|
name: string,
|
|
594
606
|
value: unknown
|
|
@@ -620,7 +632,7 @@ export class KyselyWorkflowService extends PikkuWorkflowService {
|
|
|
620
632
|
return parseJson(row.state) ?? {}
|
|
621
633
|
}
|
|
622
634
|
|
|
623
|
-
async
|
|
635
|
+
protected async upsertWorkflowVersionImpl(
|
|
624
636
|
name: string,
|
|
625
637
|
graphHash: string,
|
|
626
638
|
graph: any,
|
|
@@ -640,7 +652,7 @@ export class KyselyWorkflowService extends PikkuWorkflowService {
|
|
|
640
652
|
.execute()
|
|
641
653
|
}
|
|
642
654
|
|
|
643
|
-
async
|
|
655
|
+
protected async updateWorkflowVersionStatusImpl(
|
|
644
656
|
name: string,
|
|
645
657
|
graphHash: string,
|
|
646
658
|
status: WorkflowVersionStatus
|