@smithers-orchestrator/scheduler 0.24.0 → 0.24.2
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/package.json +3 -3
- package/src/WorkflowSessionOptions.ts +28 -0
- package/src/index.d.ts +9 -0
- package/src/makeWorkflowSession.js +22 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@smithers-orchestrator/scheduler",
|
|
3
|
-
"version": "0.24.
|
|
3
|
+
"version": "0.24.2",
|
|
4
4
|
"description": "Pure decision engine: session, scheduler, and task state management for Smithers workflows",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -176,8 +176,8 @@
|
|
|
176
176
|
],
|
|
177
177
|
"dependencies": {
|
|
178
178
|
"effect": "^3.21.1",
|
|
179
|
-
"@smithers-orchestrator/errors": "0.24.
|
|
180
|
-
"@smithers-orchestrator/graph": "0.24.
|
|
179
|
+
"@smithers-orchestrator/errors": "0.24.2",
|
|
180
|
+
"@smithers-orchestrator/graph": "0.24.2"
|
|
181
181
|
},
|
|
182
182
|
"devDependencies": {
|
|
183
183
|
"@types/bun": "latest",
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
import type { TaskDescriptor } from "@smithers-orchestrator/graph/TaskDescriptor";
|
|
2
|
+
|
|
3
|
+
/** A breached Aspects budget for a task that is about to be dispatched. */
|
|
4
|
+
export type AspectBudgetBreach = {
|
|
5
|
+
readonly kind: "tokens" | "latency";
|
|
6
|
+
readonly limit: number;
|
|
7
|
+
readonly current: number;
|
|
8
|
+
readonly onExceeded: "fail" | "warn" | "skip-remaining";
|
|
9
|
+
};
|
|
10
|
+
|
|
1
11
|
export type WorkflowSessionOptions = {
|
|
2
12
|
readonly runId?: string;
|
|
3
13
|
readonly nowMs?: () => number;
|
|
@@ -7,4 +17,22 @@ export type WorkflowSessionOptions = {
|
|
|
7
17
|
readonly iteration: number;
|
|
8
18
|
readonly done: boolean;
|
|
9
19
|
}>;
|
|
20
|
+
/**
|
|
21
|
+
* Evaluate a runnable task's Aspects budgets against the run's accumulated
|
|
22
|
+
* usage. Return the first breach, or `null`/`undefined` when within budget.
|
|
23
|
+
* Only invoked for tasks that would otherwise execute.
|
|
24
|
+
*/
|
|
25
|
+
readonly evaluateAspectBudget?: (
|
|
26
|
+
descriptor: TaskDescriptor,
|
|
27
|
+
) => AspectBudgetBreach | null | undefined;
|
|
28
|
+
/** Called when a task is skipped because its budget was exceeded (`skip-remaining`). */
|
|
29
|
+
readonly onAspectBudgetSkip?: (
|
|
30
|
+
descriptor: TaskDescriptor,
|
|
31
|
+
breach: AspectBudgetBreach,
|
|
32
|
+
) => void;
|
|
33
|
+
/** Called when a task continues despite an exceeded budget (`warn`). */
|
|
34
|
+
readonly onAspectBudgetWarn?: (
|
|
35
|
+
descriptor: TaskDescriptor,
|
|
36
|
+
breach: AspectBudgetBreach,
|
|
37
|
+
) => void;
|
|
10
38
|
};
|
package/src/index.d.ts
CHANGED
|
@@ -199,6 +199,12 @@ type WorkflowSessionService$2 = {
|
|
|
199
199
|
readonly getCurrentGraph: () => Effect.Effect<WorkflowGraph | null>;
|
|
200
200
|
};
|
|
201
201
|
|
|
202
|
+
type AspectBudgetBreach$1 = {
|
|
203
|
+
readonly kind: "tokens" | "latency";
|
|
204
|
+
readonly limit: number;
|
|
205
|
+
readonly current: number;
|
|
206
|
+
readonly onExceeded: "fail" | "warn" | "skip-remaining";
|
|
207
|
+
};
|
|
202
208
|
type WorkflowSessionOptions$2 = {
|
|
203
209
|
readonly runId?: string;
|
|
204
210
|
readonly nowMs?: () => number;
|
|
@@ -208,6 +214,9 @@ type WorkflowSessionOptions$2 = {
|
|
|
208
214
|
readonly iteration: number;
|
|
209
215
|
readonly done: boolean;
|
|
210
216
|
}>;
|
|
217
|
+
readonly evaluateAspectBudget?: (descriptor: TaskDescriptor$3) => AspectBudgetBreach$1 | null | undefined;
|
|
218
|
+
readonly onAspectBudgetSkip?: (descriptor: TaskDescriptor$3, breach: AspectBudgetBreach$1) => void;
|
|
219
|
+
readonly onAspectBudgetWarn?: (descriptor: TaskDescriptor$3, breach: AspectBudgetBreach$1) => void;
|
|
211
220
|
};
|
|
212
221
|
|
|
213
222
|
type TaskRecord$1 = {
|
|
@@ -530,6 +530,28 @@ export function makeWorkflowSession(options = {}) {
|
|
|
530
530
|
changed = true;
|
|
531
531
|
continue;
|
|
532
532
|
}
|
|
533
|
+
const budgetBreach = options.evaluateAspectBudget?.(task);
|
|
534
|
+
if (budgetBreach) {
|
|
535
|
+
if (budgetBreach.onExceeded === "skip-remaining") {
|
|
536
|
+
options.onAspectBudgetSkip?.(task, budgetBreach);
|
|
537
|
+
state.states.set(key, "skipped");
|
|
538
|
+
changed = true;
|
|
539
|
+
continue;
|
|
540
|
+
}
|
|
541
|
+
if (budgetBreach.onExceeded === "warn") {
|
|
542
|
+
options.onAspectBudgetWarn?.(task, budgetBreach);
|
|
543
|
+
}
|
|
544
|
+
else {
|
|
545
|
+
return {
|
|
546
|
+
_tag: "Failed",
|
|
547
|
+
error: new SmithersError("ASPECT_BUDGET_EXCEEDED", `Aspects ${budgetBreach.kind} budget exceeded for task "${task.nodeId}": ${budgetBreach.current} >= ${budgetBreach.limit}`, {
|
|
548
|
+
kind: budgetBreach.kind,
|
|
549
|
+
limit: budgetBreach.limit,
|
|
550
|
+
current: budgetBreach.current,
|
|
551
|
+
}),
|
|
552
|
+
};
|
|
553
|
+
}
|
|
554
|
+
}
|
|
533
555
|
state.states.set(key, "in-progress");
|
|
534
556
|
executable.push(task);
|
|
535
557
|
changed = true;
|