reactor-effect-client 0.3.3 → 0.3.4

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 CHANGED
@@ -162,6 +162,8 @@ The adapter exposes autoplay, flush, playback, reset, and other model controls a
162
162
 
163
163
  `ClipRequest.sameSessionAs` targets the physical session that owns a known clip, including one already ready or playing, while leaving queue position unchanged. `before` requests insertion ahead of a clip still in the generation queue. Source affinity, insertion anchors, continuation, and sequence ownership must agree; missing, conflicting, retired, or recovering ownership fails locally with a `not-submitted` outcome. This keeps a dependent request on its required session during renewal without inventing an insertion point.
164
164
 
165
+ `Orchestration.makeLineup({ filler })` is opt-in scheduling for clips that must play in the order they were written with filler in between, such as a host's spoken lines between idle moments. It enqueues each clip behind the clips already waiting and ahead of all waiting filler, moves it once Ready directly behind the Ready clips, and keeps `filler.ready` filler clips from `filler.clip(n)` Ready behind the playing clip, built one at a time. Clips overtake filler only, never each other or a clip the lineup did not enqueue, and with autoplay on nothing is cut. `enqueue` returns the clip's id, its `fate` (`Started`, with the start's observed time and length, or `Failed`, including a clip lost with its session, removed with `remove`, or still waiting when the orchestration ends) and `remove`. `state` says whether a lineup clip, filler or another clip is playing, how many filler clips are Ready and how often playout ran dry. The lineup knows its own clips by the requests it captured, so it reads no clip metadata. `layerLineup(options)` provides it as the `Lineup` service over the `Engine` in context.
166
+
165
167
  `Orchestration.Submission` models an inert prepared operation. Preparation may be interrupted before commit; once execution commits, callers joining or abandoning the result do not replay the dispatch. `CommandFailure.context` distinguishes `not-submitted`, `unknown`, and `replied` outcomes independently of the transport error category, and an engine command fails with `EngineError`, a `CommandFailure` or a local `PolicyFailure`.
166
168
 
167
169
  `Orchestration.Sequences` owns bounded sequence affinity and explicit member outcomes. Partial admission is represented member-by-member as accepted, rejected, or indeterminate, and a sequence remains bound to one owner until it is sealed/retired and explicitly released.
@@ -8,6 +8,8 @@ export type { H3Source, SessionSourceOptions } from "./h3-source.js";
8
8
  export { layer, make } from "./renewal.js";
9
9
  export type { Options, Opened, Renewal, MediaTail } from "./renewal.js";
10
10
  export { Allocation, openH3, resumeH3 } from "./open-h3.js";
11
+ export { Lineup, layerLineup, makeLineup } from "./lineup.js";
12
+ export type { ClipFate, LineupClip, LineupOptions, LineupShape, LineupState } from "./lineup.js";
11
13
  export type { Allocated, OpenedH3, OpenH3Options, ResumeH3Options } from "./open-h3.js";
12
14
  export * as References from "./references.js";
13
15
  export * as Sequences from "../Sequence.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/orchestration/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,cAAc,EACd,cAAc,EACd,MAAM,EACN,aAAa,GACd,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC5F,OAAO,EACL,MAAM,EACN,KAAK,EACL,MAAM,EACN,WAAW,EACX,WAAW,EACX,aAAa,EACb,aAAa,EACb,aAAa,GACd,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,UAAU,EACV,eAAe,EACf,QAAQ,EACR,WAAW,EACX,WAAW,EACX,UAAU,EACV,UAAU,EACV,WAAW,EACX,MAAM,EACN,WAAW,EACX,WAAW,EACX,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,YAAY,EACZ,WAAW,EACX,aAAa,GACd,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAChG,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC5D,YAAY,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACrE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAC3C,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC5D,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACxF,OAAO,KAAK,UAAU,MAAM,iBAAiB,CAAC;AAC9C,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAC;AAC5C,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/orchestration/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,cAAc,EACd,cAAc,EACd,MAAM,EACN,aAAa,GACd,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC5F,OAAO,EACL,MAAM,EACN,KAAK,EACL,MAAM,EACN,WAAW,EACX,WAAW,EACX,aAAa,EACb,aAAa,EACb,aAAa,GACd,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,UAAU,EACV,eAAe,EACf,QAAQ,EACR,WAAW,EACX,WAAW,EACX,UAAU,EACV,UAAU,EACV,WAAW,EACX,MAAM,EACN,WAAW,EACX,WAAW,EACX,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,YAAY,EACZ,WAAW,EACX,aAAa,GACd,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAChG,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC5D,YAAY,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACrE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAC3C,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9D,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,aAAa,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACjG,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACxF,OAAO,KAAK,UAAU,MAAM,iBAAiB,CAAC;AAC9C,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAC;AAC5C,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC"}
