@voyantjs/workflows-orchestrator 0.38.0 → 0.38.1
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/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/orchestrator.d.ts +7 -0
- package/dist/orchestrator.d.ts.map +1 -1
- package/dist/orchestrator.js +1 -1
- package/dist/resume-run.d.ts +23 -0
- package/dist/resume-run.d.ts.map +1 -0
- package/dist/resume-run.js +65 -0
- package/package.json +2 -2
- package/src/index.ts +7 -0
- package/src/orchestrator.ts +8 -1
- package/src/resume-run.ts +103 -0
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export { createHttpStepHandler, type HttpStepHandlerDeps, type HttpStepTarget, }
|
|
|
7
7
|
export { createInMemoryRunStore } from "./in-memory-store.js";
|
|
8
8
|
export { emptyJournal } from "./journal-helpers.js";
|
|
9
9
|
export { type CancelArgs, cancel, type OrchestratorDeps, type ResumeArgs, type ResumeDueAlarmsArgs, resume, resumeDueAlarms, type TriggerArgs, trigger, } from "./orchestrator.js";
|
|
10
|
+
export { type BuildResumeJournalInput, type BuildResumeJournalResult, type BuildSeededResumeJournalInput, buildResumeJournal, buildSeededResumeJournal, } from "./resume-run.js";
|
|
10
11
|
export { type CronSpec, computeNextFire, createScheduler, manifestScheduleSources, nextCronFire, parseCron, type SchedulableDeclaration, type SchedulerDeps, type SchedulerHandle, type ScheduleSource, toMs, } from "./schedule.js";
|
|
11
12
|
export * from "./types.js";
|
|
12
13
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAWA,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,kBAAkB,GACnB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACL,KAAK,mBAAmB,EACxB,qCAAqC,EACrC,KAAK,+BAA+B,EACpC,KAAK,wBAAwB,EAC7B,qBAAqB,EACrB,gCAAgC,GACjC,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,uBAAuB,EAAE,KAAK,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AACzF,OAAO,EACL,oBAAoB,EACpB,KAAK,qBAAqB,GAC3B,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,UAAU,GACX,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACL,qBAAqB,EACrB,KAAK,mBAAmB,EACxB,KAAK,cAAc,GACpB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAA;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACnD,OAAO,EACL,KAAK,UAAU,EACf,MAAM,EACN,KAAK,gBAAgB,EACrB,KAAK,UAAU,EACf,KAAK,mBAAmB,EACxB,MAAM,EACN,eAAe,EACf,KAAK,WAAW,EAChB,OAAO,GACR,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACL,KAAK,QAAQ,EACb,eAAe,EACf,eAAe,EACf,uBAAuB,EACvB,YAAY,EACZ,SAAS,EACT,KAAK,sBAAsB,EAC3B,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,IAAI,GACL,MAAM,eAAe,CAAA;AACtB,cAAc,YAAY,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAWA,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,kBAAkB,GACnB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACL,KAAK,mBAAmB,EACxB,qCAAqC,EACrC,KAAK,+BAA+B,EACpC,KAAK,wBAAwB,EAC7B,qBAAqB,EACrB,gCAAgC,GACjC,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,uBAAuB,EAAE,KAAK,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AACzF,OAAO,EACL,oBAAoB,EACpB,KAAK,qBAAqB,GAC3B,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,UAAU,GACX,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACL,qBAAqB,EACrB,KAAK,mBAAmB,EACxB,KAAK,cAAc,GACpB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAA;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACnD,OAAO,EACL,KAAK,UAAU,EACf,MAAM,EACN,KAAK,gBAAgB,EACrB,KAAK,UAAU,EACf,KAAK,mBAAmB,EACxB,MAAM,EACN,eAAe,EACf,KAAK,WAAW,EAChB,OAAO,GACR,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACL,KAAK,uBAAuB,EAC5B,KAAK,wBAAwB,EAC7B,KAAK,6BAA6B,EAClC,kBAAkB,EAClB,wBAAwB,GACzB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,KAAK,QAAQ,EACb,eAAe,EACf,eAAe,EACf,uBAAuB,EACvB,YAAY,EACZ,SAAS,EACT,KAAK,sBAAsB,EAC3B,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,IAAI,GACL,MAAM,eAAe,CAAA;AACtB,cAAc,YAAY,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -17,5 +17,6 @@ export { createHttpStepHandler, } from "./http-step-handler.js";
|
|
|
17
17
|
export { createInMemoryRunStore } from "./in-memory-store.js";
|
|
18
18
|
export { emptyJournal } from "./journal-helpers.js";
|
|
19
19
|
export { cancel, resume, resumeDueAlarms, trigger, } from "./orchestrator.js";
|
|
20
|
+
export { buildResumeJournal, buildSeededResumeJournal, } from "./resume-run.js";
|
|
20
21
|
export { computeNextFire, createScheduler, manifestScheduleSources, nextCronFire, parseCron, toMs, } from "./schedule.js";
|
|
21
22
|
export * from "./types.js";
|
package/dist/orchestrator.d.ts
CHANGED
|
@@ -38,6 +38,13 @@ export interface TriggerArgs {
|
|
|
38
38
|
* run.
|
|
39
39
|
*/
|
|
40
40
|
initialJournal?: JournalSlice;
|
|
41
|
+
/**
|
|
42
|
+
* Metadata cursor paired with `initialJournal`. Resume callers that
|
|
43
|
+
* seed a journal with an existing `metadataState` must also seed the
|
|
44
|
+
* positional cursor so replayed metadata mutations are not applied
|
|
45
|
+
* twice.
|
|
46
|
+
*/
|
|
47
|
+
initialMetadataAppliedCount?: number;
|
|
41
48
|
/**
|
|
42
49
|
* Compute-time budget in ms, typically from `WorkflowConfig.timeout`.
|
|
43
50
|
* Parked time on waitpoints does not count against this. When the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../src/orchestrator.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAGnD,OAAO,EAA2B,KAAK,YAAY,EAAoB,MAAM,YAAY,CAAA;AAEzF,OAAO,KAAK,EACV,YAAY,EACZ,SAAS,EACT,cAAc,EACd,UAAU,EACV,WAAW,EACX,kBAAkB,EACnB,MAAM,YAAY,CAAA;AAEnB,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAA;IAClB,eAAe,EAAE,MAAM,CAAA;IACvB,KAAK,EAAE,OAAO,CAAA;IACd,UAAU,EAAE,SAAS,CAAC,YAAY,CAAC,CAAA;IACnC,WAAW,CAAC,EAAE,SAAS,CAAC,aAAa,CAAC,CAAA;IACtC,WAAW,CAAC,EAAE,UAAU,CAAA;IACxB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,8DAA8D;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;;;;;;;;OAUG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;;;;OAIG;IACH,KAAK,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAA;IACvB,sEAAsE;IACtE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;OAIG;IACH,cAAc,CAAC,EAAE,YAAY,CAAA;IAC7B;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAA;IAC/C;;;OAGG;IACH,kBAAkB,CAAC,EAAE,CAAC,MAAM,EAAE,SAAS,KAAK,IAAI,CAAA;CACjD;AAED,MAAM,WAAW,gBAAiB,SAAQ,YAAY;IACpD,KAAK,EAAE,cAAc,CAAA;IACrB,OAAO,EAAE,WAAW,CAAA;IACpB,gDAAgD;IAChD,WAAW,CAAC,EAAE,MAAM,MAAM,CAAA;CAC3B;AAED,wBAAsB,OAAO,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,SAAS,CAAC,CA6F3F;AA8FD,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,kBAAkB,CAAA;CAC9B;AAED,wBAAsB,MAAM,CAC1B,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,gBAAgB,GACrB,OAAO,CACN;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,SAAS,CAAA;CAAE,GAC/B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,WAAW,GAAG,YAAY,GAAG,UAAU,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAClF,CA0CA;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAA;CACd;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,mBAAmB,EACzB,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAsC3B;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,wBAAsB,MAAM,CAC1B,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,gBAAgB,GACrB,OAAO,CACN;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,SAAS,CAAA;CAAE,GAC/B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,WAAW,GAAG,kBAAkB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAC3E,CAqCA"}
|
|
1
|
+
{"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../src/orchestrator.ts"],"names":[],"mappings":"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"}
|
package/dist/orchestrator.js
CHANGED
|
@@ -32,7 +32,7 @@ export async function trigger(args, deps) {
|
|
|
32
32
|
input: args.input,
|
|
33
33
|
journal: args.initialJournal ? cloneJournal(args.initialJournal) : emptyJournal(),
|
|
34
34
|
invocationCount: 0,
|
|
35
|
-
metadataAppliedCount: 0,
|
|
35
|
+
metadataAppliedCount: args.initialMetadataAppliedCount ?? 0,
|
|
36
36
|
computeTimeMs: 0,
|
|
37
37
|
timeoutMs: args.timeoutMs,
|
|
38
38
|
priority: args.priority,
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { JournalSlice, RunRecord } from "./types.js";
|
|
2
|
+
export interface BuildResumeJournalInput {
|
|
3
|
+
parent: RunRecord;
|
|
4
|
+
resumeFromStep?: string;
|
|
5
|
+
seedResults?: Record<string, unknown>;
|
|
6
|
+
now?: () => number;
|
|
7
|
+
}
|
|
8
|
+
export interface BuildResumeJournalResult {
|
|
9
|
+
resumeFromStep: string;
|
|
10
|
+
journal: JournalSlice;
|
|
11
|
+
metadataAppliedCount: number;
|
|
12
|
+
}
|
|
13
|
+
export interface BuildSeededResumeJournalInput {
|
|
14
|
+
parentRunId: string;
|
|
15
|
+
resumeFromStep: string;
|
|
16
|
+
seedResults: Record<string, unknown>;
|
|
17
|
+
metadataState?: Record<string, unknown>;
|
|
18
|
+
metadataAppliedCount?: number;
|
|
19
|
+
now?: () => number;
|
|
20
|
+
}
|
|
21
|
+
export declare function buildResumeJournal(input: BuildResumeJournalInput): BuildResumeJournalResult;
|
|
22
|
+
export declare function buildSeededResumeJournal(input: BuildSeededResumeJournalInput): BuildResumeJournalResult;
|
|
23
|
+
//# sourceMappingURL=resume-run.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resume-run.d.ts","sourceRoot":"","sources":["../src/resume-run.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAoB,MAAM,YAAY,CAAA;AAE3E,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,SAAS,CAAA;IACjB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACrC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,wBAAwB;IACvC,cAAc,EAAE,MAAM,CAAA;IACtB,OAAO,EAAE,YAAY,CAAA;IACrB,oBAAoB,EAAE,MAAM,CAAA;CAC7B;AAED,MAAM,WAAW,6BAA6B;IAC5C,WAAW,EAAE,MAAM,CAAA;IACnB,cAAc,EAAE,MAAM,CAAA;IACtB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACpC,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACvC,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;CACnB;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,uBAAuB,GAAG,wBAAwB,CAwC3F;AAED,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,6BAA6B,GACnC,wBAAwB,CAgB1B"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { emptyJournal } from "./journal-helpers.js";
|
|
2
|
+
export function buildResumeJournal(input) {
|
|
3
|
+
const resumeFromStep = input.resumeFromStep ?? findFirstFailedStep(input.parent);
|
|
4
|
+
if (!resumeFromStep) {
|
|
5
|
+
throw new Error(`run "${input.parent.id}" has no failed step; pass resumeFromStep explicitly to resume it`);
|
|
6
|
+
}
|
|
7
|
+
const journal = emptyJournal();
|
|
8
|
+
journal.metadataState = structuredClone(input.parent.journal.metadataState);
|
|
9
|
+
if (input.seedResults) {
|
|
10
|
+
return buildSeededResumeJournal({
|
|
11
|
+
parentRunId: input.parent.id,
|
|
12
|
+
resumeFromStep,
|
|
13
|
+
seedResults: input.seedResults,
|
|
14
|
+
metadataState: journal.metadataState,
|
|
15
|
+
metadataAppliedCount: input.parent.metadataAppliedCount,
|
|
16
|
+
now: input.now,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
for (const [stepId, entry] of Object.entries(input.parent.journal.stepResults)) {
|
|
20
|
+
if (stepId === resumeFromStep)
|
|
21
|
+
break;
|
|
22
|
+
if (entry.status !== "ok") {
|
|
23
|
+
throw new Error(`step "${stepId}" completed before "${resumeFromStep}" but is not successful; cannot seed resume journal`);
|
|
24
|
+
}
|
|
25
|
+
journal.stepResults[stepId] = structuredClone(entry);
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
resumeFromStep,
|
|
29
|
+
journal,
|
|
30
|
+
metadataAppliedCount: input.parent.metadataAppliedCount,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export function buildSeededResumeJournal(input) {
|
|
34
|
+
const journal = emptyJournal();
|
|
35
|
+
journal.metadataState = input.metadataState
|
|
36
|
+
? structuredClone(input.metadataState)
|
|
37
|
+
: {};
|
|
38
|
+
const now = input.now ?? (() => Date.now());
|
|
39
|
+
let at = now();
|
|
40
|
+
for (const [stepId, output] of Object.entries(input.seedResults)) {
|
|
41
|
+
journal.stepResults[stepId] = seededStepEntry(output, at);
|
|
42
|
+
at += 1;
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
resumeFromStep: input.resumeFromStep,
|
|
46
|
+
journal,
|
|
47
|
+
metadataAppliedCount: input.metadataAppliedCount ?? 0,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function findFirstFailedStep(parent) {
|
|
51
|
+
for (const [stepId, entry] of Object.entries(parent.journal.stepResults)) {
|
|
52
|
+
if (entry.status === "err")
|
|
53
|
+
return stepId;
|
|
54
|
+
}
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
function seededStepEntry(output, at) {
|
|
58
|
+
return {
|
|
59
|
+
attempt: 1,
|
|
60
|
+
status: "ok",
|
|
61
|
+
output,
|
|
62
|
+
startedAt: at,
|
|
63
|
+
finishedAt: at,
|
|
64
|
+
};
|
|
65
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voyantjs/workflows-orchestrator",
|
|
3
|
-
"version": "0.38.
|
|
3
|
+
"version": "0.38.1",
|
|
4
4
|
"description": "Reference orchestrator core for Voyant Workflows — drives runs through the tenant step handler over the v1 wire protocol.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"NOTICE"
|
|
31
31
|
],
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@voyantjs/workflows": "0.38.
|
|
33
|
+
"@voyantjs/workflows": "0.38.1"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@types/node": "^20.12.0",
|
package/src/index.ts
CHANGED
|
@@ -50,6 +50,13 @@ export {
|
|
|
50
50
|
type TriggerArgs,
|
|
51
51
|
trigger,
|
|
52
52
|
} from "./orchestrator.js"
|
|
53
|
+
export {
|
|
54
|
+
type BuildResumeJournalInput,
|
|
55
|
+
type BuildResumeJournalResult,
|
|
56
|
+
type BuildSeededResumeJournalInput,
|
|
57
|
+
buildResumeJournal,
|
|
58
|
+
buildSeededResumeJournal,
|
|
59
|
+
} from "./resume-run.js"
|
|
53
60
|
export {
|
|
54
61
|
type CronSpec,
|
|
55
62
|
computeNextFire,
|
package/src/orchestrator.ts
CHANGED
|
@@ -58,6 +58,13 @@ export interface TriggerArgs {
|
|
|
58
58
|
* run.
|
|
59
59
|
*/
|
|
60
60
|
initialJournal?: JournalSlice
|
|
61
|
+
/**
|
|
62
|
+
* Metadata cursor paired with `initialJournal`. Resume callers that
|
|
63
|
+
* seed a journal with an existing `metadataState` must also seed the
|
|
64
|
+
* positional cursor so replayed metadata mutations are not applied
|
|
65
|
+
* twice.
|
|
66
|
+
*/
|
|
67
|
+
initialMetadataAppliedCount?: number
|
|
61
68
|
/**
|
|
62
69
|
* Compute-time budget in ms, typically from `WorkflowConfig.timeout`.
|
|
63
70
|
* Parked time on waitpoints does not count against this. When the
|
|
@@ -109,7 +116,7 @@ export async function trigger(args: TriggerArgs, deps: OrchestratorDeps): Promis
|
|
|
109
116
|
input: args.input,
|
|
110
117
|
journal: args.initialJournal ? cloneJournal(args.initialJournal) : emptyJournal(),
|
|
111
118
|
invocationCount: 0,
|
|
112
|
-
metadataAppliedCount: 0,
|
|
119
|
+
metadataAppliedCount: args.initialMetadataAppliedCount ?? 0,
|
|
113
120
|
computeTimeMs: 0,
|
|
114
121
|
timeoutMs: args.timeoutMs,
|
|
115
122
|
priority: args.priority,
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { emptyJournal } from "./journal-helpers.js"
|
|
2
|
+
import type { JournalSlice, RunRecord, StepJournalEntry } from "./types.js"
|
|
3
|
+
|
|
4
|
+
export interface BuildResumeJournalInput {
|
|
5
|
+
parent: RunRecord
|
|
6
|
+
resumeFromStep?: string
|
|
7
|
+
seedResults?: Record<string, unknown>
|
|
8
|
+
now?: () => number
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface BuildResumeJournalResult {
|
|
12
|
+
resumeFromStep: string
|
|
13
|
+
journal: JournalSlice
|
|
14
|
+
metadataAppliedCount: number
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface BuildSeededResumeJournalInput {
|
|
18
|
+
parentRunId: string
|
|
19
|
+
resumeFromStep: string
|
|
20
|
+
seedResults: Record<string, unknown>
|
|
21
|
+
metadataState?: Record<string, unknown>
|
|
22
|
+
metadataAppliedCount?: number
|
|
23
|
+
now?: () => number
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function buildResumeJournal(input: BuildResumeJournalInput): BuildResumeJournalResult {
|
|
27
|
+
const resumeFromStep = input.resumeFromStep ?? findFirstFailedStep(input.parent)
|
|
28
|
+
if (!resumeFromStep) {
|
|
29
|
+
throw new Error(
|
|
30
|
+
`run "${input.parent.id}" has no failed step; pass resumeFromStep explicitly to resume it`,
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const journal = emptyJournal()
|
|
35
|
+
journal.metadataState = structuredClone(input.parent.journal.metadataState) as Record<
|
|
36
|
+
string,
|
|
37
|
+
unknown
|
|
38
|
+
>
|
|
39
|
+
|
|
40
|
+
if (input.seedResults) {
|
|
41
|
+
return buildSeededResumeJournal({
|
|
42
|
+
parentRunId: input.parent.id,
|
|
43
|
+
resumeFromStep,
|
|
44
|
+
seedResults: input.seedResults,
|
|
45
|
+
metadataState: journal.metadataState,
|
|
46
|
+
metadataAppliedCount: input.parent.metadataAppliedCount,
|
|
47
|
+
now: input.now,
|
|
48
|
+
})
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
for (const [stepId, entry] of Object.entries(input.parent.journal.stepResults)) {
|
|
52
|
+
if (stepId === resumeFromStep) break
|
|
53
|
+
if (entry.status !== "ok") {
|
|
54
|
+
throw new Error(
|
|
55
|
+
`step "${stepId}" completed before "${resumeFromStep}" but is not successful; cannot seed resume journal`,
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
journal.stepResults[stepId] = structuredClone(entry) as StepJournalEntry
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
resumeFromStep,
|
|
63
|
+
journal,
|
|
64
|
+
metadataAppliedCount: input.parent.metadataAppliedCount,
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function buildSeededResumeJournal(
|
|
69
|
+
input: BuildSeededResumeJournalInput,
|
|
70
|
+
): BuildResumeJournalResult {
|
|
71
|
+
const journal = emptyJournal()
|
|
72
|
+
journal.metadataState = input.metadataState
|
|
73
|
+
? (structuredClone(input.metadataState) as Record<string, unknown>)
|
|
74
|
+
: {}
|
|
75
|
+
const now = input.now ?? (() => Date.now())
|
|
76
|
+
let at = now()
|
|
77
|
+
for (const [stepId, output] of Object.entries(input.seedResults)) {
|
|
78
|
+
journal.stepResults[stepId] = seededStepEntry(output, at)
|
|
79
|
+
at += 1
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
resumeFromStep: input.resumeFromStep,
|
|
83
|
+
journal,
|
|
84
|
+
metadataAppliedCount: input.metadataAppliedCount ?? 0,
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function findFirstFailedStep(parent: RunRecord): string | undefined {
|
|
89
|
+
for (const [stepId, entry] of Object.entries(parent.journal.stepResults)) {
|
|
90
|
+
if (entry.status === "err") return stepId
|
|
91
|
+
}
|
|
92
|
+
return undefined
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function seededStepEntry(output: unknown, at: number): StepJournalEntry {
|
|
96
|
+
return {
|
|
97
|
+
attempt: 1,
|
|
98
|
+
status: "ok",
|
|
99
|
+
output,
|
|
100
|
+
startedAt: at,
|
|
101
|
+
finishedAt: at,
|
|
102
|
+
}
|
|
103
|
+
}
|