@yolk-sdk/harness 0.1.0-canary.100
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/LICENSE +21 -0
- package/README.md +206 -0
- package/dist/coordinator.d.mts +72 -0
- package/dist/coordinator.d.mts.map +1 -0
- package/dist/coordinator.mjs +154 -0
- package/dist/coordinator.mjs.map +1 -0
- package/dist/driver/durable-object.d.mts +20 -0
- package/dist/driver/durable-object.d.mts.map +1 -0
- package/dist/driver/durable-object.mjs +12 -0
- package/dist/driver/durable-object.mjs.map +1 -0
- package/dist/driver/memory.d.mts +21 -0
- package/dist/driver/memory.d.mts.map +1 -0
- package/dist/driver/memory.mjs +15 -0
- package/dist/driver/memory.mjs.map +1 -0
- package/dist/driver.d.mts +126 -0
- package/dist/driver.d.mts.map +1 -0
- package/dist/driver.mjs +96 -0
- package/dist/driver.mjs.map +1 -0
- package/dist/inbox.d.mts +368 -0
- package/dist/inbox.d.mts.map +1 -0
- package/dist/inbox.mjs +235 -0
- package/dist/inbox.mjs.map +1 -0
- package/dist/index.d.mts +1 -0
- package/dist/index.mjs +1 -0
- package/dist/outcome-constructors-internal.d.mts +403 -0
- package/dist/outcome-constructors-internal.d.mts.map +1 -0
- package/dist/outcome-constructors-internal.mjs +11 -0
- package/dist/outcome-constructors-internal.mjs.map +1 -0
- package/dist/outcome.d.mts +361 -0
- package/dist/outcome.d.mts.map +1 -0
- package/dist/outcome.mjs +136 -0
- package/dist/outcome.mjs.map +1 -0
- package/dist/store.d.mts +39 -0
- package/dist/store.d.mts.map +1 -0
- package/dist/store.mjs +98 -0
- package/dist/store.mjs.map +1 -0
- package/package.json +90 -0
- package/src/coordinator.ts +355 -0
- package/src/driver/durable-object.ts +28 -0
- package/src/driver/memory.ts +39 -0
- package/src/driver.ts +270 -0
- package/src/inbox.ts +528 -0
- package/src/index.ts +2 -0
- package/src/outcome-constructors-internal.ts +18 -0
- package/src/outcome.ts +377 -0
- package/src/store.ts +161 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { RunStore } from "./store.mjs";
|
|
2
|
+
import { InterruptReason, Promotable, RunCoordinator } from "./coordinator.mjs";
|
|
3
|
+
import { DrainToken, HitlAdmission, HitlDecision, Inbox, InboxItem, ParkedResponse, PauseDecision } from "./inbox.mjs";
|
|
4
|
+
import { Context, Data, Effect, Layer } from "effect";
|
|
5
|
+
|
|
6
|
+
//#region src/driver.d.ts
|
|
7
|
+
declare const defaultMaxResumeAttempts = 10;
|
|
8
|
+
declare const InvalidMaxResumeAttempts_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }>) => import("effect/Cause").YieldableError & {
|
|
9
|
+
readonly _tag: "InvalidMaxResumeAttempts";
|
|
10
|
+
} & Readonly<A>;
|
|
11
|
+
declare class InvalidMaxResumeAttempts extends InvalidMaxResumeAttempts_base<{
|
|
12
|
+
readonly maxResumeAttempts: number;
|
|
13
|
+
}> {}
|
|
14
|
+
type ResumeSuspendedResult = {
|
|
15
|
+
readonly resumed: ReadonlyArray<string>;
|
|
16
|
+
readonly exhausted: ReadonlyArray<string>;
|
|
17
|
+
};
|
|
18
|
+
type DrainContext = {
|
|
19
|
+
readonly drainToken: DrainToken;
|
|
20
|
+
readonly readyResponses: ReadonlyArray<ParkedResponse>;
|
|
21
|
+
};
|
|
22
|
+
type Drain = (runId: string, force: boolean, scope: Promotable, context: DrainContext) => Effect.Effect<void, never, Inbox | RunStore>;
|
|
23
|
+
type DriverLayerOptions = {
|
|
24
|
+
readonly drain?: Drain;
|
|
25
|
+
readonly maxResumeAttempts?: number;
|
|
26
|
+
};
|
|
27
|
+
type StopDecision = {
|
|
28
|
+
readonly _tag: 'Interrupted';
|
|
29
|
+
} | {
|
|
30
|
+
readonly _tag: 'ParkCleared';
|
|
31
|
+
} | {
|
|
32
|
+
readonly _tag: 'Idle';
|
|
33
|
+
};
|
|
34
|
+
declare const StopDecision: {
|
|
35
|
+
readonly Interrupted: Data.TaggedEnum.ConstructorFrom<{
|
|
36
|
+
readonly _tag: "Interrupted";
|
|
37
|
+
}, "_tag">;
|
|
38
|
+
readonly ParkCleared: Data.TaggedEnum.ConstructorFrom<{
|
|
39
|
+
readonly _tag: "ParkCleared";
|
|
40
|
+
}, "_tag">;
|
|
41
|
+
readonly Idle: Data.TaggedEnum.ConstructorFrom<{
|
|
42
|
+
readonly _tag: "Idle";
|
|
43
|
+
}, "_tag">;
|
|
44
|
+
readonly $is: <Tag extends "Interrupted" | "ParkCleared" | "Idle">(tag: Tag) => (u: unknown) => u is Extract<{
|
|
45
|
+
readonly _tag: "Interrupted";
|
|
46
|
+
}, {
|
|
47
|
+
readonly _tag: Tag;
|
|
48
|
+
}> | Extract<{
|
|
49
|
+
readonly _tag: "ParkCleared";
|
|
50
|
+
}, {
|
|
51
|
+
readonly _tag: Tag;
|
|
52
|
+
}> | Extract<{
|
|
53
|
+
readonly _tag: "Idle";
|
|
54
|
+
}, {
|
|
55
|
+
readonly _tag: Tag;
|
|
56
|
+
}>;
|
|
57
|
+
readonly $match: {
|
|
58
|
+
<Cases extends {
|
|
59
|
+
readonly Interrupted: (args: {
|
|
60
|
+
readonly _tag: "Interrupted";
|
|
61
|
+
}) => any;
|
|
62
|
+
readonly ParkCleared: (args: {
|
|
63
|
+
readonly _tag: "ParkCleared";
|
|
64
|
+
}) => any;
|
|
65
|
+
readonly Idle: (args: {
|
|
66
|
+
readonly _tag: "Idle";
|
|
67
|
+
}) => any;
|
|
68
|
+
}>(cases: Cases): (value: StopDecision) => import("effect/Unify").Unify<ReturnType<Cases["Interrupted" | "ParkCleared" | "Idle"]>>;
|
|
69
|
+
<Cases extends {
|
|
70
|
+
readonly Interrupted: (args: {
|
|
71
|
+
readonly _tag: "Interrupted";
|
|
72
|
+
}) => any;
|
|
73
|
+
readonly ParkCleared: (args: {
|
|
74
|
+
readonly _tag: "ParkCleared";
|
|
75
|
+
}) => any;
|
|
76
|
+
readonly Idle: (args: {
|
|
77
|
+
readonly _tag: "Idle";
|
|
78
|
+
}) => any;
|
|
79
|
+
}>(value: StopDecision, cases: Cases): import("effect/Unify").Unify<ReturnType<Cases["Interrupted" | "ParkCleared" | "Idle"]>>;
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
type DriverApi = {
|
|
83
|
+
readonly active: Effect.Effect<ReadonlySet<string>>;
|
|
84
|
+
readonly isActive: (runId: string) => Effect.Effect<boolean>;
|
|
85
|
+
readonly run: (runId: string) => Effect.Effect<void>;
|
|
86
|
+
readonly wake: (runId: string, scope?: Promotable) => Effect.Effect<void>;
|
|
87
|
+
readonly interrupt: (runId: string, options?: {
|
|
88
|
+
readonly reason?: InterruptReason;
|
|
89
|
+
readonly awaitSettlement?: boolean;
|
|
90
|
+
}) => Effect.Effect<boolean>;
|
|
91
|
+
readonly awaitIdle: (runId: string) => Effect.Effect<void>;
|
|
92
|
+
readonly resumeSuspended: Effect.Effect<ResumeSuspendedResult>;
|
|
93
|
+
readonly admit: (item: InboxItem) => Effect.Effect<void>;
|
|
94
|
+
readonly pause: (runId: string, requestIds: ReadonlyArray<string>, drainToken: DrainToken) => Effect.Effect<PauseDecision>;
|
|
95
|
+
readonly resumeHitl: (runId: string, admission: HitlAdmission) => Effect.Effect<HitlDecision>;
|
|
96
|
+
readonly stop: (runId: string) => Effect.Effect<StopDecision>;
|
|
97
|
+
};
|
|
98
|
+
declare const Driver_base: Context.ServiceClass<Driver, "@yolk-sdk/harness/Driver", DriverApi>;
|
|
99
|
+
declare class Driver extends Driver_base {
|
|
100
|
+
static layer(): Layer.Layer<Driver, never, RunStore | Inbox | RunCoordinator>;
|
|
101
|
+
static layer(options?: {
|
|
102
|
+
readonly maxResumeAttempts?: undefined;
|
|
103
|
+
}): Layer.Layer<Driver, never, RunStore | Inbox | RunCoordinator>;
|
|
104
|
+
static layer(options?: Pick<DriverLayerOptions, 'maxResumeAttempts'>): Layer.Layer<Driver, InvalidMaxResumeAttempts, RunStore | Inbox | RunCoordinator>;
|
|
105
|
+
static coordinatedLayer(): Layer.Layer<Driver, never, RunStore | Inbox>;
|
|
106
|
+
static coordinatedLayer(options?: {
|
|
107
|
+
readonly drain?: Drain;
|
|
108
|
+
readonly maxResumeAttempts?: undefined;
|
|
109
|
+
}): Layer.Layer<Driver, never, RunStore | Inbox>;
|
|
110
|
+
static coordinatedLayer(options?: DriverLayerOptions): Layer.Layer<Driver, InvalidMaxResumeAttempts, RunStore | Inbox>;
|
|
111
|
+
}
|
|
112
|
+
declare const makeHarness: <DE, DR, SE, SR, IE, IR>(input: {
|
|
113
|
+
readonly driver: Layer.Layer<Driver, DE, DR>;
|
|
114
|
+
readonly store: Layer.Layer<RunStore, SE, SR>;
|
|
115
|
+
readonly inbox: Layer.Layer<Inbox, IE, IR>;
|
|
116
|
+
}) => Layer.Layer<Driver | RunStore | Inbox, DE | SE | IE, DR | SR | IR>;
|
|
117
|
+
declare const admit: (item: InboxItem) => Effect.Effect<void, never, Driver>;
|
|
118
|
+
declare function makeDriverLayer(): Layer.Layer<Driver, never, RunStore | Inbox>;
|
|
119
|
+
declare function makeDriverLayer(options?: {
|
|
120
|
+
readonly drain?: Drain;
|
|
121
|
+
readonly maxResumeAttempts?: undefined;
|
|
122
|
+
}): Layer.Layer<Driver, never, RunStore | Inbox>;
|
|
123
|
+
declare function makeDriverLayer(options?: DriverLayerOptions): Layer.Layer<Driver, InvalidMaxResumeAttempts, RunStore | Inbox>;
|
|
124
|
+
//#endregion
|
|
125
|
+
export { Drain, DrainContext, Driver, DriverApi, DriverLayerOptions, type InterruptReason, InvalidMaxResumeAttempts, ResumeSuspendedResult, StopDecision, admit, defaultMaxResumeAttempts, makeDriverLayer, makeHarness };
|
|
126
|
+
//# sourceMappingURL=driver.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"driver.d.mts","names":[],"sources":["../src/driver.ts"],"mappings":"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"}
|
package/dist/driver.mjs
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { StopDecision as StopDecision$1 } from "./outcome-constructors-internal.mjs";
|
|
2
|
+
import { RunStore } from "./store.mjs";
|
|
3
|
+
import { RunCoordinator } from "./coordinator.mjs";
|
|
4
|
+
import { DrainBegin, Inbox, RecoveryAttempt } from "./inbox.mjs";
|
|
5
|
+
import { Context, Data, Effect, Exit, Layer, Predicate, Semaphore } from "effect";
|
|
6
|
+
//#region src/driver.ts
|
|
7
|
+
const defaultMaxResumeAttempts = 10;
|
|
8
|
+
var InvalidMaxResumeAttempts = class extends Data.TaggedError("InvalidMaxResumeAttempts") {};
|
|
9
|
+
const isValidMaxResumeAttempts = (value) => Number.isSafeInteger(value) && value >= 0;
|
|
10
|
+
const StopDecision = StopDecision$1;
|
|
11
|
+
var Driver = class Driver extends Context.Service()("@yolk-sdk/harness/Driver") {
|
|
12
|
+
static layer(options) {
|
|
13
|
+
return Layer.effect(Driver, Effect.gen(function* () {
|
|
14
|
+
const maxResumeAttempts = options?.maxResumeAttempts ?? 10;
|
|
15
|
+
if (!isValidMaxResumeAttempts(maxResumeAttempts)) return yield* Effect.fail(new InvalidMaxResumeAttempts({ maxResumeAttempts }));
|
|
16
|
+
const store = yield* RunStore;
|
|
17
|
+
const inbox = yield* Inbox;
|
|
18
|
+
const sweep = yield* Semaphore.make(1);
|
|
19
|
+
const coordinator = yield* RunCoordinator;
|
|
20
|
+
const resumeSuspended = sweep.withPermits(1)(Effect.gen(function* () {
|
|
21
|
+
const claimed = yield* store.claimed;
|
|
22
|
+
const resumed = [];
|
|
23
|
+
const exhausted = [];
|
|
24
|
+
for (const runId of claimed) {
|
|
25
|
+
const admission = yield* inbox.admitRecovery(runId, Effect.gen(function* () {
|
|
26
|
+
if (yield* coordinator.isActive(runId)) return RecoveryAttempt.Skip();
|
|
27
|
+
if (!(yield* store.isClaimed(runId))) return RecoveryAttempt.Skip();
|
|
28
|
+
if ((yield* store.resumeCount(runId)) >= maxResumeAttempts) {
|
|
29
|
+
yield* store.release(runId);
|
|
30
|
+
return RecoveryAttempt.Exhausted();
|
|
31
|
+
}
|
|
32
|
+
yield* store.incrementResumeCount(runId);
|
|
33
|
+
return RecoveryAttempt.Resume();
|
|
34
|
+
}), coordinator.wake(runId, "input"));
|
|
35
|
+
if (Predicate.isTagged(admission, "Resumed")) resumed.push(runId);
|
|
36
|
+
else if (Predicate.isTagged(admission, "Exhausted")) exhausted.push(runId);
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
resumed,
|
|
40
|
+
exhausted
|
|
41
|
+
};
|
|
42
|
+
}));
|
|
43
|
+
return Driver.of({
|
|
44
|
+
active: coordinator.active,
|
|
45
|
+
isActive: coordinator.isActive,
|
|
46
|
+
run: (runId) => {
|
|
47
|
+
const continueRun = () => inbox.startIfUnblocked(runId, coordinator.captureRun(runId)).pipe(Effect.flatMap((ticket) => {
|
|
48
|
+
if (ticket === void 0) return Effect.void;
|
|
49
|
+
if (Predicate.isTagged(ticket, "Stopping")) return ticket.awaitSettlement.pipe(Effect.andThen(Effect.suspend(continueRun)));
|
|
50
|
+
return ticket.join;
|
|
51
|
+
}));
|
|
52
|
+
return continueRun();
|
|
53
|
+
},
|
|
54
|
+
wake: (runId, scope = "input") => inbox.wakeIfUnblocked(runId, scope, coordinator.wake(runId, scope)).pipe(Effect.asVoid),
|
|
55
|
+
interrupt: (runId, interruptOptions) => coordinator.interrupt(runId, interruptOptions?.reason ?? "user", interruptOptions),
|
|
56
|
+
awaitIdle: coordinator.awaitIdle,
|
|
57
|
+
resumeSuspended,
|
|
58
|
+
admit: (item) => inbox.enqueueAndWake(item, coordinator.wake(item.runId, item.delivery === "steer" ? "steer" : "input")),
|
|
59
|
+
pause: (runId, requestIds, drainToken) => inbox.park(runId, requestIds, drainToken),
|
|
60
|
+
resumeHitl: (runId, admission) => inbox.acceptHitl(runId, admission, coordinator.wake(runId, "input")),
|
|
61
|
+
stop: (runId) => inbox.invalidate(runId, coordinator.terminalStop(runId, "user").pipe(Effect.map((receipt) => Predicate.isTagged(receipt, "Interrupted") || Predicate.isTagged(receipt, "LiveStopping"))), store.isClaimed(runId).pipe(Effect.flatMap((claimed) => claimed ? store.release(runId) : Effect.void))).pipe(Effect.map((result) => {
|
|
62
|
+
if (result.interrupted) return StopDecision.Interrupted();
|
|
63
|
+
if (result.hadPark) return StopDecision.ParkCleared();
|
|
64
|
+
return StopDecision.Idle();
|
|
65
|
+
}))
|
|
66
|
+
});
|
|
67
|
+
}));
|
|
68
|
+
}
|
|
69
|
+
static coordinatedLayer(options) {
|
|
70
|
+
return Layer.unwrap(Effect.gen(function* () {
|
|
71
|
+
const store = yield* RunStore;
|
|
72
|
+
const inbox = yield* Inbox;
|
|
73
|
+
const hostDrain = options?.drain ?? ((_runId, _force, _scope, _context) => Effect.void);
|
|
74
|
+
const maxResumeAttempts = options?.maxResumeAttempts ?? 10;
|
|
75
|
+
const storeLayer = Layer.succeed(RunStore, store);
|
|
76
|
+
const inboxLayer = Layer.succeed(Inbox, inbox);
|
|
77
|
+
const coordinator = RunCoordinator.layer({ drain: (runId, force, scope) => inbox.beginDrain(runId, scope).pipe(Effect.flatMap((begun) => {
|
|
78
|
+
if (DrainBegin.$is("Skip")(begun)) return Effect.void;
|
|
79
|
+
return Effect.suspend(() => hostDrain(runId, force, scope, {
|
|
80
|
+
drainToken: begun.drainToken,
|
|
81
|
+
readyResponses: begun.readyResponses
|
|
82
|
+
})).pipe(Effect.provideService(Inbox, inbox), Effect.provideService(RunStore, store), Effect.onExit((exit) => inbox.endDrain(runId, begun.drainToken, Exit.isSuccess(exit))));
|
|
83
|
+
})) }).pipe(Layer.provide(storeLayer));
|
|
84
|
+
return Driver.layer({ maxResumeAttempts }).pipe(Layer.provide(coordinator), Layer.provide(storeLayer), Layer.provide(inboxLayer));
|
|
85
|
+
}));
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
const makeHarness = (input) => Layer.mergeAll(input.driver, input.store, input.inbox);
|
|
89
|
+
const admit = (item) => Effect.flatMap(Driver, (driver) => driver.admit(item));
|
|
90
|
+
function makeDriverLayer(options) {
|
|
91
|
+
return options === void 0 ? Driver.coordinatedLayer() : Driver.coordinatedLayer(options);
|
|
92
|
+
}
|
|
93
|
+
//#endregion
|
|
94
|
+
export { Driver, InvalidMaxResumeAttempts, StopDecision, admit, defaultMaxResumeAttempts, makeDriverLayer, makeHarness };
|
|
95
|
+
|
|
96
|
+
//# sourceMappingURL=driver.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"driver.mjs","names":["stopDecision"],"sources":["../src/driver.ts"],"sourcesContent":["import { Context, Data, Effect, Exit, Layer, Predicate, Semaphore } from 'effect'\nimport { StopDecision as stopDecision } from './outcome-constructors-internal.ts'\nimport { RunCoordinator, type InterruptReason, type Promotable } from './coordinator.ts'\nimport {\n DrainBegin,\n Inbox,\n RecoveryAttempt,\n type DrainToken,\n type HitlAdmission,\n type HitlDecision,\n type InboxItem,\n type ParkedResponse,\n type PauseDecision\n} from './inbox.ts'\nimport { RunStore } from './store.ts'\n\nexport type { InterruptReason } from './coordinator.ts'\n\nexport const defaultMaxResumeAttempts = 10\n\nexport class InvalidMaxResumeAttempts extends Data.TaggedError('InvalidMaxResumeAttempts')<{\n readonly maxResumeAttempts: number\n}> {}\n\nconst isValidMaxResumeAttempts = (value: number) => Number.isSafeInteger(value) && value >= 0\n\nexport type ResumeSuspendedResult = {\n readonly resumed: ReadonlyArray<string>\n readonly exhausted: ReadonlyArray<string>\n}\n\nexport type DrainContext = {\n readonly drainToken: DrainToken\n readonly readyResponses: ReadonlyArray<ParkedResponse>\n}\n\nexport type Drain = (\n runId: string,\n force: boolean,\n scope: Promotable,\n context: DrainContext\n) => Effect.Effect<void, never, Inbox | RunStore>\n\nexport type DriverLayerOptions = {\n readonly drain?: Drain\n readonly maxResumeAttempts?: number\n}\n\nexport type StopDecision =\n | { readonly _tag: 'Interrupted' }\n | { readonly _tag: 'ParkCleared' }\n | { readonly _tag: 'Idle' }\n\nexport const StopDecision = stopDecision\n\nexport type DriverApi = {\n readonly active: Effect.Effect<ReadonlySet<string>>\n readonly isActive: (runId: string) => Effect.Effect<boolean>\n readonly run: (runId: string) => Effect.Effect<void>\n readonly wake: (runId: string, scope?: Promotable) => Effect.Effect<void>\n readonly interrupt: (\n runId: string,\n options?: { readonly reason?: InterruptReason; readonly awaitSettlement?: boolean }\n ) => Effect.Effect<boolean>\n readonly awaitIdle: (runId: string) => Effect.Effect<void>\n readonly resumeSuspended: Effect.Effect<ResumeSuspendedResult>\n readonly admit: (item: InboxItem) => Effect.Effect<void>\n readonly pause: (\n runId: string,\n requestIds: ReadonlyArray<string>,\n drainToken: DrainToken\n ) => Effect.Effect<PauseDecision>\n readonly resumeHitl: (runId: string, admission: HitlAdmission) => Effect.Effect<HitlDecision>\n readonly stop: (runId: string) => Effect.Effect<StopDecision>\n}\n\nexport class Driver extends Context.Service<Driver, DriverApi>()('@yolk-sdk/harness/Driver') {\n static layer(): Layer.Layer<Driver, never, RunStore | Inbox | RunCoordinator>\n static layer(options?: {\n readonly maxResumeAttempts?: undefined\n }): Layer.Layer<Driver, never, RunStore | Inbox | RunCoordinator>\n static layer(\n options?: Pick<DriverLayerOptions, 'maxResumeAttempts'>\n ): Layer.Layer<Driver, InvalidMaxResumeAttempts, RunStore | Inbox | RunCoordinator>\n static layer(options?: Pick<DriverLayerOptions, 'maxResumeAttempts'>) {\n return Layer.effect(\n Driver,\n Effect.gen(function* () {\n const maxResumeAttempts = options?.maxResumeAttempts ?? defaultMaxResumeAttempts\n\n if (!isValidMaxResumeAttempts(maxResumeAttempts)) {\n return yield* Effect.fail(new InvalidMaxResumeAttempts({ maxResumeAttempts }))\n }\n\n const store = yield* RunStore\n const inbox = yield* Inbox\n const sweep = yield* Semaphore.make(1)\n const coordinator = yield* RunCoordinator\n\n const resumeSuspended = sweep.withPermits(1)(\n Effect.gen(function* () {\n const claimed = yield* store.claimed\n const resumed: Array<string> = []\n const exhausted: Array<string> = []\n\n for (const runId of claimed) {\n const admission = yield* inbox.admitRecovery(\n runId,\n Effect.gen(function* () {\n if (yield* coordinator.isActive(runId)) return RecoveryAttempt.Skip()\n\n if (!(yield* store.isClaimed(runId))) return RecoveryAttempt.Skip()\n const count = yield* store.resumeCount(runId)\n\n if (count >= maxResumeAttempts) {\n yield* store.release(runId)\n\n return RecoveryAttempt.Exhausted()\n }\n\n yield* store.incrementResumeCount(runId)\n\n return RecoveryAttempt.Resume()\n }),\n coordinator.wake(runId, 'input')\n )\n\n if (Predicate.isTagged(admission, 'Resumed')) resumed.push(runId)\n else if (Predicate.isTagged(admission, 'Exhausted')) exhausted.push(runId)\n }\n\n return { resumed, exhausted }\n })\n )\n\n return Driver.of({\n active: coordinator.active,\n isActive: coordinator.isActive,\n run: runId => {\n const continueRun = (): Effect.Effect<void> =>\n inbox.startIfUnblocked(runId, coordinator.captureRun(runId)).pipe(\n Effect.flatMap(ticket => {\n if (ticket === undefined) return Effect.void\n\n if (Predicate.isTagged(ticket, 'Stopping')) {\n return ticket.awaitSettlement.pipe(Effect.andThen(Effect.suspend(continueRun)))\n }\n\n return ticket.join\n })\n )\n\n return continueRun()\n },\n wake: (runId, scope = 'input') =>\n inbox.wakeIfUnblocked(runId, scope, coordinator.wake(runId, scope)).pipe(Effect.asVoid),\n interrupt: (runId, interruptOptions) =>\n coordinator.interrupt(runId, interruptOptions?.reason ?? 'user', interruptOptions),\n awaitIdle: coordinator.awaitIdle,\n resumeSuspended,\n admit: item =>\n inbox.enqueueAndWake(\n item,\n coordinator.wake(item.runId, item.delivery === 'steer' ? 'steer' : 'input')\n ),\n pause: (runId, requestIds, drainToken) => inbox.park(runId, requestIds, drainToken),\n resumeHitl: (runId, admission) =>\n inbox.acceptHitl(runId, admission, coordinator.wake(runId, 'input')),\n stop: runId =>\n inbox\n .invalidate(\n runId,\n coordinator\n .terminalStop(runId, 'user')\n .pipe(\n Effect.map(\n receipt =>\n Predicate.isTagged(receipt, 'Interrupted') ||\n Predicate.isTagged(receipt, 'LiveStopping')\n )\n ),\n store\n .isClaimed(runId)\n .pipe(Effect.flatMap(claimed => (claimed ? store.release(runId) : Effect.void)))\n )\n .pipe(\n Effect.map(result => {\n if (result.interrupted) return StopDecision.Interrupted()\n\n if (result.hadPark) return StopDecision.ParkCleared()\n\n return StopDecision.Idle()\n })\n )\n })\n })\n )\n }\n\n static coordinatedLayer(): Layer.Layer<Driver, never, RunStore | Inbox>\n static coordinatedLayer(options?: {\n readonly drain?: Drain\n readonly maxResumeAttempts?: undefined\n }): Layer.Layer<Driver, never, RunStore | Inbox>\n static coordinatedLayer(\n options?: DriverLayerOptions\n ): Layer.Layer<Driver, InvalidMaxResumeAttempts, RunStore | Inbox>\n static coordinatedLayer(options?: DriverLayerOptions) {\n return Layer.unwrap(\n Effect.gen(function* () {\n const store = yield* RunStore\n const inbox = yield* Inbox\n // Keep compatibility option reads lazy and in drain/max order.\n const hostDrain = options?.drain ?? ((_runId, _force, _scope, _context) => Effect.void)\n const maxResumeAttempts = options?.maxResumeAttempts ?? defaultMaxResumeAttempts\n const storeLayer = Layer.succeed(RunStore, store)\n const inboxLayer = Layer.succeed(Inbox, inbox)\n\n const coordinator = RunCoordinator.layer({\n drain: (runId, force, scope) =>\n inbox.beginDrain(runId, scope).pipe(\n Effect.flatMap(begun => {\n if (DrainBegin.$is('Skip')(begun)) return Effect.void\n\n return Effect.suspend(() =>\n hostDrain(runId, force, scope, {\n drainToken: begun.drainToken,\n readyResponses: begun.readyResponses\n })\n ).pipe(\n Effect.provideService(Inbox, inbox),\n Effect.provideService(RunStore, store),\n Effect.onExit(exit =>\n inbox.endDrain(runId, begun.drainToken, Exit.isSuccess(exit))\n )\n )\n })\n )\n }).pipe(Layer.provide(storeLayer))\n\n return Driver.layer({ maxResumeAttempts }).pipe(\n Layer.provide(coordinator),\n Layer.provide(storeLayer),\n Layer.provide(inboxLayer)\n )\n })\n )\n }\n}\n\nexport const makeHarness = <DE, DR, SE, SR, IE, IR>(input: {\n readonly driver: Layer.Layer<Driver, DE, DR>\n readonly store: Layer.Layer<RunStore, SE, SR>\n readonly inbox: Layer.Layer<Inbox, IE, IR>\n}): Layer.Layer<Driver | RunStore | Inbox, DE | SE | IE, DR | SR | IR> =>\n Layer.mergeAll(input.driver, input.store, input.inbox)\n\nexport const admit = (item: InboxItem) => Effect.flatMap(Driver, driver => driver.admit(item))\n\nexport function makeDriverLayer(): Layer.Layer<Driver, never, RunStore | Inbox>\nexport function makeDriverLayer(options?: {\n readonly drain?: Drain\n readonly maxResumeAttempts?: undefined\n}): Layer.Layer<Driver, never, RunStore | Inbox>\nexport function makeDriverLayer(\n options?: DriverLayerOptions\n): Layer.Layer<Driver, InvalidMaxResumeAttempts, RunStore | Inbox>\nexport function makeDriverLayer(options?: DriverLayerOptions) {\n return options === undefined ? Driver.coordinatedLayer() : Driver.coordinatedLayer(options)\n}\n"],"mappings":"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"}
|
package/dist/inbox.d.mts
ADDED
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
import { CapturedRun, Promotable } from "./coordinator.mjs";
|
|
2
|
+
import { Context, Data, Effect, Layer } from "effect";
|
|
3
|
+
import * as Schema from "effect/Schema";
|
|
4
|
+
|
|
5
|
+
//#region src/inbox.d.ts
|
|
6
|
+
/** Nominal identity only. All strings stay admissible so stale/empty/foreign
|
|
7
|
+
* tokens retain the inbox's existing no-op decisions rather than parse failures. */
|
|
8
|
+
declare const DrainToken: Schema.brand<Schema.String, "DrainToken">;
|
|
9
|
+
type DrainToken = typeof DrainToken.Type;
|
|
10
|
+
/** Nominal identity only; freshness and instance ownership are checked by Inbox. */
|
|
11
|
+
declare const ParkGeneration: Schema.brand<Schema.String, "ParkGeneration">;
|
|
12
|
+
type ParkGeneration = typeof ParkGeneration.Type;
|
|
13
|
+
type InboxKind = 'input' | 'hitl';
|
|
14
|
+
type InboxItem = {
|
|
15
|
+
readonly id: string;
|
|
16
|
+
readonly runId: string;
|
|
17
|
+
readonly delivery: Promotable | 'queue';
|
|
18
|
+
readonly kind: InboxKind;
|
|
19
|
+
};
|
|
20
|
+
type ParkedResponse = {
|
|
21
|
+
readonly itemId: string;
|
|
22
|
+
readonly requestId: string;
|
|
23
|
+
};
|
|
24
|
+
type ParkedState = {
|
|
25
|
+
readonly generation: ParkGeneration;
|
|
26
|
+
readonly requestIds: ReadonlyArray<string>;
|
|
27
|
+
readonly responses: ReadonlyArray<ParkedResponse>;
|
|
28
|
+
readonly ready: boolean;
|
|
29
|
+
};
|
|
30
|
+
type HitlAdmission = {
|
|
31
|
+
readonly itemId: string;
|
|
32
|
+
readonly requestId: string;
|
|
33
|
+
readonly generation: ParkGeneration;
|
|
34
|
+
};
|
|
35
|
+
type HitlDecision = {
|
|
36
|
+
readonly _tag: 'Accepted';
|
|
37
|
+
} | {
|
|
38
|
+
readonly _tag: 'Ready';
|
|
39
|
+
} | {
|
|
40
|
+
readonly _tag: 'Duplicate';
|
|
41
|
+
} | {
|
|
42
|
+
readonly _tag: 'Stale';
|
|
43
|
+
} | {
|
|
44
|
+
readonly _tag: 'UnknownRequest';
|
|
45
|
+
} | {
|
|
46
|
+
readonly _tag: 'NotParked';
|
|
47
|
+
};
|
|
48
|
+
type PauseDecision = {
|
|
49
|
+
readonly _tag: 'Parked';
|
|
50
|
+
readonly generation: ParkGeneration;
|
|
51
|
+
} | {
|
|
52
|
+
readonly _tag: 'Stale';
|
|
53
|
+
};
|
|
54
|
+
type RecoveryAttempt = {
|
|
55
|
+
readonly _tag: 'Skip';
|
|
56
|
+
} | {
|
|
57
|
+
readonly _tag: 'Exhausted';
|
|
58
|
+
} | {
|
|
59
|
+
readonly _tag: 'Resume';
|
|
60
|
+
};
|
|
61
|
+
type RecoveryAdmission = {
|
|
62
|
+
readonly _tag: 'Skip';
|
|
63
|
+
} | {
|
|
64
|
+
readonly _tag: 'Exhausted';
|
|
65
|
+
} | {
|
|
66
|
+
readonly _tag: 'Resumed';
|
|
67
|
+
};
|
|
68
|
+
type DrainBegin = {
|
|
69
|
+
readonly _tag: 'Skip';
|
|
70
|
+
} | {
|
|
71
|
+
readonly _tag: 'Run';
|
|
72
|
+
readonly drainToken: DrainToken;
|
|
73
|
+
readonly readyResponses: ReadonlyArray<ParkedResponse>;
|
|
74
|
+
};
|
|
75
|
+
declare const HitlDecision: {
|
|
76
|
+
readonly Accepted: Data.TaggedEnum.ConstructorFrom<{
|
|
77
|
+
readonly _tag: "Accepted";
|
|
78
|
+
}, "_tag">;
|
|
79
|
+
readonly Ready: Data.TaggedEnum.ConstructorFrom<{
|
|
80
|
+
readonly _tag: "Ready";
|
|
81
|
+
}, "_tag">;
|
|
82
|
+
readonly Duplicate: Data.TaggedEnum.ConstructorFrom<{
|
|
83
|
+
readonly _tag: "Duplicate";
|
|
84
|
+
}, "_tag">;
|
|
85
|
+
readonly Stale: Data.TaggedEnum.ConstructorFrom<{
|
|
86
|
+
readonly _tag: "Stale";
|
|
87
|
+
}, "_tag">;
|
|
88
|
+
readonly UnknownRequest: Data.TaggedEnum.ConstructorFrom<{
|
|
89
|
+
readonly _tag: "UnknownRequest";
|
|
90
|
+
}, "_tag">;
|
|
91
|
+
readonly NotParked: Data.TaggedEnum.ConstructorFrom<{
|
|
92
|
+
readonly _tag: "NotParked";
|
|
93
|
+
}, "_tag">;
|
|
94
|
+
readonly $is: <Tag extends "Accepted" | "Ready" | "Duplicate" | "Stale" | "UnknownRequest" | "NotParked">(tag: Tag) => (u: unknown) => u is Extract<{
|
|
95
|
+
readonly _tag: "Accepted";
|
|
96
|
+
}, {
|
|
97
|
+
readonly _tag: Tag;
|
|
98
|
+
}> | Extract<{
|
|
99
|
+
readonly _tag: "Ready";
|
|
100
|
+
}, {
|
|
101
|
+
readonly _tag: Tag;
|
|
102
|
+
}> | Extract<{
|
|
103
|
+
readonly _tag: "Duplicate";
|
|
104
|
+
}, {
|
|
105
|
+
readonly _tag: Tag;
|
|
106
|
+
}> | Extract<{
|
|
107
|
+
readonly _tag: "Stale";
|
|
108
|
+
}, {
|
|
109
|
+
readonly _tag: Tag;
|
|
110
|
+
}> | Extract<{
|
|
111
|
+
readonly _tag: "UnknownRequest";
|
|
112
|
+
}, {
|
|
113
|
+
readonly _tag: Tag;
|
|
114
|
+
}> | Extract<{
|
|
115
|
+
readonly _tag: "NotParked";
|
|
116
|
+
}, {
|
|
117
|
+
readonly _tag: Tag;
|
|
118
|
+
}>;
|
|
119
|
+
readonly $match: {
|
|
120
|
+
<Cases extends {
|
|
121
|
+
readonly Accepted: (args: {
|
|
122
|
+
readonly _tag: "Accepted";
|
|
123
|
+
}) => any;
|
|
124
|
+
readonly Ready: (args: {
|
|
125
|
+
readonly _tag: "Ready";
|
|
126
|
+
}) => any;
|
|
127
|
+
readonly Duplicate: (args: {
|
|
128
|
+
readonly _tag: "Duplicate";
|
|
129
|
+
}) => any;
|
|
130
|
+
readonly Stale: (args: {
|
|
131
|
+
readonly _tag: "Stale";
|
|
132
|
+
}) => any;
|
|
133
|
+
readonly UnknownRequest: (args: {
|
|
134
|
+
readonly _tag: "UnknownRequest";
|
|
135
|
+
}) => any;
|
|
136
|
+
readonly NotParked: (args: {
|
|
137
|
+
readonly _tag: "NotParked";
|
|
138
|
+
}) => any;
|
|
139
|
+
}>(cases: Cases): (value: HitlDecision) => import("effect/Unify").Unify<ReturnType<Cases["Accepted" | "Ready" | "Duplicate" | "Stale" | "UnknownRequest" | "NotParked"]>>;
|
|
140
|
+
<Cases extends {
|
|
141
|
+
readonly Accepted: (args: {
|
|
142
|
+
readonly _tag: "Accepted";
|
|
143
|
+
}) => any;
|
|
144
|
+
readonly Ready: (args: {
|
|
145
|
+
readonly _tag: "Ready";
|
|
146
|
+
}) => any;
|
|
147
|
+
readonly Duplicate: (args: {
|
|
148
|
+
readonly _tag: "Duplicate";
|
|
149
|
+
}) => any;
|
|
150
|
+
readonly Stale: (args: {
|
|
151
|
+
readonly _tag: "Stale";
|
|
152
|
+
}) => any;
|
|
153
|
+
readonly UnknownRequest: (args: {
|
|
154
|
+
readonly _tag: "UnknownRequest";
|
|
155
|
+
}) => any;
|
|
156
|
+
readonly NotParked: (args: {
|
|
157
|
+
readonly _tag: "NotParked";
|
|
158
|
+
}) => any;
|
|
159
|
+
}>(value: HitlDecision, cases: Cases): import("effect/Unify").Unify<ReturnType<Cases["Accepted" | "Ready" | "Duplicate" | "Stale" | "UnknownRequest" | "NotParked"]>>;
|
|
160
|
+
};
|
|
161
|
+
};
|
|
162
|
+
declare const PauseDecision: {
|
|
163
|
+
readonly Stale: Data.TaggedEnum.ConstructorFrom<{
|
|
164
|
+
readonly _tag: "Stale";
|
|
165
|
+
}, "_tag">;
|
|
166
|
+
readonly Parked: Data.TaggedEnum.ConstructorFrom<{
|
|
167
|
+
readonly _tag: "Parked";
|
|
168
|
+
readonly generation: ParkGeneration;
|
|
169
|
+
}, "_tag">;
|
|
170
|
+
readonly $is: <Tag extends "Stale" | "Parked">(tag: Tag) => (u: unknown) => u is Extract<{
|
|
171
|
+
readonly _tag: "Parked";
|
|
172
|
+
readonly generation: ParkGeneration;
|
|
173
|
+
}, {
|
|
174
|
+
readonly _tag: Tag;
|
|
175
|
+
}> | Extract<{
|
|
176
|
+
readonly _tag: "Stale";
|
|
177
|
+
}, {
|
|
178
|
+
readonly _tag: Tag;
|
|
179
|
+
}>;
|
|
180
|
+
readonly $match: {
|
|
181
|
+
<Cases extends {
|
|
182
|
+
readonly Stale: (args: {
|
|
183
|
+
readonly _tag: "Stale";
|
|
184
|
+
}) => any;
|
|
185
|
+
readonly Parked: (args: {
|
|
186
|
+
readonly _tag: "Parked";
|
|
187
|
+
readonly generation: ParkGeneration;
|
|
188
|
+
}) => any;
|
|
189
|
+
}>(cases: Cases): (value: PauseDecision) => import("effect/Unify").Unify<ReturnType<Cases["Stale" | "Parked"]>>;
|
|
190
|
+
<Cases extends {
|
|
191
|
+
readonly Stale: (args: {
|
|
192
|
+
readonly _tag: "Stale";
|
|
193
|
+
}) => any;
|
|
194
|
+
readonly Parked: (args: {
|
|
195
|
+
readonly _tag: "Parked";
|
|
196
|
+
readonly generation: ParkGeneration;
|
|
197
|
+
}) => any;
|
|
198
|
+
}>(value: PauseDecision, cases: Cases): import("effect/Unify").Unify<ReturnType<Cases["Stale" | "Parked"]>>;
|
|
199
|
+
};
|
|
200
|
+
};
|
|
201
|
+
declare const RecoveryAttempt: {
|
|
202
|
+
readonly Skip: Data.TaggedEnum.ConstructorFrom<{
|
|
203
|
+
readonly _tag: "Skip";
|
|
204
|
+
}, "_tag">;
|
|
205
|
+
readonly Exhausted: Data.TaggedEnum.ConstructorFrom<{
|
|
206
|
+
readonly _tag: "Exhausted";
|
|
207
|
+
}, "_tag">;
|
|
208
|
+
readonly Resume: Data.TaggedEnum.ConstructorFrom<{
|
|
209
|
+
readonly _tag: "Resume";
|
|
210
|
+
}, "_tag">;
|
|
211
|
+
readonly $is: <Tag extends "Skip" | "Exhausted" | "Resume">(tag: Tag) => (u: unknown) => u is Extract<{
|
|
212
|
+
readonly _tag: "Skip";
|
|
213
|
+
}, {
|
|
214
|
+
readonly _tag: Tag;
|
|
215
|
+
}> | Extract<{
|
|
216
|
+
readonly _tag: "Exhausted";
|
|
217
|
+
}, {
|
|
218
|
+
readonly _tag: Tag;
|
|
219
|
+
}> | Extract<{
|
|
220
|
+
readonly _tag: "Resume";
|
|
221
|
+
}, {
|
|
222
|
+
readonly _tag: Tag;
|
|
223
|
+
}>;
|
|
224
|
+
readonly $match: {
|
|
225
|
+
<Cases extends {
|
|
226
|
+
readonly Skip: (args: {
|
|
227
|
+
readonly _tag: "Skip";
|
|
228
|
+
}) => any;
|
|
229
|
+
readonly Exhausted: (args: {
|
|
230
|
+
readonly _tag: "Exhausted";
|
|
231
|
+
}) => any;
|
|
232
|
+
readonly Resume: (args: {
|
|
233
|
+
readonly _tag: "Resume";
|
|
234
|
+
}) => any;
|
|
235
|
+
}>(cases: Cases): (value: RecoveryAttempt) => import("effect/Unify").Unify<ReturnType<Cases["Skip" | "Exhausted" | "Resume"]>>;
|
|
236
|
+
<Cases extends {
|
|
237
|
+
readonly Skip: (args: {
|
|
238
|
+
readonly _tag: "Skip";
|
|
239
|
+
}) => any;
|
|
240
|
+
readonly Exhausted: (args: {
|
|
241
|
+
readonly _tag: "Exhausted";
|
|
242
|
+
}) => any;
|
|
243
|
+
readonly Resume: (args: {
|
|
244
|
+
readonly _tag: "Resume";
|
|
245
|
+
}) => any;
|
|
246
|
+
}>(value: RecoveryAttempt, cases: Cases): import("effect/Unify").Unify<ReturnType<Cases["Skip" | "Exhausted" | "Resume"]>>;
|
|
247
|
+
};
|
|
248
|
+
};
|
|
249
|
+
declare const RecoveryAdmission: {
|
|
250
|
+
readonly Skip: Data.TaggedEnum.ConstructorFrom<{
|
|
251
|
+
readonly _tag: "Skip";
|
|
252
|
+
}, "_tag">;
|
|
253
|
+
readonly Exhausted: Data.TaggedEnum.ConstructorFrom<{
|
|
254
|
+
readonly _tag: "Exhausted";
|
|
255
|
+
}, "_tag">;
|
|
256
|
+
readonly Resumed: Data.TaggedEnum.ConstructorFrom<{
|
|
257
|
+
readonly _tag: "Resumed";
|
|
258
|
+
}, "_tag">;
|
|
259
|
+
readonly $is: <Tag extends "Skip" | "Exhausted" | "Resumed">(tag: Tag) => (u: unknown) => u is Extract<{
|
|
260
|
+
readonly _tag: "Skip";
|
|
261
|
+
}, {
|
|
262
|
+
readonly _tag: Tag;
|
|
263
|
+
}> | Extract<{
|
|
264
|
+
readonly _tag: "Exhausted";
|
|
265
|
+
}, {
|
|
266
|
+
readonly _tag: Tag;
|
|
267
|
+
}> | Extract<{
|
|
268
|
+
readonly _tag: "Resumed";
|
|
269
|
+
}, {
|
|
270
|
+
readonly _tag: Tag;
|
|
271
|
+
}>;
|
|
272
|
+
readonly $match: {
|
|
273
|
+
<Cases extends {
|
|
274
|
+
readonly Skip: (args: {
|
|
275
|
+
readonly _tag: "Skip";
|
|
276
|
+
}) => any;
|
|
277
|
+
readonly Exhausted: (args: {
|
|
278
|
+
readonly _tag: "Exhausted";
|
|
279
|
+
}) => any;
|
|
280
|
+
readonly Resumed: (args: {
|
|
281
|
+
readonly _tag: "Resumed";
|
|
282
|
+
}) => any;
|
|
283
|
+
}>(cases: Cases): (value: RecoveryAdmission) => import("effect/Unify").Unify<ReturnType<Cases["Skip" | "Exhausted" | "Resumed"]>>;
|
|
284
|
+
<Cases extends {
|
|
285
|
+
readonly Skip: (args: {
|
|
286
|
+
readonly _tag: "Skip";
|
|
287
|
+
}) => any;
|
|
288
|
+
readonly Exhausted: (args: {
|
|
289
|
+
readonly _tag: "Exhausted";
|
|
290
|
+
}) => any;
|
|
291
|
+
readonly Resumed: (args: {
|
|
292
|
+
readonly _tag: "Resumed";
|
|
293
|
+
}) => any;
|
|
294
|
+
}>(value: RecoveryAdmission, cases: Cases): import("effect/Unify").Unify<ReturnType<Cases["Skip" | "Exhausted" | "Resumed"]>>;
|
|
295
|
+
};
|
|
296
|
+
};
|
|
297
|
+
declare const DrainBegin: {
|
|
298
|
+
readonly Skip: Data.TaggedEnum.ConstructorFrom<{
|
|
299
|
+
readonly _tag: "Skip";
|
|
300
|
+
}, "_tag">;
|
|
301
|
+
readonly Run: Data.TaggedEnum.ConstructorFrom<{
|
|
302
|
+
readonly _tag: "Run";
|
|
303
|
+
readonly drainToken: DrainToken;
|
|
304
|
+
readonly readyResponses: ReadonlyArray<ParkedResponse>;
|
|
305
|
+
}, "_tag">;
|
|
306
|
+
readonly $is: <Tag extends "Skip" | "Run">(tag: Tag) => (u: unknown) => u is Extract<{
|
|
307
|
+
readonly _tag: "Skip";
|
|
308
|
+
}, {
|
|
309
|
+
readonly _tag: Tag;
|
|
310
|
+
}> | Extract<{
|
|
311
|
+
readonly _tag: "Run";
|
|
312
|
+
readonly drainToken: DrainToken;
|
|
313
|
+
readonly readyResponses: ReadonlyArray<ParkedResponse>;
|
|
314
|
+
}, {
|
|
315
|
+
readonly _tag: Tag;
|
|
316
|
+
}>;
|
|
317
|
+
readonly $match: {
|
|
318
|
+
<Cases extends {
|
|
319
|
+
readonly Skip: (args: {
|
|
320
|
+
readonly _tag: "Skip";
|
|
321
|
+
}) => any;
|
|
322
|
+
readonly Run: (args: {
|
|
323
|
+
readonly _tag: "Run";
|
|
324
|
+
readonly drainToken: DrainToken;
|
|
325
|
+
readonly readyResponses: ReadonlyArray<ParkedResponse>;
|
|
326
|
+
}) => any;
|
|
327
|
+
}>(cases: Cases): (value: DrainBegin) => import("effect/Unify").Unify<ReturnType<Cases["Skip" | "Run"]>>;
|
|
328
|
+
<Cases extends {
|
|
329
|
+
readonly Skip: (args: {
|
|
330
|
+
readonly _tag: "Skip";
|
|
331
|
+
}) => any;
|
|
332
|
+
readonly Run: (args: {
|
|
333
|
+
readonly _tag: "Run";
|
|
334
|
+
readonly drainToken: DrainToken;
|
|
335
|
+
readonly readyResponses: ReadonlyArray<ParkedResponse>;
|
|
336
|
+
}) => any;
|
|
337
|
+
}>(value: DrainBegin, cases: Cases): import("effect/Unify").Unify<ReturnType<Cases["Skip" | "Run"]>>;
|
|
338
|
+
};
|
|
339
|
+
};
|
|
340
|
+
type InboxApi = {
|
|
341
|
+
readonly enqueue: (item: InboxItem) => Effect.Effect<void>;
|
|
342
|
+
readonly takePromotable: (runId: string, scope: Promotable, drainToken: DrainToken) => Effect.Effect<InboxItem | undefined>;
|
|
343
|
+
readonly pending: (runId: string) => Effect.Effect<ReadonlyArray<InboxItem>>;
|
|
344
|
+
readonly parked: (runId: string) => Effect.Effect<ParkedState | undefined>;
|
|
345
|
+
readonly park: (runId: string, requestIds: ReadonlyArray<string>, drainToken: DrainToken) => Effect.Effect<PauseDecision>;
|
|
346
|
+
readonly acceptHitl: (runId: string, admission: HitlAdmission, onReady: Effect.Effect<void>) => Effect.Effect<HitlDecision>;
|
|
347
|
+
readonly clearPark: (runId: string, generation: ParkGeneration) => Effect.Effect<boolean>;
|
|
348
|
+
readonly beginDrain: (runId: string, scope: Promotable) => Effect.Effect<DrainBegin>;
|
|
349
|
+
readonly endDrain: (runId: string, drainToken: DrainToken, acknowledged: boolean) => Effect.Effect<void>;
|
|
350
|
+
readonly invalidate: (runId: string, interrupt: Effect.Effect<boolean>, releaseIdleClaim: Effect.Effect<void>) => Effect.Effect<{
|
|
351
|
+
readonly hadPark: boolean;
|
|
352
|
+
readonly interrupted: boolean;
|
|
353
|
+
}>;
|
|
354
|
+
readonly enqueueAndWake: (item: InboxItem, wake: Effect.Effect<void>) => Effect.Effect<void>;
|
|
355
|
+
readonly wakeIfUnblocked: (runId: string, scope: Promotable, wake: Effect.Effect<void>) => Effect.Effect<boolean>;
|
|
356
|
+
readonly startIfUnblocked: <E, R>(runId: string, start: Effect.Effect<CapturedRun<E>, E, R>) => Effect.Effect<CapturedRun<E> | undefined, E, R>;
|
|
357
|
+
readonly admitRecovery: <E, R>(runId: string, attempt: Effect.Effect<RecoveryAttempt, E, R>, wake: Effect.Effect<void>) => Effect.Effect<RecoveryAdmission, E, R>;
|
|
358
|
+
};
|
|
359
|
+
declare const Inbox_base: Context.ServiceClass<Inbox, "@yolk-sdk/harness/Inbox", InboxApi>;
|
|
360
|
+
declare class Inbox extends Inbox_base {
|
|
361
|
+
/** Fresh queue, admission gate and HITL generations per layer acquisition. */
|
|
362
|
+
static layer: () => Layer.Layer<Inbox>;
|
|
363
|
+
}
|
|
364
|
+
/** Backward-compatible delegation to the owning inbox layer. */
|
|
365
|
+
declare const makeInMemoryInboxLayer: () => Layer.Layer<Inbox>;
|
|
366
|
+
//#endregion
|
|
367
|
+
export { DrainBegin, DrainToken, HitlAdmission, HitlDecision, Inbox, InboxApi, InboxItem, InboxKind, ParkGeneration, ParkedResponse, ParkedState, PauseDecision, RecoveryAdmission, RecoveryAttempt, makeInMemoryInboxLayer };
|
|
368
|
+
//# sourceMappingURL=inbox.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbox.d.mts","names":[],"sources":["../src/inbox.ts"],"mappings":"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"}
|