@@ -5,6 +5,7 @@ export { emptyState, isIdle, isLive, committedMs, securedMs, pendingCount } from
5
5
  export { fromH3Session, isLocalClip } from "./h3-source.js";
6
6
  export { layer, make } from "./renewal.js";
7
7
  export { Allocation, openH3, resumeH3 } from "./open-h3.js";
8
+ export { Lineup, layerLineup, makeLineup } from "./lineup.js";
8
9
  export * as References from "./references.js";
9
10
  export * as Sequences from "../Sequence.js";
10
11
  export * as Submission from "../Submission.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/orchestration/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,cAAc,EACd,cAAc,EACd,MAAM,EACN,aAAa,GACd,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC5F,OAAO,EACL,MAAM,EACN,KAAK,EACL,MAAM,EACN,WAAW,EACX,WAAW,EACX,aAAa,EACb,aAAa,EACb,aAAa,GACd,MAAM,YAAY,CAAC;AAqBpB,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAChG,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE5D,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAE3C,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE5D,OAAO,KAAK,UAAU,MAAM,iBAAiB,CAAC;AAC9C,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAC;AAC5C,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/orchestration/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,cAAc,EACd,cAAc,EACd,MAAM,EACN,aAAa,GACd,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC5F,OAAO,EACL,MAAM,EACN,KAAK,EACL,MAAM,EACN,WAAW,EACX,WAAW,EACX,aAAa,EACb,aAAa,EACb,aAAa,GACd,MAAM,YAAY,CAAC;AAqBpB,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAChG,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE5D,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAE3C,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAG9D,OAAO,KAAK,UAAU,MAAM,iBAAiB,CAAC;AAC9C,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAC;AAC5C,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,90 @@
