@aikirun/workflow 0.14.0 → 0.16.0
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 +16 -0
- package/dist/index.d.ts +79 -48
- package/dist/index.js +121 -50
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -44,6 +44,21 @@ const handle = await onboardingWorkflowV1.start(aikiClient, {
|
|
|
44
44
|
const result = await handle.waitForStatus("completed");
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
+
## Scheduling
|
|
48
|
+
|
|
49
|
+
Run workflows on a schedule using cron expressions or intervals:
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
import { schedule } from "@aikirun/workflow";
|
|
53
|
+
|
|
54
|
+
const dailyReport = schedule({
|
|
55
|
+
type: "cron",
|
|
56
|
+
expression: "0 9 * * *", // Every day at 9 AM
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
await dailyReport.activate(aikiClient, onboardingWorkflowV1, { email: "daily@example.com" });
|
|
60
|
+
```
|
|
61
|
+
|
|
47
62
|
## Features
|
|
48
63
|
|
|
49
64
|
- **Durable Execution** - Workflows survive crashes and restarts
|
|
@@ -53,6 +68,7 @@ const result = await handle.waitForStatus("completed");
|
|
|
53
68
|
- **Child Workflows** - Compose workflows together
|
|
54
69
|
- **Automatic Retries** - Configurable retry strategies
|
|
55
70
|
- **Versioning** - Run multiple versions simultaneously
|
|
71
|
+
- **Scheduling** - Trigger workflows on cron or interval schedules
|
|
56
72
|
|
|
57
73
|
## Documentation
|
|
58
74
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { WorkflowName, WorkflowVersionId } from '@aikirun/types/workflow';
|
|
2
2
|
import { Client, Logger, ApiClient } from '@aikirun/types/client';
|
|
3
3
|
import { INTERNAL } from '@aikirun/types/symbols';
|
|
4
|
-
import { WorkflowRun, TerminalWorkflowRunStatus, WorkflowRunState, WorkflowRunId,
|
|
4
|
+
import { WorkflowRun, TerminalWorkflowRunStatus, WorkflowRunState, WorkflowRunId, WorkflowStartOptions, WorkflowDefinitionOptions } from '@aikirun/types/workflow-run';
|
|
5
5
|
import { StandardSchemaV1 } from '@standard-schema/spec';
|
|
6
6
|
import { DurationObject, Duration } from '@aikirun/types/duration';
|
|
7
7
|
import { SleepResult } from '@aikirun/types/sleep';
|
|
@@ -10,6 +10,7 @@ import { Serializable } from '@aikirun/types/serializable';
|
|
|
10
10
|
import { DistributiveOmit, RequireAtLeastOneProp } from '@aikirun/types/utils';
|
|
11
11
|
import { TaskId } from '@aikirun/types/task';
|
|
12
12
|
import { WorkflowRunStateRequest, WorkflowRunTransitionTaskStateRequestV1 } from '@aikirun/types/workflow-run-api';
|
|
13
|
+
import { OverlapPolicy, ScheduleActivateOptions, ScheduleId } from '@aikirun/types/schedule';
|
|
13
14
|
|
|
14
15
|
type NonEmptyArray<T> = [T, ...T[]];
|
|
15
16
|
|
|
@@ -30,11 +31,11 @@ type PathFromObjectInternal<T, IncludeArrayKeys extends boolean> = And<[
|
|
|
30
31
|
type ExtractObjectType<T> = T extends object ? T : never;
|
|
31
32
|
type TypeOfValueAtPath<T extends object, Path extends PathFromObject<T>> = Path extends keyof T ? T[Path] : Path extends `${infer First}.${infer Rest}` ? First extends keyof T ? undefined extends T[First] ? Rest extends PathFromObject<ExtractObjectType<T[First]>> ? TypeOfValueAtPath<ExtractObjectType<T[First]>, Rest> | undefined : never : Rest extends PathFromObject<ExtractObjectType<T[First]>> ? TypeOfValueAtPath<ExtractObjectType<T[First]>, Rest> : never : never : never;
|
|
32
33
|
|
|
33
|
-
declare function workflowRunHandle<Input, Output, AppContext,
|
|
34
|
-
declare function workflowRunHandle<Input, Output, AppContext,
|
|
35
|
-
interface WorkflowRunHandle<Input, Output, AppContext,
|
|
34
|
+
declare function workflowRunHandle<Input, Output, AppContext, TEvents extends EventsDefinition>(client: Client<AppContext>, id: WorkflowRunId, eventsDefinition?: TEvents, logger?: Logger): Promise<WorkflowRunHandle<Input, Output, AppContext, TEvents>>;
|
|
35
|
+
declare function workflowRunHandle<Input, Output, AppContext, TEvents extends EventsDefinition>(client: Client<AppContext>, run: WorkflowRun<Input, Output>, eventsDefinition?: TEvents, logger?: Logger): Promise<WorkflowRunHandle<Input, Output, AppContext, TEvents>>;
|
|
36
|
+
interface WorkflowRunHandle<Input, Output, AppContext, TEvents extends EventsDefinition = EventsDefinition> {
|
|
36
37
|
run: Readonly<WorkflowRun<Input, Output>>;
|
|
37
|
-
events: EventSenders<
|
|
38
|
+
events: EventSenders<TEvents>;
|
|
38
39
|
refresh: () => Promise<void>;
|
|
39
40
|
/**
|
|
40
41
|
* Waits for the child workflow run to reach a terminal status by polling.
|
|
@@ -145,16 +146,16 @@ interface EventDefinition<Data> {
|
|
|
145
146
|
schema?: StandardSchemaV1<Data>;
|
|
146
147
|
}
|
|
147
148
|
type EventsDefinition = Record<string, EventDefinition<unknown>>;
|
|
148
|
-
type EventData<
|
|
149
|
-
type EventWaiters<
|
|
150
|
-
[K in keyof
|
|
149
|
+
type EventData<TEvent> = TEvent extends EventDefinition<infer Data> ? Data : never;
|
|
150
|
+
type EventWaiters<TEvents extends EventsDefinition> = {
|
|
151
|
+
[K in keyof TEvents]: EventWaiter<EventData<TEvents[K]>>;
|
|
151
152
|
};
|
|
152
153
|
interface EventWaiter<Data> {
|
|
153
154
|
wait(options?: EventWaitOptions<false>): Promise<EventWaitState<Data, false>>;
|
|
154
155
|
wait(options: EventWaitOptions<true>): Promise<EventWaitState<Data, true>>;
|
|
155
156
|
}
|
|
156
|
-
type EventSenders<
|
|
157
|
-
[K in keyof
|
|
157
|
+
type EventSenders<TEvents extends EventsDefinition> = {
|
|
158
|
+
[K in keyof TEvents]: EventSender<EventData<TEvents[K]>>;
|
|
158
159
|
};
|
|
159
160
|
interface EventSender<Data> {
|
|
160
161
|
with(): EventSenderBuilder<Data>;
|
|
@@ -164,8 +165,8 @@ interface EventSenderBuilder<Data> {
|
|
|
164
165
|
opt<Path extends PathFromObject<EventSendOptions>>(path: Path, value: TypeOfValueAtPath<EventSendOptions, Path>): EventSenderBuilder<Data>;
|
|
165
166
|
send: (...args: Data extends void ? [] : [Data]) => Promise<void>;
|
|
166
167
|
}
|
|
167
|
-
type EventMulticasters<
|
|
168
|
-
[K in keyof
|
|
168
|
+
type EventMulticasters<TEvents extends EventsDefinition> = {
|
|
169
|
+
[K in keyof TEvents]: EventMulticaster<EventData<TEvents[K]>>;
|
|
169
170
|
};
|
|
170
171
|
interface EventMulticaster<Data> {
|
|
171
172
|
with(): EventMulticasterBuilder<Data>;
|
|
@@ -175,26 +176,26 @@ interface EventMulticasterBuilder<Data> {
|
|
|
175
176
|
opt<Path extends PathFromObject<EventSendOptions>>(path: Path, value: TypeOfValueAtPath<EventSendOptions, Path>): EventMulticasterBuilder<Data>;
|
|
176
177
|
send: <AppContext>(client: Client<AppContext>, runId: string | string[], ...args: Data extends void ? [] : [Data]) => Promise<void>;
|
|
177
178
|
}
|
|
178
|
-
declare function createEventWaiters<
|
|
179
|
-
declare function createEventSenders<
|
|
179
|
+
declare function createEventWaiters<TEvents extends EventsDefinition>(handle: WorkflowRunHandle<unknown, unknown, unknown, TEvents>, eventsDefinition: TEvents, logger: Logger): EventWaiters<TEvents>;
|
|
180
|
+
declare function createEventSenders<TEvents extends EventsDefinition>(api: ApiClient, workflowRunId: string, eventsDefinition: TEvents, logger: Logger, onSend: (run: WorkflowRun<unknown, unknown>) => void): EventSenders<TEvents>;
|
|
180
181
|
|
|
181
|
-
interface WorkflowRunContext<Input, AppContext,
|
|
182
|
+
interface WorkflowRunContext<Input, AppContext, TEvents extends EventsDefinition> {
|
|
182
183
|
id: WorkflowRunId;
|
|
183
184
|
name: WorkflowName;
|
|
184
185
|
versionId: WorkflowVersionId;
|
|
185
|
-
options:
|
|
186
|
+
options: WorkflowStartOptions;
|
|
186
187
|
logger: Logger;
|
|
187
188
|
sleep: (name: string, duration: Duration) => Promise<SleepResult>;
|
|
188
|
-
events: EventWaiters<
|
|
189
|
+
events: EventWaiters<TEvents>;
|
|
189
190
|
[INTERNAL]: {
|
|
190
|
-
handle: WorkflowRunHandle<Input, unknown, AppContext,
|
|
191
|
+
handle: WorkflowRunHandle<Input, unknown, AppContext, TEvents>;
|
|
191
192
|
options: {
|
|
192
193
|
spinThresholdMs: number;
|
|
193
194
|
};
|
|
194
195
|
};
|
|
195
196
|
}
|
|
196
197
|
|
|
197
|
-
type ChildWorkflowRunHandle<Input, Output, AppContext,
|
|
198
|
+
type ChildWorkflowRunHandle<Input, Output, AppContext, TEvents extends EventsDefinition = EventsDefinition> = Omit<WorkflowRunHandle<Input, Output, AppContext, TEvents>, "waitForStatus"> & {
|
|
198
199
|
/**
|
|
199
200
|
* Waits for the child workflow run to reach a terminal status.
|
|
200
201
|
*
|
|
@@ -239,47 +240,44 @@ interface ChildWorkflowRunWaitOptions<Timed extends boolean> {
|
|
|
239
240
|
timeout?: Timed extends true ? DurationObject : never;
|
|
240
241
|
}
|
|
241
242
|
|
|
242
|
-
interface WorkflowVersionParams<Input, Output, AppContext,
|
|
243
|
-
handler: (run: Readonly<WorkflowRunContext<Input, AppContext,
|
|
244
|
-
events?:
|
|
245
|
-
opts?:
|
|
243
|
+
interface WorkflowVersionParams<Input, Output, AppContext, TEvents extends EventsDefinition> {
|
|
244
|
+
handler: (run: Readonly<WorkflowRunContext<Input, AppContext, TEvents>>, input: Input, context: AppContext) => Promise<Output>;
|
|
245
|
+
events?: TEvents;
|
|
246
|
+
opts?: WorkflowDefinitionOptions;
|
|
246
247
|
schema?: RequireAtLeastOneProp<{
|
|
247
248
|
input?: StandardSchemaV1<Input>;
|
|
248
249
|
output?: StandardSchemaV1<Output>;
|
|
249
250
|
}>;
|
|
250
251
|
}
|
|
251
|
-
interface WorkflowVersion<Input, Output, AppContext,
|
|
252
|
+
interface WorkflowVersion<Input, Output, AppContext, TEvents extends EventsDefinition = EventsDefinition> {
|
|
252
253
|
name: WorkflowName;
|
|
253
254
|
versionId: WorkflowVersionId;
|
|
254
|
-
events: EventMulticasters<
|
|
255
|
-
with(): WorkflowBuilder<Input, Output, AppContext,
|
|
256
|
-
start: (client: Client<AppContext>, ...args: Input extends void ? [] : [Input]) => Promise<WorkflowRunHandle<Input, Output, AppContext,
|
|
257
|
-
startAsChild: <ParentInput,
|
|
258
|
-
getHandleById: (client: Client<AppContext>, runId: string) => Promise<WorkflowRunHandle<Input, Output, AppContext,
|
|
259
|
-
getHandleByReferenceId: (client: Client<AppContext>, referenceId: string) => Promise<WorkflowRunHandle<Input, Output, AppContext,
|
|
255
|
+
events: EventMulticasters<TEvents>;
|
|
256
|
+
with(): WorkflowBuilder<Input, Output, AppContext, TEvents>;
|
|
257
|
+
start: (client: Client<AppContext>, ...args: Input extends void ? [] : [Input]) => Promise<WorkflowRunHandle<Input, Output, AppContext, TEvents>>;
|
|
258
|
+
startAsChild: <ParentInput, ParentEvents extends EventsDefinition>(parentRun: WorkflowRunContext<ParentInput, AppContext, ParentEvents>, ...args: Input extends void ? [] : [Input]) => Promise<ChildWorkflowRunHandle<Input, Output, AppContext, TEvents>>;
|
|
259
|
+
getHandleById: (client: Client<AppContext>, runId: string) => Promise<WorkflowRunHandle<Input, Output, AppContext, TEvents>>;
|
|
260
|
+
getHandleByReferenceId: (client: Client<AppContext>, referenceId: string) => Promise<WorkflowRunHandle<Input, Output, AppContext, TEvents>>;
|
|
260
261
|
[INTERNAL]: {
|
|
261
|
-
eventsDefinition:
|
|
262
|
-
handler: (run: WorkflowRunContext<Input, AppContext,
|
|
262
|
+
eventsDefinition: TEvents;
|
|
263
|
+
handler: (run: WorkflowRunContext<Input, AppContext, TEvents>, input: Input, context: AppContext) => Promise<void>;
|
|
263
264
|
};
|
|
264
265
|
}
|
|
265
|
-
|
|
266
|
-
opt<Path extends PathFromObject<WorkflowOptions>>(path: Path, value: TypeOfValueAtPath<WorkflowOptions, Path>): WorkflowBuilder<Input, Output, AppContext, TEventsDefinition>;
|
|
267
|
-
start: WorkflowVersion<Input, Output, AppContext, TEventsDefinition>["start"];
|
|
268
|
-
startAsChild: WorkflowVersion<Input, Output, AppContext, TEventsDefinition>["startAsChild"];
|
|
269
|
-
}
|
|
270
|
-
declare class WorkflowVersionImpl<Input, Output, AppContext, TEventsDefinition extends EventsDefinition> implements WorkflowVersion<Input, Output, AppContext, TEventsDefinition> {
|
|
266
|
+
declare class WorkflowVersionImpl<Input, Output, AppContext, TEvents extends EventsDefinition> implements WorkflowVersion<Input, Output, AppContext, TEvents> {
|
|
271
267
|
readonly name: WorkflowName;
|
|
272
268
|
readonly versionId: WorkflowVersionId;
|
|
273
269
|
private readonly params;
|
|
274
|
-
readonly events: EventMulticasters<
|
|
275
|
-
readonly [INTERNAL]: WorkflowVersion<Input, Output, AppContext,
|
|
276
|
-
constructor(name: WorkflowName, versionId: WorkflowVersionId, params: WorkflowVersionParams<Input, Output, AppContext,
|
|
277
|
-
with(): WorkflowBuilder<Input, Output, AppContext,
|
|
278
|
-
start(client: Client<AppContext>, ...args: Input extends void ? [] : [Input]): Promise<WorkflowRunHandle<Input, Output, AppContext,
|
|
279
|
-
|
|
270
|
+
readonly events: EventMulticasters<TEvents>;
|
|
271
|
+
readonly [INTERNAL]: WorkflowVersion<Input, Output, AppContext, TEvents>[typeof INTERNAL];
|
|
272
|
+
constructor(name: WorkflowName, versionId: WorkflowVersionId, params: WorkflowVersionParams<Input, Output, AppContext, TEvents>);
|
|
273
|
+
with(): WorkflowBuilder<Input, Output, AppContext, TEvents>;
|
|
274
|
+
start(client: Client<AppContext>, ...args: Input extends void ? [] : [Input]): Promise<WorkflowRunHandle<Input, Output, AppContext, TEvents>>;
|
|
275
|
+
startWithOpts(client: Client<AppContext>, startOpts: WorkflowStartOptions, ...args: Input extends void ? [] : [Input]): Promise<WorkflowRunHandle<Input, Output, AppContext, TEvents>>;
|
|
276
|
+
startAsChild(parentRun: WorkflowRunContext<unknown, AppContext, EventsDefinition>, ...args: Input extends void ? [] : [Input]): Promise<ChildWorkflowRunHandle<Input, Output, AppContext, TEvents>>;
|
|
277
|
+
startAsChildWithOpts(parentRun: WorkflowRunContext<unknown, AppContext, EventsDefinition>, startOpts: WorkflowStartOptions, ...args: Input extends void ? [] : [Input]): Promise<ChildWorkflowRunHandle<Input, Output, AppContext, TEvents>>;
|
|
280
278
|
private assertUniqueChildRunReferenceId;
|
|
281
|
-
getHandleById(client: Client<AppContext>, runId: string): Promise<WorkflowRunHandle<Input, Output, AppContext,
|
|
282
|
-
getHandleByReferenceId(client: Client<AppContext>, referenceId: string): Promise<WorkflowRunHandle<Input, Output, AppContext,
|
|
279
|
+
getHandleById(client: Client<AppContext>, runId: string): Promise<WorkflowRunHandle<Input, Output, AppContext, TEvents>>;
|
|
280
|
+
getHandleByReferenceId(client: Client<AppContext>, referenceId: string): Promise<WorkflowRunHandle<Input, Output, AppContext, TEvents>>;
|
|
283
281
|
private handler;
|
|
284
282
|
private tryExecuteWorkflow;
|
|
285
283
|
private assertRetryAllowed;
|
|
@@ -287,6 +285,11 @@ declare class WorkflowVersionImpl<Input, Output, AppContext, TEventsDefinition e
|
|
|
287
285
|
private createFailedState;
|
|
288
286
|
private createAwaitingRetryState;
|
|
289
287
|
}
|
|
288
|
+
interface WorkflowBuilder<Input, Output, AppContext, TEvents extends EventsDefinition> {
|
|
289
|
+
opt<Path extends PathFromObject<WorkflowStartOptions>>(path: Path, value: TypeOfValueAtPath<WorkflowStartOptions, Path>): WorkflowBuilder<Input, Output, AppContext, TEvents>;
|
|
290
|
+
start: WorkflowVersion<Input, Output, AppContext, TEvents>["start"];
|
|
291
|
+
startAsChild: WorkflowVersion<Input, Output, AppContext, TEvents>["startAsChild"];
|
|
292
|
+
}
|
|
290
293
|
|
|
291
294
|
declare function workflowRegistry(): WorkflowRegistry;
|
|
292
295
|
type Workflow$1 = WorkflowVersion<unknown, unknown, unknown>;
|
|
@@ -302,6 +305,34 @@ interface WorkflowRegistry {
|
|
|
302
305
|
|
|
303
306
|
declare function createSleeper(handle: WorkflowRunHandle<unknown, unknown, unknown>, logger: Logger): (name: string, duration: Duration) => Promise<SleepResult>;
|
|
304
307
|
|
|
308
|
+
interface CronScheduleParams {
|
|
309
|
+
type: "cron";
|
|
310
|
+
expression: string;
|
|
311
|
+
timezone?: string;
|
|
312
|
+
overlapPolicy?: OverlapPolicy;
|
|
313
|
+
}
|
|
314
|
+
interface IntervalScheduleParams {
|
|
315
|
+
type: "interval";
|
|
316
|
+
every: DurationObject;
|
|
317
|
+
overlapPolicy?: OverlapPolicy;
|
|
318
|
+
}
|
|
319
|
+
type ScheduleParams = CronScheduleParams | IntervalScheduleParams;
|
|
320
|
+
interface ScheduleHandle {
|
|
321
|
+
id: ScheduleId;
|
|
322
|
+
pause(): Promise<void>;
|
|
323
|
+
resume(): Promise<void>;
|
|
324
|
+
delete(): Promise<void>;
|
|
325
|
+
}
|
|
326
|
+
interface ScheduleBuilder {
|
|
327
|
+
opt<Path extends PathFromObject<ScheduleActivateOptions>>(path: Path, value: TypeOfValueAtPath<ScheduleActivateOptions, Path>): ScheduleBuilder;
|
|
328
|
+
activate<Input, Output, AppContext, TEvents extends EventsDefinition>(client: Client<AppContext>, workflow: WorkflowVersion<Input, Output, AppContext, TEvents>, ...args: Input extends void ? [] : [Input]): Promise<ScheduleHandle>;
|
|
329
|
+
}
|
|
330
|
+
type ScheduleDefinition = ScheduleParams & {
|
|
331
|
+
with(): ScheduleBuilder;
|
|
332
|
+
activate<Input, Output, AppContext, TEvents extends EventsDefinition>(client: Client<AppContext>, workflow: WorkflowVersion<Input, Output, AppContext, TEvents>, ...args: Input extends void ? [] : [Input]): Promise<ScheduleHandle>;
|
|
333
|
+
};
|
|
334
|
+
declare function schedule(params: ScheduleParams): ScheduleDefinition;
|
|
335
|
+
|
|
305
336
|
/**
|
|
306
337
|
* Defines a durable workflow with versioning and multiple task execution.
|
|
307
338
|
*
|
|
@@ -355,11 +386,11 @@ interface WorkflowParams {
|
|
|
355
386
|
}
|
|
356
387
|
interface Workflow {
|
|
357
388
|
name: WorkflowName;
|
|
358
|
-
v: <Input extends Serializable, Output extends Serializable, AppContext = null,
|
|
389
|
+
v: <Input extends Serializable, Output extends Serializable, AppContext = null, TEvents extends EventsDefinition = Record<string, never>>(versionId: string, params: WorkflowVersionParams<Input, Output, AppContext, TEvents>) => WorkflowVersion<Input, Output, AppContext, TEvents>;
|
|
359
390
|
[INTERNAL]: {
|
|
360
391
|
getAllVersions: () => WorkflowVersion<unknown, unknown, unknown>[];
|
|
361
392
|
getVersion: (versionId: WorkflowVersionId) => WorkflowVersion<unknown, unknown, unknown> | undefined;
|
|
362
393
|
};
|
|
363
394
|
}
|
|
364
395
|
|
|
365
|
-
export { type EventMulticaster, type EventMulticasters, type EventSender, type EventSenders, type EventWaiter, type EventWaiters, type Workflow, type WorkflowParams, type WorkflowRegistry, type WorkflowRunContext, type WorkflowRunHandle, type WorkflowRunWaitOptions, type WorkflowVersion, WorkflowVersionImpl, type WorkflowVersionParams, createEventSenders, createEventWaiters, createSleeper, event, workflow, workflowRegistry, workflowRunHandle };
|
|
396
|
+
export { type EventMulticaster, type EventMulticasters, type EventSender, type EventSenders, type EventWaiter, type EventWaiters, type ScheduleDefinition, type ScheduleHandle, type ScheduleParams, type Workflow, type WorkflowParams, type WorkflowRegistry, type WorkflowRunContext, type WorkflowRunHandle, type WorkflowRunWaitOptions, type WorkflowVersion, WorkflowVersionImpl, type WorkflowVersionParams, createEventSenders, createEventWaiters, createSleeper, event, schedule, workflow, workflowRegistry, workflowRunHandle };
|
package/dist/index.js
CHANGED
|
@@ -292,8 +292,8 @@ function getRetryParams(attempts, strategy) {
|
|
|
292
292
|
import { INTERNAL } from "@aikirun/types/symbols";
|
|
293
293
|
import { SchemaValidationError } from "@aikirun/types/validator";
|
|
294
294
|
import {
|
|
295
|
-
WorkflowRunConflictError,
|
|
296
295
|
WorkflowRunFailedError,
|
|
296
|
+
WorkflowRunRevisionConflictError,
|
|
297
297
|
WorkflowRunSuspendedError
|
|
298
298
|
} from "@aikirun/types/workflow-run";
|
|
299
299
|
function event(params) {
|
|
@@ -361,7 +361,7 @@ function createEventWaiter(handle, eventName, schema, logger) {
|
|
|
361
361
|
...timeoutInMs !== void 0 ? { "aiki.timeoutInMs": timeoutInMs } : {}
|
|
362
362
|
});
|
|
363
363
|
} catch (error) {
|
|
364
|
-
if (error instanceof
|
|
364
|
+
if (error instanceof WorkflowRunRevisionConflictError) {
|
|
365
365
|
throw new WorkflowRunSuspendedError(handle.run.id);
|
|
366
366
|
}
|
|
367
367
|
throw error;
|
|
@@ -392,10 +392,9 @@ function createEventSender(api, workflowRunId, eventName, schema, logger, onSend
|
|
|
392
392
|
send: (...args) => createEventSender(api, workflowRunId, eventName, schema, logger, onSend, optsBuilder.build()).send(...args)
|
|
393
393
|
});
|
|
394
394
|
async function send(...args) {
|
|
395
|
-
|
|
396
|
-
let data = dataRaw;
|
|
395
|
+
let data = args[0];
|
|
397
396
|
if (schema) {
|
|
398
|
-
const schemaValidation = schema["~standard"].validate(
|
|
397
|
+
const schemaValidation = schema["~standard"].validate(data);
|
|
399
398
|
const schemaValidationResult = schemaValidation instanceof Promise ? await schemaValidation : schemaValidation;
|
|
400
399
|
if (schemaValidationResult.issues) {
|
|
401
400
|
logger.error("Invalid event data", { "aiki.issues": schemaValidationResult.issues });
|
|
@@ -443,10 +442,9 @@ function createEventMulticaster(workflowName, workflowVersionId, eventName, sche
|
|
|
443
442
|
)
|
|
444
443
|
});
|
|
445
444
|
async function send(client, runId, ...args) {
|
|
446
|
-
|
|
447
|
-
let data = dataRaw;
|
|
445
|
+
let data = args[0];
|
|
448
446
|
if (schema) {
|
|
449
|
-
const schemaValidation = schema["~standard"].validate(
|
|
447
|
+
const schemaValidation = schema["~standard"].validate(data);
|
|
450
448
|
const schemaValidationResult = schemaValidation instanceof Promise ? await schemaValidation : schemaValidation;
|
|
451
449
|
if (schemaValidationResult.issues) {
|
|
452
450
|
client.logger.error("Invalid event data", {
|
|
@@ -487,8 +485,8 @@ function createEventMulticaster(workflowName, workflowVersionId, eventName, sche
|
|
|
487
485
|
import { INTERNAL as INTERNAL2 } from "@aikirun/types/symbols";
|
|
488
486
|
import {
|
|
489
487
|
isTerminalWorkflowRunStatus,
|
|
490
|
-
|
|
491
|
-
|
|
488
|
+
WorkflowRunNotExecutableError,
|
|
489
|
+
WorkflowRunRevisionConflictError as WorkflowRunRevisionConflictError2
|
|
492
490
|
} from "@aikirun/types/workflow-run";
|
|
493
491
|
async function workflowRunHandle(client, runOrId, eventsDefinition, logger) {
|
|
494
492
|
const run = typeof runOrId !== "string" ? runOrId : (await client.api.workflowRun.getByIdV1({ id: runOrId })).run;
|
|
@@ -624,7 +622,7 @@ var WorkflowRunHandleImpl = class {
|
|
|
624
622
|
this._run = run;
|
|
625
623
|
} catch (error) {
|
|
626
624
|
if (isConflictError(error)) {
|
|
627
|
-
throw new
|
|
625
|
+
throw new WorkflowRunRevisionConflictError2(this.run.id);
|
|
628
626
|
}
|
|
629
627
|
throw error;
|
|
630
628
|
}
|
|
@@ -640,7 +638,7 @@ var WorkflowRunHandleImpl = class {
|
|
|
640
638
|
return { taskId };
|
|
641
639
|
} catch (error) {
|
|
642
640
|
if (isConflictError(error)) {
|
|
643
|
-
throw new
|
|
641
|
+
throw new WorkflowRunRevisionConflictError2(this.run.id);
|
|
644
642
|
}
|
|
645
643
|
throw error;
|
|
646
644
|
}
|
|
@@ -658,7 +656,10 @@ function isConflictError(error) {
|
|
|
658
656
|
|
|
659
657
|
// run/sleeper.ts
|
|
660
658
|
import { INTERNAL as INTERNAL3 } from "@aikirun/types/symbols";
|
|
661
|
-
import {
|
|
659
|
+
import {
|
|
660
|
+
WorkflowRunRevisionConflictError as WorkflowRunRevisionConflictError3,
|
|
661
|
+
WorkflowRunSuspendedError as WorkflowRunSuspendedError2
|
|
662
|
+
} from "@aikirun/types/workflow-run";
|
|
662
663
|
var MAX_SLEEP_YEARS = 10;
|
|
663
664
|
var MAX_SLEEP_MS = MAX_SLEEP_YEARS * 365 * 24 * 60 * 60 * 1e3;
|
|
664
665
|
function createSleeper(handle, logger) {
|
|
@@ -680,7 +681,7 @@ function createSleeper(handle, logger) {
|
|
|
680
681
|
"aiki.durationMs": durationMs
|
|
681
682
|
});
|
|
682
683
|
} catch (error) {
|
|
683
|
-
if (error instanceof
|
|
684
|
+
if (error instanceof WorkflowRunRevisionConflictError3) {
|
|
684
685
|
throw new WorkflowRunSuspendedError2(handle.run.id);
|
|
685
686
|
}
|
|
686
687
|
throw error;
|
|
@@ -728,7 +729,7 @@ function createSleeper(handle, logger) {
|
|
|
728
729
|
"aiki.durationMs": durationMs
|
|
729
730
|
});
|
|
730
731
|
} catch (error) {
|
|
731
|
-
if (error instanceof
|
|
732
|
+
if (error instanceof WorkflowRunRevisionConflictError3) {
|
|
732
733
|
throw new WorkflowRunSuspendedError2(handle.run.id);
|
|
733
734
|
}
|
|
734
735
|
throw error;
|
|
@@ -737,11 +738,72 @@ function createSleeper(handle, logger) {
|
|
|
737
738
|
};
|
|
738
739
|
}
|
|
739
740
|
|
|
741
|
+
// schedule.ts
|
|
742
|
+
function schedule(params) {
|
|
743
|
+
async function activateWithOpts(client, workflow2, options, ...args) {
|
|
744
|
+
const input = args[0];
|
|
745
|
+
let scheduleSpec;
|
|
746
|
+
if (params.type === "interval") {
|
|
747
|
+
const { every, ...rest } = params;
|
|
748
|
+
scheduleSpec = {
|
|
749
|
+
...rest,
|
|
750
|
+
everyMs: toMilliseconds(every)
|
|
751
|
+
};
|
|
752
|
+
} else {
|
|
753
|
+
scheduleSpec = params;
|
|
754
|
+
}
|
|
755
|
+
const { schedule: schedule2 } = await client.api.schedule.activateV1({
|
|
756
|
+
workflowName: workflow2.name,
|
|
757
|
+
workflowVersionId: workflow2.versionId,
|
|
758
|
+
spec: scheduleSpec,
|
|
759
|
+
input,
|
|
760
|
+
options
|
|
761
|
+
});
|
|
762
|
+
client.logger.info("Schedule activated", {
|
|
763
|
+
scheduleSpec,
|
|
764
|
+
workflowName: workflow2.name,
|
|
765
|
+
workflowVersionId: workflow2.versionId,
|
|
766
|
+
referenceId: options?.reference?.id
|
|
767
|
+
});
|
|
768
|
+
const scheduleId = schedule2.id;
|
|
769
|
+
return {
|
|
770
|
+
id: scheduleId,
|
|
771
|
+
pause: async () => {
|
|
772
|
+
await client.api.schedule.pauseV1({ id: scheduleId });
|
|
773
|
+
},
|
|
774
|
+
resume: async () => {
|
|
775
|
+
await client.api.schedule.resumeV1({ id: scheduleId });
|
|
776
|
+
},
|
|
777
|
+
delete: async () => {
|
|
778
|
+
await client.api.schedule.deleteV1({ id: scheduleId });
|
|
779
|
+
}
|
|
780
|
+
};
|
|
781
|
+
}
|
|
782
|
+
function createBuilder(optsBuilder) {
|
|
783
|
+
return {
|
|
784
|
+
opt: (path, value) => createBuilder(optsBuilder.with(path, value)),
|
|
785
|
+
async activate(client, workflow2, ...args) {
|
|
786
|
+
return activateWithOpts(client, workflow2, optsBuilder.build(), ...args);
|
|
787
|
+
}
|
|
788
|
+
};
|
|
789
|
+
}
|
|
790
|
+
return {
|
|
791
|
+
...params,
|
|
792
|
+
with() {
|
|
793
|
+
const optsOverrider = objectOverrider({});
|
|
794
|
+
return createBuilder(optsOverrider());
|
|
795
|
+
},
|
|
796
|
+
async activate(client, workflow2, ...args) {
|
|
797
|
+
return activateWithOpts(client, workflow2, {}, ...args);
|
|
798
|
+
}
|
|
799
|
+
};
|
|
800
|
+
}
|
|
801
|
+
|
|
740
802
|
// workflow.ts
|
|
741
803
|
import { INTERNAL as INTERNAL6 } from "@aikirun/types/symbols";
|
|
742
804
|
|
|
743
|
-
// ../../lib/
|
|
744
|
-
function
|
|
805
|
+
// ../../lib/address/index.ts
|
|
806
|
+
function getWorkflowRunAddress(name, versionId, referenceId) {
|
|
745
807
|
return `${name}/${versionId}/${referenceId}`;
|
|
746
808
|
}
|
|
747
809
|
|
|
@@ -750,8 +812,8 @@ import { INTERNAL as INTERNAL5 } from "@aikirun/types/symbols";
|
|
|
750
812
|
import { TaskFailedError } from "@aikirun/types/task";
|
|
751
813
|
import { SchemaValidationError as SchemaValidationError2 } from "@aikirun/types/validator";
|
|
752
814
|
import {
|
|
753
|
-
WorkflowRunConflictError as WorkflowRunConflictError5,
|
|
754
815
|
WorkflowRunFailedError as WorkflowRunFailedError2,
|
|
816
|
+
WorkflowRunRevisionConflictError as WorkflowRunRevisionConflictError5,
|
|
755
817
|
WorkflowRunSuspendedError as WorkflowRunSuspendedError4
|
|
756
818
|
} from "@aikirun/types/workflow-run";
|
|
757
819
|
|
|
@@ -759,7 +821,7 @@ import {
|
|
|
759
821
|
import { INTERNAL as INTERNAL4 } from "@aikirun/types/symbols";
|
|
760
822
|
import {
|
|
761
823
|
isTerminalWorkflowRunStatus as isTerminalWorkflowRunStatus2,
|
|
762
|
-
|
|
824
|
+
WorkflowRunRevisionConflictError as WorkflowRunRevisionConflictError4,
|
|
763
825
|
WorkflowRunSuspendedError as WorkflowRunSuspendedError3
|
|
764
826
|
} from "@aikirun/types/workflow-run";
|
|
765
827
|
async function childWorkflowRunHandle(client, run, parentRun, logger, eventsDefinition) {
|
|
@@ -780,7 +842,7 @@ function createStatusWaiter(handle, parentRun, logger) {
|
|
|
780
842
|
let nextWaitIndex = 0;
|
|
781
843
|
async function waitForStatus(expectedStatus, options) {
|
|
782
844
|
const parentRunHandle = parentRun[INTERNAL4].handle;
|
|
783
|
-
const waitResults = parentRunHandle.run.childWorkflowRuns[handle.run.
|
|
845
|
+
const waitResults = parentRunHandle.run.childWorkflowRuns[handle.run.address]?.statusWaitResults ?? [];
|
|
784
846
|
const waitResult = waitResults[nextWaitIndex];
|
|
785
847
|
if (waitResult) {
|
|
786
848
|
nextWaitIndex++;
|
|
@@ -838,7 +900,7 @@ function createStatusWaiter(handle, parentRun, logger) {
|
|
|
838
900
|
...timeoutInMs !== void 0 ? { "aiki.timeoutInMs": timeoutInMs } : {}
|
|
839
901
|
});
|
|
840
902
|
} catch (error) {
|
|
841
|
-
if (error instanceof
|
|
903
|
+
if (error instanceof WorkflowRunRevisionConflictError4) {
|
|
842
904
|
throw new WorkflowRunSuspendedError3(parentRun.id);
|
|
843
905
|
}
|
|
844
906
|
throw error;
|
|
@@ -849,7 +911,7 @@ function createStatusWaiter(handle, parentRun, logger) {
|
|
|
849
911
|
}
|
|
850
912
|
|
|
851
913
|
// workflow-version.ts
|
|
852
|
-
var WorkflowVersionImpl = class
|
|
914
|
+
var WorkflowVersionImpl = class {
|
|
853
915
|
constructor(name, versionId, params) {
|
|
854
916
|
this.name = name;
|
|
855
917
|
this.versionId = versionId;
|
|
@@ -864,28 +926,18 @@ var WorkflowVersionImpl = class _WorkflowVersionImpl {
|
|
|
864
926
|
events;
|
|
865
927
|
[INTERNAL5];
|
|
866
928
|
with() {
|
|
867
|
-
const
|
|
868
|
-
const
|
|
869
|
-
|
|
870
|
-
opt: (path, value) => createBuilder(optsBuilder.with(path, value)),
|
|
871
|
-
start: (client, ...args) => new _WorkflowVersionImpl(this.name, this.versionId, {
|
|
872
|
-
...this.params,
|
|
873
|
-
opts: optsBuilder.build()
|
|
874
|
-
}).start(client, ...args),
|
|
875
|
-
startAsChild: (parentRun, ...args) => new _WorkflowVersionImpl(this.name, this.versionId, {
|
|
876
|
-
...this.params,
|
|
877
|
-
opts: optsBuilder.build()
|
|
878
|
-
}).startAsChild(parentRun, ...args)
|
|
879
|
-
};
|
|
880
|
-
};
|
|
881
|
-
return createBuilder(optsOverrider());
|
|
929
|
+
const startOpts = this.params.opts ?? {};
|
|
930
|
+
const startOptsOverrider = objectOverrider(startOpts);
|
|
931
|
+
return new WorkflowBuilderImpl(this, startOptsOverrider());
|
|
882
932
|
}
|
|
883
933
|
async start(client, ...args) {
|
|
884
|
-
|
|
885
|
-
|
|
934
|
+
return this.startWithOpts(client, this.params.opts ?? {}, ...args);
|
|
935
|
+
}
|
|
936
|
+
async startWithOpts(client, startOpts, ...args) {
|
|
937
|
+
let input = args[0];
|
|
886
938
|
const schema = this.params.schema?.input;
|
|
887
939
|
if (schema) {
|
|
888
|
-
const schemaValidation = schema["~standard"].validate(
|
|
940
|
+
const schemaValidation = schema["~standard"].validate(input);
|
|
889
941
|
const schemaValidationResult = schemaValidation instanceof Promise ? await schemaValidation : schemaValidation;
|
|
890
942
|
if (schemaValidationResult.issues) {
|
|
891
943
|
client.logger.error("Invalid workflow data", { "aiki.issues": schemaValidationResult.issues });
|
|
@@ -897,7 +949,7 @@ var WorkflowVersionImpl = class _WorkflowVersionImpl {
|
|
|
897
949
|
name: this.name,
|
|
898
950
|
versionId: this.versionId,
|
|
899
951
|
input,
|
|
900
|
-
options:
|
|
952
|
+
options: startOpts
|
|
901
953
|
});
|
|
902
954
|
client.logger.info("Created workflow", {
|
|
903
955
|
"aiki.workflowName": this.name,
|
|
@@ -907,15 +959,18 @@ var WorkflowVersionImpl = class _WorkflowVersionImpl {
|
|
|
907
959
|
return workflowRunHandle(client, run, this[INTERNAL5].eventsDefinition);
|
|
908
960
|
}
|
|
909
961
|
async startAsChild(parentRun, ...args) {
|
|
962
|
+
return this.startAsChildWithOpts(parentRun, this.params.opts ?? {}, ...args);
|
|
963
|
+
}
|
|
964
|
+
async startAsChildWithOpts(parentRun, startOpts, ...args) {
|
|
910
965
|
const parentRunHandle = parentRun[INTERNAL5].handle;
|
|
911
966
|
parentRunHandle[INTERNAL5].assertExecutionAllowed();
|
|
912
967
|
const { client } = parentRunHandle[INTERNAL5];
|
|
913
|
-
const inputRaw =
|
|
968
|
+
const inputRaw = args[0];
|
|
914
969
|
const input = await this.parse(parentRunHandle, this.params.schema?.input, inputRaw, parentRun.logger);
|
|
915
970
|
const inputHash = await hashInput(input);
|
|
916
|
-
const reference =
|
|
917
|
-
const
|
|
918
|
-
const existingRunInfo = parentRunHandle.run.childWorkflowRuns[
|
|
971
|
+
const reference = startOpts.reference;
|
|
972
|
+
const address = getWorkflowRunAddress(this.name, this.versionId, reference?.id ?? inputHash);
|
|
973
|
+
const existingRunInfo = parentRunHandle.run.childWorkflowRuns[address];
|
|
919
974
|
if (existingRunInfo) {
|
|
920
975
|
await this.assertUniqueChildRunReferenceId(
|
|
921
976
|
parentRunHandle,
|
|
@@ -946,9 +1001,9 @@ var WorkflowVersionImpl = class _WorkflowVersionImpl {
|
|
|
946
1001
|
versionId: this.versionId,
|
|
947
1002
|
input,
|
|
948
1003
|
parentWorkflowRunId: parentRun.id,
|
|
949
|
-
options:
|
|
1004
|
+
options: startOpts
|
|
950
1005
|
});
|
|
951
|
-
parentRunHandle.run.childWorkflowRuns[
|
|
1006
|
+
parentRunHandle.run.childWorkflowRuns[address] = {
|
|
952
1007
|
id: newRun.id,
|
|
953
1008
|
name: newRun.name,
|
|
954
1009
|
versionId: newRun.versionId,
|
|
@@ -971,8 +1026,8 @@ var WorkflowVersionImpl = class _WorkflowVersionImpl {
|
|
|
971
1026
|
}
|
|
972
1027
|
async assertUniqueChildRunReferenceId(parentRunHandle, existingRunInfo, inputHash, reference, logger) {
|
|
973
1028
|
if (existingRunInfo.inputHash !== inputHash && reference) {
|
|
974
|
-
const
|
|
975
|
-
if (
|
|
1029
|
+
const conflictPolicy = reference.conflictPolicy ?? "error";
|
|
1030
|
+
if (conflictPolicy !== "error") {
|
|
976
1031
|
return;
|
|
977
1032
|
}
|
|
978
1033
|
logger.error("Reference ID already used by another child workflow", {
|
|
@@ -1026,7 +1081,7 @@ var WorkflowVersionImpl = class _WorkflowVersionImpl {
|
|
|
1026
1081
|
const output = await this.parse(handle, this.params.schema?.output, outputRaw, run.logger);
|
|
1027
1082
|
return output;
|
|
1028
1083
|
} catch (error) {
|
|
1029
|
-
if (error instanceof WorkflowRunSuspendedError4 || error instanceof WorkflowRunFailedError2 || error instanceof
|
|
1084
|
+
if (error instanceof WorkflowRunSuspendedError4 || error instanceof WorkflowRunFailedError2 || error instanceof WorkflowRunRevisionConflictError5) {
|
|
1030
1085
|
throw error;
|
|
1031
1086
|
}
|
|
1032
1087
|
const attempts = handle.run.attempts;
|
|
@@ -1123,6 +1178,21 @@ var WorkflowVersionImpl = class _WorkflowVersionImpl {
|
|
|
1123
1178
|
};
|
|
1124
1179
|
}
|
|
1125
1180
|
};
|
|
1181
|
+
var WorkflowBuilderImpl = class _WorkflowBuilderImpl {
|
|
1182
|
+
constructor(workflow2, startOptsBuilder) {
|
|
1183
|
+
this.workflow = workflow2;
|
|
1184
|
+
this.startOptsBuilder = startOptsBuilder;
|
|
1185
|
+
}
|
|
1186
|
+
opt(path, value) {
|
|
1187
|
+
return new _WorkflowBuilderImpl(this.workflow, this.startOptsBuilder.with(path, value));
|
|
1188
|
+
}
|
|
1189
|
+
start(client, ...args) {
|
|
1190
|
+
return this.workflow.startWithOpts(client, this.startOptsBuilder.build(), ...args);
|
|
1191
|
+
}
|
|
1192
|
+
startAsChild(parentRun, ...args) {
|
|
1193
|
+
return this.workflow.startAsChildWithOpts(parentRun, this.startOptsBuilder.build(), ...args);
|
|
1194
|
+
}
|
|
1195
|
+
};
|
|
1126
1196
|
|
|
1127
1197
|
// workflow.ts
|
|
1128
1198
|
function workflow(params) {
|
|
@@ -1163,6 +1233,7 @@ export {
|
|
|
1163
1233
|
createEventWaiters,
|
|
1164
1234
|
createSleeper,
|
|
1165
1235
|
event,
|
|
1236
|
+
schedule,
|
|
1166
1237
|
workflow,
|
|
1167
1238
|
workflowRegistry,
|
|
1168
1239
|
workflowRunHandle
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aikirun/workflow",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"description": "Workflow SDK for Aiki - define durable workflows with tasks, sleeps, waits, and event handling",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"build": "tsup"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@aikirun/types": "0.
|
|
21
|
+
"@aikirun/types": "0.16.0",
|
|
22
22
|
"@standard-schema/spec": "^1.1.0"
|
|
23
23
|
},
|
|
24
24
|
"publishConfig": {
|