@aikirun/workflow 0.15.0 → 0.17.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 +0 -1
- package/dist/index.d.ts +12 -11
- package/dist/index.js +79 -60
- package/package.json +2 -2
package/README.md
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -5,12 +5,12 @@ import { WorkflowRun, TerminalWorkflowRunStatus, WorkflowRunState, WorkflowRunId
|
|
|
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';
|
|
8
|
-
import { EventSendOptions, EventWaitOptions,
|
|
8
|
+
import { EventSendOptions, EventWaitOptions, EventWaitResult } from '@aikirun/types/event';
|
|
9
9
|
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 {
|
|
13
|
+
import { ScheduleOverlapPolicy, ScheduleActivateOptions, ScheduleId } from '@aikirun/types/schedule';
|
|
14
14
|
|
|
15
15
|
type NonEmptyArray<T> = [T, ...T[]];
|
|
16
16
|
|
|
@@ -151,8 +151,8 @@ type EventWaiters<TEvents extends EventsDefinition> = {
|
|
|
151
151
|
[K in keyof TEvents]: EventWaiter<EventData<TEvents[K]>>;
|
|
152
152
|
};
|
|
153
153
|
interface EventWaiter<Data> {
|
|
154
|
-
wait(options?: EventWaitOptions<false>): Promise<
|
|
155
|
-
wait(options: EventWaitOptions<true>): Promise<
|
|
154
|
+
wait(options?: EventWaitOptions<false>): Promise<EventWaitResult<Data, false>>;
|
|
155
|
+
wait(options: EventWaitOptions<true>): Promise<EventWaitResult<Data, true>>;
|
|
156
156
|
}
|
|
157
157
|
type EventSenders<TEvents extends EventsDefinition> = {
|
|
158
158
|
[K in keyof TEvents]: EventSender<EventData<TEvents[K]>>;
|
|
@@ -309,28 +309,29 @@ interface CronScheduleParams {
|
|
|
309
309
|
type: "cron";
|
|
310
310
|
expression: string;
|
|
311
311
|
timezone?: string;
|
|
312
|
-
overlapPolicy?:
|
|
312
|
+
overlapPolicy?: ScheduleOverlapPolicy;
|
|
313
313
|
}
|
|
314
314
|
interface IntervalScheduleParams {
|
|
315
315
|
type: "interval";
|
|
316
316
|
every: DurationObject;
|
|
317
|
-
overlapPolicy?:
|
|
317
|
+
overlapPolicy?: ScheduleOverlapPolicy;
|
|
318
318
|
}
|
|
319
319
|
type ScheduleParams = CronScheduleParams | IntervalScheduleParams;
|
|
320
320
|
interface ScheduleHandle {
|
|
321
321
|
id: ScheduleId;
|
|
322
|
-
name: ScheduleName;
|
|
323
322
|
pause(): Promise<void>;
|
|
324
323
|
resume(): Promise<void>;
|
|
325
324
|
delete(): Promise<void>;
|
|
326
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
|
+
}
|
|
327
330
|
type ScheduleDefinition = ScheduleParams & {
|
|
328
|
-
|
|
331
|
+
with(): ScheduleBuilder;
|
|
329
332
|
activate<Input, Output, AppContext, TEvents extends EventsDefinition>(client: Client<AppContext>, workflow: WorkflowVersion<Input, Output, AppContext, TEvents>, ...args: Input extends void ? [] : [Input]): Promise<ScheduleHandle>;
|
|
330
333
|
};
|
|
331
|
-
declare function schedule(params:
|
|
332
|
-
name: string;
|
|
333
|
-
} & ScheduleParams): ScheduleDefinition;
|
|
334
|
+
declare function schedule(params: ScheduleParams): ScheduleDefinition;
|
|
334
335
|
|
|
335
336
|
/**
|
|
336
337
|
* Defines a durable workflow with versioning and multiple task execution.
|
package/dist/index.js
CHANGED
|
@@ -77,6 +77,9 @@ function delay(ms, options) {
|
|
|
77
77
|
});
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
// ../../lib/crypto/hash.ts
|
|
81
|
+
import { createHash } from "crypto";
|
|
82
|
+
|
|
80
83
|
// ../../lib/json/stable-stringify.ts
|
|
81
84
|
function stableStringify(value) {
|
|
82
85
|
return stringifyValue(value);
|
|
@@ -292,8 +295,8 @@ function getRetryParams(attempts, strategy) {
|
|
|
292
295
|
import { INTERNAL } from "@aikirun/types/symbols";
|
|
293
296
|
import { SchemaValidationError } from "@aikirun/types/validator";
|
|
294
297
|
import {
|
|
295
|
-
WorkflowRunConflictError,
|
|
296
298
|
WorkflowRunFailedError,
|
|
299
|
+
WorkflowRunRevisionConflictError,
|
|
297
300
|
WorkflowRunSuspendedError
|
|
298
301
|
} from "@aikirun/types/workflow-run";
|
|
299
302
|
function event(params) {
|
|
@@ -320,17 +323,17 @@ function createEventWaiter(handle, eventName, schema, logger) {
|
|
|
320
323
|
let nextEventIndex = 0;
|
|
321
324
|
async function wait(options) {
|
|
322
325
|
await handle.refresh();
|
|
323
|
-
const
|
|
324
|
-
const
|
|
325
|
-
if (
|
|
326
|
+
const eventWaits = handle.run.eventWaitQueues[eventName]?.eventWaits ?? [];
|
|
327
|
+
const eventWait = eventWaits[nextEventIndex];
|
|
328
|
+
if (eventWait) {
|
|
326
329
|
nextEventIndex++;
|
|
327
|
-
if (
|
|
330
|
+
if (eventWait.status === "timeout") {
|
|
328
331
|
logger.debug("Timed out waiting for event");
|
|
329
332
|
return { timeout: true };
|
|
330
333
|
}
|
|
331
|
-
let data =
|
|
334
|
+
let data = eventWait.data;
|
|
332
335
|
if (schema) {
|
|
333
|
-
const schemaValidation = schema["~standard"].validate(
|
|
336
|
+
const schemaValidation = schema["~standard"].validate(eventWait.data);
|
|
334
337
|
const schemaValidationResult = schemaValidation instanceof Promise ? await schemaValidation : schemaValidation;
|
|
335
338
|
if (!schemaValidationResult.issues) {
|
|
336
339
|
data = schemaValidationResult.value;
|
|
@@ -361,7 +364,7 @@ function createEventWaiter(handle, eventName, schema, logger) {
|
|
|
361
364
|
...timeoutInMs !== void 0 ? { "aiki.timeoutInMs": timeoutInMs } : {}
|
|
362
365
|
});
|
|
363
366
|
} catch (error) {
|
|
364
|
-
if (error instanceof
|
|
367
|
+
if (error instanceof WorkflowRunRevisionConflictError) {
|
|
365
368
|
throw new WorkflowRunSuspendedError(handle.run.id);
|
|
366
369
|
}
|
|
367
370
|
throw error;
|
|
@@ -485,8 +488,8 @@ function createEventMulticaster(workflowName, workflowVersionId, eventName, sche
|
|
|
485
488
|
import { INTERNAL as INTERNAL2 } from "@aikirun/types/symbols";
|
|
486
489
|
import {
|
|
487
490
|
isTerminalWorkflowRunStatus,
|
|
488
|
-
|
|
489
|
-
|
|
491
|
+
WorkflowRunNotExecutableError,
|
|
492
|
+
WorkflowRunRevisionConflictError as WorkflowRunRevisionConflictError2
|
|
490
493
|
} from "@aikirun/types/workflow-run";
|
|
491
494
|
async function workflowRunHandle(client, runOrId, eventsDefinition, logger) {
|
|
492
495
|
const run = typeof runOrId !== "string" ? runOrId : (await client.api.workflowRun.getByIdV1({ id: runOrId })).run;
|
|
@@ -622,7 +625,7 @@ var WorkflowRunHandleImpl = class {
|
|
|
622
625
|
this._run = run;
|
|
623
626
|
} catch (error) {
|
|
624
627
|
if (isConflictError(error)) {
|
|
625
|
-
throw new
|
|
628
|
+
throw new WorkflowRunRevisionConflictError2(this.run.id);
|
|
626
629
|
}
|
|
627
630
|
throw error;
|
|
628
631
|
}
|
|
@@ -638,7 +641,7 @@ var WorkflowRunHandleImpl = class {
|
|
|
638
641
|
return { taskId };
|
|
639
642
|
} catch (error) {
|
|
640
643
|
if (isConflictError(error)) {
|
|
641
|
-
throw new
|
|
644
|
+
throw new WorkflowRunRevisionConflictError2(this.run.id);
|
|
642
645
|
}
|
|
643
646
|
throw error;
|
|
644
647
|
}
|
|
@@ -656,7 +659,10 @@ function isConflictError(error) {
|
|
|
656
659
|
|
|
657
660
|
// run/sleeper.ts
|
|
658
661
|
import { INTERNAL as INTERNAL3 } from "@aikirun/types/symbols";
|
|
659
|
-
import {
|
|
662
|
+
import {
|
|
663
|
+
WorkflowRunRevisionConflictError as WorkflowRunRevisionConflictError3,
|
|
664
|
+
WorkflowRunSuspendedError as WorkflowRunSuspendedError2
|
|
665
|
+
} from "@aikirun/types/workflow-run";
|
|
660
666
|
var MAX_SLEEP_YEARS = 10;
|
|
661
667
|
var MAX_SLEEP_MS = MAX_SLEEP_YEARS * 365 * 24 * 60 * 60 * 1e3;
|
|
662
668
|
function createSleeper(handle, logger) {
|
|
@@ -678,7 +684,7 @@ function createSleeper(handle, logger) {
|
|
|
678
684
|
"aiki.durationMs": durationMs
|
|
679
685
|
});
|
|
680
686
|
} catch (error) {
|
|
681
|
-
if (error instanceof
|
|
687
|
+
if (error instanceof WorkflowRunRevisionConflictError3) {
|
|
682
688
|
throw new WorkflowRunSuspendedError2(handle.run.id);
|
|
683
689
|
}
|
|
684
690
|
throw error;
|
|
@@ -726,7 +732,7 @@ function createSleeper(handle, logger) {
|
|
|
726
732
|
"aiki.durationMs": durationMs
|
|
727
733
|
});
|
|
728
734
|
} catch (error) {
|
|
729
|
-
if (error instanceof
|
|
735
|
+
if (error instanceof WorkflowRunRevisionConflictError3) {
|
|
730
736
|
throw new WorkflowRunSuspendedError2(handle.run.id);
|
|
731
737
|
}
|
|
732
738
|
throw error;
|
|
@@ -737,48 +743,61 @@ function createSleeper(handle, logger) {
|
|
|
737
743
|
|
|
738
744
|
// schedule.ts
|
|
739
745
|
function schedule(params) {
|
|
740
|
-
|
|
746
|
+
async function activateWithOpts(client, workflow2, options, ...args) {
|
|
747
|
+
const input = args[0];
|
|
748
|
+
let scheduleSpec;
|
|
749
|
+
if (params.type === "interval") {
|
|
750
|
+
const { every, ...rest } = params;
|
|
751
|
+
scheduleSpec = {
|
|
752
|
+
...rest,
|
|
753
|
+
everyMs: toMilliseconds(every)
|
|
754
|
+
};
|
|
755
|
+
} else {
|
|
756
|
+
scheduleSpec = params;
|
|
757
|
+
}
|
|
758
|
+
const { schedule: schedule2 } = await client.api.schedule.activateV1({
|
|
759
|
+
workflowName: workflow2.name,
|
|
760
|
+
workflowVersionId: workflow2.versionId,
|
|
761
|
+
spec: scheduleSpec,
|
|
762
|
+
input,
|
|
763
|
+
options
|
|
764
|
+
});
|
|
765
|
+
client.logger.info("Schedule activated", {
|
|
766
|
+
scheduleSpec,
|
|
767
|
+
workflowName: workflow2.name,
|
|
768
|
+
workflowVersionId: workflow2.versionId,
|
|
769
|
+
referenceId: options?.reference?.id
|
|
770
|
+
});
|
|
771
|
+
const scheduleId = schedule2.id;
|
|
772
|
+
return {
|
|
773
|
+
id: scheduleId,
|
|
774
|
+
pause: async () => {
|
|
775
|
+
await client.api.schedule.pauseV1({ id: scheduleId });
|
|
776
|
+
},
|
|
777
|
+
resume: async () => {
|
|
778
|
+
await client.api.schedule.resumeV1({ id: scheduleId });
|
|
779
|
+
},
|
|
780
|
+
delete: async () => {
|
|
781
|
+
await client.api.schedule.deleteV1({ id: scheduleId });
|
|
782
|
+
}
|
|
783
|
+
};
|
|
784
|
+
}
|
|
785
|
+
function createBuilder(optsBuilder) {
|
|
786
|
+
return {
|
|
787
|
+
opt: (path, value) => createBuilder(optsBuilder.with(path, value)),
|
|
788
|
+
async activate(client, workflow2, ...args) {
|
|
789
|
+
return activateWithOpts(client, workflow2, optsBuilder.build(), ...args);
|
|
790
|
+
}
|
|
791
|
+
};
|
|
792
|
+
}
|
|
741
793
|
return {
|
|
742
|
-
|
|
743
|
-
|
|
794
|
+
...params,
|
|
795
|
+
with() {
|
|
796
|
+
const optsOverrider = objectOverrider({});
|
|
797
|
+
return createBuilder(optsOverrider());
|
|
798
|
+
},
|
|
744
799
|
async activate(client, workflow2, ...args) {
|
|
745
|
-
|
|
746
|
-
let scheduleSpec;
|
|
747
|
-
if (scheduleParams.type === "interval") {
|
|
748
|
-
const { every, ...rest } = scheduleParams;
|
|
749
|
-
scheduleSpec = {
|
|
750
|
-
...rest,
|
|
751
|
-
everyMs: toMilliseconds(every)
|
|
752
|
-
};
|
|
753
|
-
} else {
|
|
754
|
-
scheduleSpec = scheduleParams;
|
|
755
|
-
}
|
|
756
|
-
const { schedule: schedule2 } = await client.api.schedule.activateV1({
|
|
757
|
-
name,
|
|
758
|
-
workflowName: workflow2.name,
|
|
759
|
-
workflowVersionId: workflow2.versionId,
|
|
760
|
-
spec: scheduleSpec,
|
|
761
|
-
input
|
|
762
|
-
});
|
|
763
|
-
client.logger.info("Schedule activated", {
|
|
764
|
-
scheduleSpec,
|
|
765
|
-
workflowName: workflow2.name,
|
|
766
|
-
workflowVersionId: workflow2.versionId
|
|
767
|
-
});
|
|
768
|
-
const scheduleId = schedule2.id;
|
|
769
|
-
return {
|
|
770
|
-
id: scheduleId,
|
|
771
|
-
name,
|
|
772
|
-
pause: async () => {
|
|
773
|
-
await client.api.schedule.pauseV1({ id: scheduleId });
|
|
774
|
-
},
|
|
775
|
-
resume: async () => {
|
|
776
|
-
await client.api.schedule.resumeV1({ id: scheduleId });
|
|
777
|
-
},
|
|
778
|
-
delete: async () => {
|
|
779
|
-
await client.api.schedule.deleteV1({ id: scheduleId });
|
|
780
|
-
}
|
|
781
|
-
};
|
|
800
|
+
return activateWithOpts(client, workflow2, {}, ...args);
|
|
782
801
|
}
|
|
783
802
|
};
|
|
784
803
|
}
|
|
@@ -788,7 +807,7 @@ import { INTERNAL as INTERNAL6 } from "@aikirun/types/symbols";
|
|
|
788
807
|
|
|
789
808
|
// ../../lib/address/index.ts
|
|
790
809
|
function getWorkflowRunAddress(name, versionId, referenceId) {
|
|
791
|
-
return `${name}
|
|
810
|
+
return `${name}:${versionId}:${referenceId}`;
|
|
792
811
|
}
|
|
793
812
|
|
|
794
813
|
// workflow-version.ts
|
|
@@ -796,8 +815,8 @@ import { INTERNAL as INTERNAL5 } from "@aikirun/types/symbols";
|
|
|
796
815
|
import { TaskFailedError } from "@aikirun/types/task";
|
|
797
816
|
import { SchemaValidationError as SchemaValidationError2 } from "@aikirun/types/validator";
|
|
798
817
|
import {
|
|
799
|
-
WorkflowRunConflictError as WorkflowRunConflictError5,
|
|
800
818
|
WorkflowRunFailedError as WorkflowRunFailedError2,
|
|
819
|
+
WorkflowRunRevisionConflictError as WorkflowRunRevisionConflictError5,
|
|
801
820
|
WorkflowRunSuspendedError as WorkflowRunSuspendedError4
|
|
802
821
|
} from "@aikirun/types/workflow-run";
|
|
803
822
|
|
|
@@ -805,7 +824,7 @@ import {
|
|
|
805
824
|
import { INTERNAL as INTERNAL4 } from "@aikirun/types/symbols";
|
|
806
825
|
import {
|
|
807
826
|
isTerminalWorkflowRunStatus as isTerminalWorkflowRunStatus2,
|
|
808
|
-
|
|
827
|
+
WorkflowRunRevisionConflictError as WorkflowRunRevisionConflictError4,
|
|
809
828
|
WorkflowRunSuspendedError as WorkflowRunSuspendedError3
|
|
810
829
|
} from "@aikirun/types/workflow-run";
|
|
811
830
|
async function childWorkflowRunHandle(client, run, parentRun, logger, eventsDefinition) {
|
|
@@ -884,7 +903,7 @@ function createStatusWaiter(handle, parentRun, logger) {
|
|
|
884
903
|
...timeoutInMs !== void 0 ? { "aiki.timeoutInMs": timeoutInMs } : {}
|
|
885
904
|
});
|
|
886
905
|
} catch (error) {
|
|
887
|
-
if (error instanceof
|
|
906
|
+
if (error instanceof WorkflowRunRevisionConflictError4) {
|
|
888
907
|
throw new WorkflowRunSuspendedError3(parentRun.id);
|
|
889
908
|
}
|
|
890
909
|
throw error;
|
|
@@ -1065,7 +1084,7 @@ var WorkflowVersionImpl = class {
|
|
|
1065
1084
|
const output = await this.parse(handle, this.params.schema?.output, outputRaw, run.logger);
|
|
1066
1085
|
return output;
|
|
1067
1086
|
} catch (error) {
|
|
1068
|
-
if (error instanceof WorkflowRunSuspendedError4 || error instanceof WorkflowRunFailedError2 || error instanceof
|
|
1087
|
+
if (error instanceof WorkflowRunSuspendedError4 || error instanceof WorkflowRunFailedError2 || error instanceof WorkflowRunRevisionConflictError5) {
|
|
1069
1088
|
throw error;
|
|
1070
1089
|
}
|
|
1071
1090
|
const attempts = handle.run.attempts;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aikirun/workflow",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.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.17.0",
|
|
22
22
|
"@standard-schema/spec": "^1.1.0"
|
|
23
23
|
},
|
|
24
24
|
"publishConfig": {
|