1
+ import * as Context from "effect/Context";
2
+ import * as Effect from "effect/Effect";
3
+ import * as Layer from "effect/Layer";
4
+ import type * as Scope from "effect/Scope";
5
+ import { ReactorError } from "../errors.js";
6
+ import { ClipRequest, PolicyFailure } from "./request.js";
7
+ import type { ClipId } from "./request.js";
8
+ import { Engine } from "./types.js";
9
+ import type { EngineError, RemoveOutcome } from "./types.js";
10
+ /**
11
+ * How a lineup clip began playing, or why it never will. `at` is when the
12
+ * start was observed, in milliseconds since the epoch, as the engine's
13
+ * `Started` event reports it.
14
+ */
15
+ export type ClipFate = {
16
+ readonly _tag: "Started";
17
+ readonly at: number;
18
+ readonly durationSeconds: number;
19
+ } | {
20
+ readonly _tag: "Failed";
21
+ readonly reason: string;
22
+ };
23
+ /** A clip the lineup enqueued. */
24
+ export interface LineupClip {
25
+ readonly clipId: ClipId;
26
+ /**
27
+ * Waits for the clip to start or fail. A clip lost with its session,
28
+ * removed with `remove`, or still waiting when the orchestration fails or
29
+ * closes has failed.
30
+ */
31
+ readonly fate: Effect.Effect<ClipFate>;
32
+ /** Takes the clip out of its queue before it starts; its fate is then a failure. */
33
+ readonly remove: Effect.Effect<RemoveOutcome, EngineError>;
34
+ }
35
+ export interface LineupOptions {
36
+ /** What plays while no clip is waiting. */
37
+ readonly filler: {
38
+ /** Filler clips kept Ready behind the playing clip, from 1 to 1024. */
39
+ readonly ready: number;
40
+ /** The nth filler clip, counting from zero. */
41
+ readonly clip: (n: number) => ClipRequest;
42
+ };
43
+ }
44
+ export interface LineupState {
45
+ /** What is playing: a lineup clip, filler, a clip the lineup did not enqueue, or nothing. */
46
+ readonly playing: "clip" | "filler" | "other" | "none";
47
+ /** Filler clips Ready behind the playing clip. */
48
+ readonly readyFiller: number;
49
+ /** How many times playout ran dry since the lineup started. */
50
+ readonly starved: number;
51
+ }
52
+ export interface LineupShape {
53
+ /**
54
+ * Enqueues a clip behind the clips already waiting and ahead of all waiting
55
+ * filler. The lineup chooses its place, so a request that names its own
56
+ * `position` or `before` is refused.
57
+ */
58
+ readonly enqueue: (request: ClipRequest) => Effect.Effect<LineupClip, EngineError>;
59
+ readonly state: Effect.Effect<LineupState>;
60
+ }
61
+ declare const Lineup_base: Context.ServiceClass<Lineup, "reactor-effect-client/Orchestration/Lineup", LineupShape>;
62
+ /** A lineup over the orchestration's `Engine`; `layerLineup` provides it. */
63
+ export declare class Lineup extends Lineup_base {
64
+ }
65
+ /**
66
+ * Clips ahead of filler: the clips an application enqueues play in the order
67
+ * it enqueued them, and filler keeps playout from running dry in between.
68
+ *
69
+ * - A clip is enqueued behind the clips already waiting and ahead of every
70
+ * waiting filler clip. Once Ready it moves directly behind the Ready clips,
71
+ * so clips overtake filler only, never each other. A clip the lineup did not
72
+ * enqueue, such as one in a resumed session's queue, counts as a clip.
73
+ * - `filler.ready` filler clips are kept Ready behind the playing clip and
74
+ * built one at a time, so a clip waits behind one filler build at worst.
75
+ * - Playback is the orchestration's autoplay, which is on unless the
76
+ * application turns it off: a Ready clip starts when the playing clip ends,
77
+ * so nothing is cut.
78
+ *
79
+ * The lineup knows its own clips by the requests it captured, so it reads no
80
+ * clip metadata. It reorders and refills after each engine change
81
+ * and at least once a second, which covers a quiet engine such as a
82
+ * replacement session that starts empty. During a renewal's overlap a clip's
83
+ * place counts both sessions' queues, so it may wait behind one more filler
84
+ * build, and it still passes no clip.
85
+ */
86
+ export declare const makeLineup: (options: LineupOptions) => Effect.Effect<LineupShape, ReactorError | PolicyFailure, Engine | Scope.Scope>;
87
+ /** The lineup as a service, over the `Engine` in context. */
88
+ export declare const layerLineup: (options: LineupOptions) => Layer.Layer<Lineup, ReactorError | PolicyFailure, Engine>;
89
+ export {};
90
+ //# sourceMappingURL=lineup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lineup.d.ts","sourceRoot":"","sources":["../../src/orchestration/lineup.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAE1C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAItC,OAAO,KAAK,KAAK,KAAK,MAAM,cAAc,CAAC;AAG3C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAkB,WAAW,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC1E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAE3C,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACpC,OAAO,KAAK,EAAc,WAAW,EAA4B,aAAa,EAAE,MAAM,YAAY,CAAC;AAEnG;;;;GAIG;AACH,MAAM,MAAM,QAAQ,GAChB;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;CAAE,GACnF;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzD,kCAAkC;AAClC,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACvC,oFAAoF;IACpF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;CAC5D;AAED,MAAM,WAAW,aAAa;IAC5B,2CAA2C;IAC3C,QAAQ,CAAC,MAAM,EAAE;QACf,uEAAuE;QACvE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,+CAA+C;QAC/C,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,WAAW,CAAC;KAC3C,CAAC;CACH;AAED,MAAM,WAAW,WAAW;IAC1B,6FAA6F;IAC7F,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;IACvD,kDAAkD;IAClD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,+DAA+D;IAC/D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;IACnF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;CAC5C;;AAED,6EAA6E;AAC7E,qBAAa,MAAO,SAAQ,WAE3B;CAAG;AAOJ;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,UAAU,YACZ,aAAa,KACrB,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,YAAY,GAAG,aAAa,EAAE,MAAM,GAAG,KAAK,CAAC,KAAK,CA+N5E,CAAC;AAEL,6DAA6D;AAC7D,eAAO,MAAM,WAAW,YACb,aAAa,KACrB,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,YAAY,GAAG,aAAa,EAAE,MAAM,CAChB,CAAC"}
@@ -0,0 +1,222 @@
1
+ import * as Clock from "effect/Clock";
2
+ import * as Context from "effect/Context";
3
+ import * as Deferred from "effect/Deferred";
4
+ import * as Effect from "effect/Effect";
5
+ import * as Exit from "effect/Exit";
6
+ import * as Layer from "effect/Layer";
7
+ import * as Option from "effect/Option";
8
+ import * as Queue from "effect/Queue";
9
+ import * as Result from "effect/Result";
10
+ import * as Semaphore from "effect/Semaphore";
11
+ import * as Stream from "effect/Stream";
12
+ import { ReactorError } from "../errors.js";
13
+ import { captureRequest, ClipRequest, PolicyFailure } from "./request.js";
14
+ import { generation } from "./routing.js";
15
+ import { Engine } from "./types.js";
16
+ /** A lineup over the orchestration's `Engine`; `layerLineup` provides it. */
17
+ export class Lineup extends Context.Service()("reactor-effect-client/Orchestration/Lineup") {
18
+ }
19
+ const logDebug = (message, reason) => Effect.logDebug(message, { reason }).pipe(Effect.annotateLogs({ module: "reactor.orchestration" }));
20
+ /**
21
+ * Clips ahead of filler: the clips an application enqueues play in the order
22
+ * it enqueued them, and filler keeps playout from running dry in between.
23
+ *
24
+ * - A clip is enqueued behind the clips already waiting and ahead of every
25
+ * waiting filler clip. Once Ready it moves directly behind the Ready clips,
26
+ * so clips overtake filler only, never each other. A clip the lineup did not
27
+ * enqueue, such as one in a resumed session's queue, counts as a clip.
28
+ * - `filler.ready` filler clips are kept Ready behind the playing clip and
29
+ * built one at a time, so a clip waits behind one filler build at worst.
30
+ * - Playback is the orchestration's autoplay, which is on unless the
31
+ * application turns it off: a Ready clip starts when the playing clip ends,
32
+ * so nothing is cut.
33
+ *
34
+ * The lineup knows its own clips by the requests it captured, so it reads no
35
+ * clip metadata. It reorders and refills after each engine change
36
+ * and at least once a second, which covers a quiet engine such as a
37
+ * replacement session that starts empty. During a renewal's overlap a clip's
38
+ * place counts both sessions' queues, so it may wait behind one more filler
39
+ * build, and it still passes no clip.
40
+ */
41
+ export const makeLineup = (options) => Effect.gen(function* () {
42
+ const engine = yield* Engine;
43
+ const target = options.filler.ready;
44
+ if (!Number.isSafeInteger(target) || target < 1 || target > 1024)
45
+ return yield* ReactorError.fromCode("InvalidInput", "A lineup keeps from 1 to 1024 filler clips Ready");
46
+ const fillers = new WeakSet();
47
+ const clips = new WeakSet();
48
+ const fillerAt = (n) => captureRequest(options.filler.clip(n)).pipe(Effect.tap((request) => Effect.sync(() => fillers.add(request))));
49
+ // A malformed filler request fails the lineup here rather than every refill later.
50
+ yield* fillerAt(0);
51
+ let made = 0;
52
+ const isFiller = (record) => record.request !== undefined && fillers.has(record.request);
53
+ const isClip = (record) => record.request !== undefined && clips.has(record.request);
54
+ const playing = (state) => {
55
+ if (Option.isNone(state.playing))
56
+ return "none";
57
+ const record = state.playing.value.record;
58
+ if (Option.isNone(record))
59
+ return "other";
60
+ return isFiller(record.value) ? "filler" : isClip(record.value) ? "clip" : "other";
61
+ };
62
+ const permit = yield* Semaphore.make(1);
63
+ const changed = yield* Queue.dropping(1);
64
+ const waiting = new Map();
65
+ // Fates observed while an enqueue waits for its reply, before the reply names
66
+ // the clip: a clip can fail before its enqueue returns.
67
+ let unclaimed;
68
+ let ended;
69
+ let starved = 0;
70
+ const release = (clipId, fate) => Effect.suspend(() => {
71
+ const waiter = waiting.get(clipId);
72
+ if (waiter === undefined)
73
+ return Effect.succeed(false);
74
+ waiting.delete(clipId);
75
+ return Effect.as(Deferred.succeed(waiter, fate), true);
76
+ });
77
+ const settle = (clipId, fate) => release(clipId, fate).pipe(Effect.tap((released) => Effect.sync(() => {
78
+ if (!released)
79
+ unclaimed?.set(clipId, fate);
80
+ })));
81
+ const settleAll = (reason) => Effect.suspend(() => {
82
+ ended = reason;
83
+ const waiters = [...waiting.values()];
84
+ waiting.clear();
85
+ return Effect.forEach(waiters, (waiter) => Deferred.succeed(waiter, { _tag: "Failed", reason }), { discard: true });
86
+ });
87
+ yield* Effect.addFinalizer(() => settleAll("The lineup closed"));
88
+ // Ready clips take the front of playout in the order they already have: each
89
+ // moves only forward, and only over filler. The moves come from one reading
90
+ // of the state, which each move leaves true for the clips after it. A move
91
+ // that fails means its clip started or left, and that change wakes the next pass.
92
+ const order = Effect.gen(function* () {
93
+ const ready = (yield* engine.state).ready;
94
+ const ahead = ready.flatMap((record, index) => (isFiller(record) ? [] : [{ record, index }]));
95
+ for (const [rank, clip] of ahead.entries()) {
96
+ if (clip.index === rank)
97
+ continue;
98
+ const moved = yield* Effect.result(engine.move(clip.record.clipId, rank, "playout"));
99
+ if (Result.isFailure(moved))
100
+ return;
101
+ }
102
+ });
103
+ // One filler clip at most waits for generation, enqueued only while fewer
104
+ // than `ready` are Ready, so a clip queues behind one filler build at worst.
105
+ const refill = Effect.gen(function* () {
106
+ const state = yield* engine.state;
107
+ if (state.availability !== "Ready")
108
+ return;
109
+ if (generation(state).some(isFiller))
110
+ return;
111
+ if (state.ready.filter(isFiller).length >= target)
112
+ return;
113
+ yield* engine.enqueue(yield* fillerAt(made++));
114
+ });
115
+ const reconcile = permit
116
+ .withPermit(Effect.andThen(order, refill))
117
+ .pipe(Effect.catch((failure) => logDebug("lineup reconcile deferred", failure.reason._tag)));
118
+ const record = (event) => {
119
+ switch (event._tag) {
120
+ case "Started":
121
+ return Effect.asVoid(settle(event.clipId, {
122
+ _tag: "Started",
123
+ at: event.at,
124
+ durationSeconds: event.durationSeconds,
125
+ }));
126
+ case "Failed":
127
+ return Effect.asVoid(settle(event.clipId, { _tag: "Failed", reason: event.reason }));
128
+ case "Starved":
129
+ return Effect.sync(() => {
130
+ starved++;
131
+ });
132
+ case "SessionFailed":
133
+ return settleAll(`The orchestration failed: ${event.failure.message}`);
134
+ default:
135
+ return Effect.void;
136
+ }
137
+ };
138
+ // After an observer falls behind, the fresh state settles what it can: a
139
+ // waiting clip that is playing has started, and one that is listed failed has failed.
140
+ const recover = (state) => Effect.gen(function* () {
141
+ const playing = Option.getOrUndefined(state.playing);
142
+ const now = yield* Clock.currentTimeMillis;
143
+ for (const clipId of [...waiting.keys()]) {
144
+ if (playing?.clipId === clipId && Option.isSome(playing.record))
145
+ yield* settle(clipId, {
146
+ _tag: "Started",
147
+ at: Option.getOrElse(playing.startedAt, () => now),
148
+ durationSeconds: playing.record.value.durationSeconds,
149
+ });
150
+ else if (state.failed.includes(clipId))
151
+ yield* settle(clipId, { _tag: "Failed", reason: "The clip failed unobserved" });
152
+ }
153
+ });
154
+ const wake = Effect.sync(() => Queue.offerUnsafe(changed, undefined));
155
+ const observe = Effect.scoped(Effect.gen(function* () {
156
+ const observation = yield* engine.observe({ capacity: 4096 });
157
+ yield* recover(observation.initial);
158
+ yield* wake;
159
+ yield* observation.events.pipe(Stream.runForEach((event) => Effect.andThen(record(event),
160
+ // Queued and Building follow the lineup's own enqueues: nothing to reorder.
161
+ event._tag === "Queued" || event._tag === "Building" ? Effect.void : wake)));
162
+ }));
163
+ // The events end when the orchestration closes. An observer 4096 events behind
164
+ // observes again from a fresh state; any other failure ends the lineup's view.
165
+ const watch = Effect.gen(function* () {
166
+ for (;;) {
167
+ const observed = yield* Effect.result(observe);
168
+ if (Result.isSuccess(observed))
169
+ return yield* settleAll("The orchestration closed");
170
+ if (observed.failure.reason._tag !== "Overflow")
171
+ return yield* settleAll(`The engine's events failed: ${observed.failure.message}`);
172
+ yield* logDebug("lineup observer fell behind", "Overflow");
173
+ }
174
+ });
175
+ yield* Effect.forkScoped(watch);
176
+ // The reconciler never holds up the observer, so a fate settles as soon as it
177
+ // is seen, even while an enqueue holds the permit.
178
+ yield* Effect.forkScoped(Effect.gen(function* () {
179
+ while (ended === undefined) {
180
+ yield* Effect.timeoutOption(Queue.take(changed), "1 second");
181
+ yield* reconcile;
182
+ }
183
+ }));
184
+ const remove = (clipId) => engine
185
+ .remove(clipId)
186
+ .pipe(Effect.tap(() => release(clipId, { _tag: "Failed", reason: "Removed" })));
187
+ const enqueue = (input) => permit.withPermit(Effect.gen(function* () {
188
+ if (input.position !== undefined || input.before !== undefined)
189
+ return yield* PolicyFailure.refuse("InvalidRequest", "A lineup chooses where its clips go", "enqueue");
190
+ const last = generation(yield* engine.state).findLastIndex((record) => !isFiller(record));
191
+ const request = yield* captureRequest(new ClipRequest({ ...input, position: last + 1 }));
192
+ clips.add(request);
193
+ const fate = yield* Deferred.make();
194
+ const seen = new Map();
195
+ unclaimed = seen;
196
+ const clipId = yield* engine.enqueue(request).pipe(Effect.onExit((exit) => Exit.isFailure(exit)
197
+ ? Effect.sync(() => {
198
+ unclaimed = undefined;
199
+ })
200
+ : Effect.void));
201
+ // From here to registering the waiter nothing yields, so no fate is missed.
202
+ const early = seen.get(clipId) ??
203
+ (ended === undefined ? undefined : { _tag: "Failed", reason: ended });
204
+ unclaimed = undefined;
205
+ if (early === undefined)
206
+ waiting.set(clipId, fate);
207
+ else
208
+ yield* Deferred.succeed(fate, early);
209
+ return { clipId, fate: Deferred.await(fate), remove: remove(clipId) };
210
+ }));
211
+ return {
212
+ enqueue,
213
+ state: Effect.map(engine.state, (state) => ({
214
+ playing: playing(state),
215
+ readyFiller: state.ready.filter(isFiller).length,
216
+ starved,
217
+ })),
218
+ };
219
+ });
220
+ /** The lineup as a service, over the `Engine` in context. */
221
+ export const layerLineup = (options) => Layer.effect(Lineup, makeLineup(options));
222
+ //# sourceMappingURL=lineup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lineup.js","sourceRoot":"","sources":["../../src/orchestration/lineup.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "reactor-effect-client",
3
- "version": "0.3.3",
3
+ "version": "0.3.4",
4
4
  "description": "Scoped Reactor sessions, H3 provider state and explicit orchestration over Effect",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -59,7 +59,7 @@
59
59
  "@effect/vitest": "^4.0.0-rc.117",
60
60
  "@types/node": "22.20.2",
61
61
  "effect": "^4.0.0-rc.117",
62
- "reactor-effect-test-kit": "0.3.3",
62
+ "reactor-effect-test-kit": "0.3.4",
63
63
  "vitest": "5.0.0"
64
64
  },
65
65
  "scripts": {