@rotorsoft/act 0.20.0 → 0.21.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.
@@ -1 +1 @@
1
- {"version":3,"file":"InMemoryStore.d.ts","sourceRoot":"","sources":["../../../src/adapters/InMemoryStore.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EACV,SAAS,EACT,SAAS,EACT,KAAK,EACL,OAAO,EACP,KAAK,EACL,OAAO,EACP,KAAK,EACN,MAAM,mBAAmB,CAAC;AAkG3B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG;AACH,qBAAa,aAAc,YAAW,KAAK;IAEzC,OAAO,CAAC,OAAO,CAA2C;IAE1D,OAAO,CAAC,QAAQ,CAA0C;IAE1D;;;OAGG;IACG,OAAO;IAKb;;;OAGG;IACG,IAAI;IAIV;;;OAGG;IACG,IAAI;IAMV,OAAO,CAAC,QAAQ;IAUhB;;;;;OAKG;IACG,KAAK,CAAC,CAAC,SAAS,OAAO,EAC3B,QAAQ,EAAE,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,KAAK,IAAI,EAChD,KAAK,CAAC,EAAE,KAAK;IAiCf;;;;;;;;OAQG;IACG,MAAM,CAAC,CAAC,SAAS,OAAO,EAC5B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,EAC3B,IAAI,EAAE,SAAS,EACf,eAAe,CAAC,EAAE,MAAM;IAiC1B;;;;;OAKG;IACG,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;;;;;;IAyB3C;;;;;OAKG;IACG,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM;IAa3C;;;OAGG;IACG,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE;;;;;;;;IAOzB;;;;OAIG;IACG,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;;;;;;;;;CAMrD"}
1
+ {"version":3,"file":"InMemoryStore.d.ts","sourceRoot":"","sources":["../../../src/adapters/InMemoryStore.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EACV,SAAS,EACT,SAAS,EACT,KAAK,EACL,OAAO,EACP,KAAK,EACL,OAAO,EACP,KAAK,EACN,MAAM,mBAAmB,CAAC;AAkG3B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG;AACH,qBAAa,aAAc,YAAW,KAAK;IAEzC,OAAO,CAAC,OAAO,CAA2C;IAE1D,OAAO,CAAC,QAAQ,CAA0C;IAE1D;;;OAGG;IACG,OAAO;IAKb;;;OAGG;IACG,IAAI;IAIV;;;OAGG;IACG,IAAI;IAMV,OAAO,CAAC,QAAQ;IAUhB;;;;;OAKG;IACG,KAAK,CAAC,CAAC,SAAS,OAAO,EAC3B,QAAQ,EAAE,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,KAAK,IAAI,EAChD,KAAK,CAAC,EAAE,KAAK;IAiCf;;;;;;;;OAQG;IACG,MAAM,CAAC,CAAC,SAAS,OAAO,EAC5B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,EAC3B,IAAI,EAAE,SAAS,EACf,eAAe,CAAC,EAAE,MAAM;IAiC1B;;;;;;;;OAQG;IACG,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAoCxE;;;;OAIG;IACG,SAAS,CAAC,OAAO,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAYnE;;;OAGG;IACG,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE;;;;;;;;IAOzB;;;;OAIG;IACG,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;;;;;;;;;CAMrD"}
@@ -221,7 +221,10 @@ export declare const cache: (adapter?: Cache | undefined) => Cache;
221
221
  */
222
222
  export declare function build_tracer(logLevel: LogLevel): {
223
223
  fetched: <E extends Schemas>(fetched: Fetch<E>) => void;
224
- correlated: (leases: Lease[]) => void;
224
+ correlated: (streams: Array<{
225
+ stream: string;
226
+ source?: string;
227
+ }>) => void;
225
228
  leased: (leases: Lease[]) => void;
226
229
  acked: (leases: Lease[]) => void;
227
230
  blocked: (leases: Array<Lease & {
@@ -1 +1 @@
1
- {"version":3,"file":"ports.d.ts","sourceRoot":"","sources":["../../src/ports.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,KAAK,EACL,UAAU,EACV,QAAQ,EACR,KAAK,EACL,KAAK,EACL,QAAQ,EACR,OAAO,EACP,KAAK,EACN,MAAM,kBAAkB,CAAC;AAE1B;;;;;;;;;;GAUG;AAEH;;GAEG;AACH,eAAO,MAAM,SAAS,4BAA6B,CAAC;AAEpD;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC;AAElD;;;;;;;GAOG;AACH,eAAO,MAAM,MAAM,uCAajB,CAAC;AAEH;;;;;;;;;GASG;AACH,KAAK,QAAQ,CAAC,IAAI,SAAS,UAAU,IAAI,CAAC,OAAO,CAAC,EAAE,IAAI,KAAK,IAAI,CAAC;AAElE,wBAAgB,IAAI,CAAC,IAAI,SAAS,UAAU,EAAE,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,IACnD,UAAU,IAAI,KAAG,IAAI,CAQvC;AAGD,wBAAsB,cAAc,CAAC,IAAI,GAAE,QAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAa3E;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8EG;AACH,wBAAgB,OAAO,CACrB,QAAQ,CAAC,EAAE,QAAQ,GAClB,CAAC,IAAI,CAAC,EAAE,QAAQ,KAAK,OAAO,CAAC,IAAI,CAAC,CAGpC;AAED;;GAEG;AACH,eAAO,MAAM,UAAU,iBAAiB,CAAC;AAEzC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6EG;AACH,eAAO,MAAM,KAAK,wCAEhB,CAAC;AAEH;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,KAAK,wCAEhB,CAAC;AAEH;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,QAAQ,GAAG;IAChD,OAAO,EAAE,CAAC,CAAC,SAAS,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;IACxD,UAAU,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,IAAI,CAAC;IACtC,MAAM,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,IAAI,CAAC;IAClC,KAAK,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,IAAI,CAAC;IACjC,OAAO,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,KAAK,IAAI,CAAC;CAC7D,CAkDA"}
1
+ {"version":3,"file":"ports.d.ts","sourceRoot":"","sources":["../../src/ports.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,KAAK,EACL,UAAU,EACV,QAAQ,EACR,KAAK,EACL,KAAK,EACL,QAAQ,EACR,OAAO,EACP,KAAK,EACN,MAAM,kBAAkB,CAAC;AAE1B;;;;;;;;;;GAUG;AAEH;;GAEG;AACH,eAAO,MAAM,SAAS,4BAA6B,CAAC;AAEpD;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC;AAElD;;;;;;;GAOG;AACH,eAAO,MAAM,MAAM,uCAajB,CAAC;AAEH;;;;;;;;;GASG;AACH,KAAK,QAAQ,CAAC,IAAI,SAAS,UAAU,IAAI,CAAC,OAAO,CAAC,EAAE,IAAI,KAAK,IAAI,CAAC;AAElE,wBAAgB,IAAI,CAAC,IAAI,SAAS,UAAU,EAAE,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,IACnD,UAAU,IAAI,KAAG,IAAI,CAQvC;AAGD,wBAAsB,cAAc,CAAC,IAAI,GAAE,QAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAa3E;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8EG;AACH,wBAAgB,OAAO,CACrB,QAAQ,CAAC,EAAE,QAAQ,GAClB,CAAC,IAAI,CAAC,EAAE,QAAQ,KAAK,OAAO,CAAC,IAAI,CAAC,CAGpC;AAED;;GAEG;AACH,eAAO,MAAM,UAAU,iBAAiB,CAAC;AAEzC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6EG;AACH,eAAO,MAAM,KAAK,wCAEhB,CAAC;AAEH;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,KAAK,wCAEhB,CAAC;AAEH;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,QAAQ,GAAG;IAChD,OAAO,EAAE,CAAC,CAAC,SAAS,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;IACxD,UAAU,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,KAAK,IAAI,CAAC;IAC1E,MAAM,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,IAAI,CAAC;IAClC,KAAK,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,IAAI,CAAC;IACjC,OAAO,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,KAAK,IAAI,CAAC;CAC7D,CAkDA"}
@@ -5,7 +5,7 @@
5
5
  * Types and interfaces for event store ports and disposables in the Act Framework.
6
6
  */
7
7
  import type { Committed, EventMeta, Message, Query, Schema, Schemas } from "./action.js";
8
- import type { Lease, Poll } from "./reaction.js";
8
+ import type { Lease } from "./reaction.js";
9
9
  /**
10
10
  * A cached snapshot entry for a stream.
11
11
  *
@@ -170,82 +170,83 @@ export interface Store extends Disposable {
170
170
  */
171
171
  query: <E extends Schemas>(callback: (event: Committed<E, keyof E>) => void, query?: Query) => Promise<number>;
172
172
  /**
173
- * Polls for streams that need reaction processing.
174
- *
175
- * Returns streams that have uncommitted events, ordered by their watermark.
176
- * Uses a dual-frontier approach:
177
- * - **Lagging**: New or behind streams (ascending watermark)
178
- * - **Leading**: Active streams (descending watermark)
173
+ * Acknowledges successful processing of leased streams.
179
174
  *
180
- * Only returns unblocked streams that aren't currently leased.
175
+ * Updates the watermark to indicate events have been processed successfully.
176
+ * Releases the lease so other workers can process subsequent events.
181
177
  *
182
- * @param lagging - Max streams to return from lagging frontier
183
- * @param leading - Max streams to return from leading frontier
184
- * @returns Array of poll results with stream, source, watermark, and lag status
178
+ * @param leases - Leases to acknowledge with updated watermarks
179
+ * @returns Acknowledged leases
185
180
  *
186
181
  * @example
187
182
  * ```typescript
188
- * const polled = await store().poll(5, 5); // 5 lagging + 5 leading
189
- * polled.forEach(({ stream, at, lagging }) => {
190
- * console.log(`${stream} at ${at} (lagging: ${lagging})`);
191
- * });
183
+ * const leased = await store().claim(5, 5, randomUUID(), 10000);
184
+ * // Process events up to ID 150
185
+ * await store().ack(leased.map(l => ({ ...l, at: 150 })));
192
186
  * ```
193
187
  *
194
- * @see {@link Lease} for lease management
188
+ * @see {@link claim} for acquiring leases
195
189
  */
196
- poll: (lagging: number, leading: number) => Promise<Poll[]>;
190
+ ack: (leases: Lease[]) => Promise<Lease[]>;
197
191
  /**
198
- * Acquires leases for exclusive stream processing.
192
+ * Atomically discovers and leases streams for reaction processing.
193
+ *
194
+ * Combines {@link poll} and {@link lease} into a single operation, eliminating
195
+ * the race condition where another worker can grab a stream between poll and lease.
196
+ *
197
+ * PostgresStore uses `FOR UPDATE SKIP LOCKED` for zero-contention competing
198
+ * consumer semantics — workers never block each other, each grabbing different
199
+ * streams atomically. InMemoryStore fuses its poll+lease logic equivalently.
199
200
  *
200
- * Leasing prevents multiple workers from processing the same stream concurrently.
201
- * Only grants leases if:
202
- * - Stream isn't currently leased by another worker
203
- * - Lease hasn't expired
204
- * - Stream isn't blocked due to errors
201
+ * Used by `Act.drain()` as the primary stream acquisition method.
205
202
  *
206
- * @param leases - Array of lease requests
203
+ * @param lagging - Max streams from the lagging frontier (ascending watermark)
204
+ * @param leading - Max streams from the leading frontier (descending watermark)
205
+ * @param by - Unique lease holder identifier (UUID)
207
206
  * @param millis - Lease duration in milliseconds
208
- * @returns Array of successfully granted leases
207
+ * @returns Array of successfully leased streams with metadata
209
208
  *
210
209
  * @example
211
210
  * ```typescript
212
- * const granted = await store().lease([
213
- * { stream: "user-123", by: workerId, at: 0, retry: 0, lagging: false }
214
- * ], 10000); // 10 second lease
215
- *
216
- * if (granted.length > 0) {
217
- * // Process events...
218
- * await store().ack(granted);
219
- * }
211
+ * const leased = await store().claim(5, 5, randomUUID(), 10000);
212
+ * leased.forEach(({ stream, at, lagging }) => {
213
+ * console.log(`Leased ${stream} at ${at} (lagging: ${lagging})`);
214
+ * });
220
215
  * ```
221
216
  *
222
- * @see {@link poll} for finding streams to lease
217
+ * @see {@link subscribe} for registering new streams (used by correlate)
223
218
  * @see {@link ack} for acknowledging completion
219
+ * @see {@link block} for blocking failed streams
224
220
  */
225
- lease: (leases: Lease[], millis: number) => Promise<Lease[]>;
221
+ claim: (lagging: number, leading: number, by: string, millis: number) => Promise<Lease[]>;
226
222
  /**
227
- * Acknowledges successful processing of leased streams.
223
+ * Registers streams for event processing.
228
224
  *
229
- * Updates the watermark to indicate events have been processed successfully.
230
- * Releases the lease so other workers can process subsequent events.
225
+ * Upserts stream entries so they become visible to {@link claim}. Used by
226
+ * `correlate()` to register dynamically discovered reaction target streams.
231
227
  *
232
- * @param leases - Leases to acknowledge with updated watermarks
233
- * @returns Acknowledged leases
228
+ * @param streams - Streams to register with optional source hint
229
+ * @returns Number of newly registered streams (excludes already-known streams)
234
230
  *
235
231
  * @example
236
232
  * ```typescript
237
- * const leased = await store().lease([...], 10000);
238
- * // Process events up to ID 150
239
- * await store().ack(leased.map(l => ({ ...l, at: 150 })));
233
+ * const count = await store().subscribe([
234
+ * { stream: "stats-user-1", source: "user-1" },
235
+ * { stream: "stats-user-2", source: "user-2" },
236
+ * ]);
237
+ * console.log(`Registered ${count} new streams`);
240
238
  * ```
241
239
  *
242
- * @see {@link lease} for acquiring leases
240
+ * @see {@link claim} for discovering and leasing registered streams
243
241
  */
244
- ack: (leases: Lease[]) => Promise<Lease[]>;
242
+ subscribe: (streams: Array<{
243
+ stream: string;
244
+ source?: string;
245
+ }>) => Promise<number>;
245
246
  /**
246
247
  * Blocks streams after persistent processing failures.
247
248
  *
248
- * Blocked streams won't be returned by {@link poll} until manually unblocked.
249
+ * Blocked streams won't be returned by {@link claim} until manually unblocked.
249
250
  * This prevents poison messages from repeatedly failing and consuming resources.
250
251
  *
251
252
  * Streams are typically blocked when:
@@ -271,7 +272,7 @@ export interface Store extends Disposable {
271
272
  * }
272
273
  * ```
273
274
  *
274
- * @see {@link lease} for lease management
275
+ * @see {@link claim} for lease management
275
276
  */
276
277
  block: (leases: Array<Lease & {
277
278
  error: string;
@@ -1 +1 @@
1
- {"version":3,"file":"ports.d.ts","sourceRoot":"","sources":["../../../src/types/ports.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ports.d.ts","sourceRoot":"","sources":["../../../src/types/ports.ts"],"names":[],"mappings":"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"}
@@ -128,19 +128,6 @@ export type ReactionPayload<TEvents extends Schemas> = Reaction<TEvents> & {
128
128
  readonly event: Committed<TEvents, keyof TEvents>;
129
129
  readonly source?: string;
130
130
  };
131
- /**
132
- * Poll details for stream processing.
133
- * @property stream - The target stream name.
134
- * @property source - The source stream.
135
- * @property at - The lease watermark.
136
- * @property lagging - Whether the stream is lagging behind.
137
- */
138
- export type Poll = {
139
- readonly stream: string;
140
- readonly source?: string;
141
- readonly at: number;
142
- readonly lagging: boolean;
143
- };
144
131
  /**
145
132
  * Result of fetching events from the store for processing.
146
133
  * @template TEvents - Event schemas.
@@ -1 +1 @@
1
- {"version":3,"file":"reaction.d.ts","sourceRoot":"","sources":["../../../src/types/reaction.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EACV,KAAK,EACL,SAAS,EACT,UAAU,EACV,KAAK,EACL,MAAM,EACN,OAAO,EACP,QAAQ,EACT,MAAM,aAAa,CAAC;AAErB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,MAAM,eAAe,CACzB,OAAO,SAAS,OAAO,EACvB,IAAI,SAAS,MAAM,OAAO,EAC1B,QAAQ,SAAS,OAAO,GAAG,OAAO,EAClC,MAAM,SAAS,KAAK,GAAG,KAAK,IAC1B,CACF,KAAK,EAAE,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,EAC/B,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,KAC9B,OAAO,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;AAE/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,MAAM,MAAM,gBAAgB,CAC1B,OAAO,SAAS,OAAO,EACvB,IAAI,SAAS,MAAM,OAAO,IAExB;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GACnC,CAAC,CACC,KAAK,EAAE,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,KAC5B;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAAC,CAAC;AAE1D;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,MAAM,QAAQ,CAClB,OAAO,SAAS,OAAO,EACvB,IAAI,SAAS,MAAM,OAAO,GAAG,MAAM,OAAO,EAC1C,QAAQ,SAAS,OAAO,GAAG,OAAO,EAClC,MAAM,SAAS,KAAK,GAAG,KAAK,IAC1B;IACF,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;IACnE,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACnD,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;CACnC,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,MAAM,eAAe,CAAC,OAAO,SAAS,OAAO,IAAI,QAAQ,CAAC,OAAO,CAAC,GAAG;IACzE,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC;IAClD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,IAAI,GAAG;IACjB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,MAAM,KAAK,CAAC,OAAO,SAAS,OAAO,IAAI,KAAK,CAAC;IACjD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC,EAAE,CAAC;CACtD,CAAC,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,MAAM,MAAM,KAAK,GAAG;IAClB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,KAAK,CAAC,OAAO,SAAS,OAAO,IAAI;IAC3C,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC,KAAK,GAAG;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC7D,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,MAAM,aAAa,GAAG,YAAY,GAAG;IACzC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC"}
1
+ {"version":3,"file":"reaction.d.ts","sourceRoot":"","sources":["../../../src/types/reaction.ts"],"names":[],"mappings":"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"}
package/dist/index.cjs CHANGED
@@ -460,41 +460,54 @@ var InMemoryStore = class {
460
460
  });
461
461
  }
462
462
  /**
463
- * Polls the store for unblocked streams needing processing, ordered by lease watermark ascending.
464
- * @param lagging - Max number of streams to poll in ascending order.
465
- * @param leading - Max number of streams to poll in descending order.
466
- * @returns The polled streams.
463
+ * Atomically discovers and leases streams for processing.
464
+ * Fuses poll + lease into a single operation.
465
+ * @param lagging - Max streams from lagging frontier.
466
+ * @param leading - Max streams from leading frontier.
467
+ * @param by - Lease holder identifier.
468
+ * @param millis - Lease duration in milliseconds.
469
+ * @returns Granted leases.
467
470
  */
468
- async poll(lagging, leading) {
471
+ async claim(lagging, leading, by, millis) {
469
472
  await sleep();
470
- const a = [...this._streams.values()].filter((s) => s.is_avaliable).sort((a2, b2) => a2.at - b2.at).slice(0, lagging).map(({ stream, source, at }) => ({
471
- stream,
472
- source,
473
- at,
473
+ const available = [...this._streams.values()].filter((s) => s.is_avaliable);
474
+ const lag = available.sort((a, b) => a.at - b.at).slice(0, lagging).map((s) => ({
475
+ stream: s.stream,
476
+ source: s.source,
477
+ at: s.at,
474
478
  lagging: true
475
479
  }));
476
- const b = [...this._streams.values()].filter((s) => s.is_avaliable).sort((a2, b2) => b2.at - a2.at).slice(0, leading).map(({ stream, source, at }) => ({
477
- stream,
478
- source,
479
- at,
480
+ const lead = available.sort((a, b) => b.at - a.at).slice(0, leading).map((s) => ({
481
+ stream: s.stream,
482
+ source: s.source,
483
+ at: s.at,
480
484
  lagging: false
481
485
  }));
482
- return [...a, ...b];
486
+ const seen = /* @__PURE__ */ new Set();
487
+ const combined = [...lag, ...lead].filter((p) => {
488
+ if (seen.has(p.stream)) return false;
489
+ seen.add(p.stream);
490
+ return true;
491
+ });
492
+ return combined.map(
493
+ (p) => this._streams.get(p.stream)?.lease({ ...p, by, retry: 0 }, millis)
494
+ ).filter((l) => !!l);
483
495
  }
484
496
  /**
485
- * Lease streams for processing (e.g., for distributed consumers).
486
- * @param leases - Lease requests for streams, including end-of-lease watermark, lease holder, and source stream.
487
- * @param leaseMilis - Lease duration in milliseconds.
488
- * @returns Granted leases.
497
+ * Registers streams for event processing.
498
+ * @param streams - Streams to register with optional source.
499
+ * @returns Number of newly registered streams.
489
500
  */
490
- async lease(leases, millis) {
501
+ async subscribe(streams) {
491
502
  await sleep();
492
- return leases.map((l) => {
493
- if (!this._streams.has(l.stream)) {
494
- this._streams.set(l.stream, new InMemoryStream(l.stream, l.source));
503
+ let count = 0;
504
+ for (const { stream, source } of streams) {
505
+ if (!this._streams.has(stream)) {
506
+ this._streams.set(stream, new InMemoryStream(stream, source));
507
+ count++;
495
508
  }
496
- return this._streams.get(l.stream)?.lease(l, millis);
497
- }).filter((l) => !!l);
509
+ }
510
+ return count;
498
511
  }
499
512
  /**
500
513
  * Acknowledge completion of processing for leased streams.
@@ -578,8 +591,8 @@ function build_tracer(logLevel2) {
578
591
  );
579
592
  logger.trace(data, "\u26A1\uFE0F fetch");
580
593
  },
581
- correlated: (leases) => {
582
- const data = leases.map(({ stream }) => stream).join(" ");
594
+ correlated: (streams) => {
595
+ const data = streams.map(({ stream }) => stream).join(" ");
583
596
  logger.trace(`\u26A1\uFE0F correlate ${data}`);
584
597
  },
585
598
  leased: (leases) => {
@@ -1098,9 +1111,16 @@ var Act = class {
1098
1111
  this._drain_locked = true;
1099
1112
  const lagging = Math.ceil(streamLimit * this._drain_lag2lead_ratio);
1100
1113
  const leading = streamLimit - lagging;
1101
- const polled = await store().poll(lagging, leading);
1114
+ const leased = await store().claim(
1115
+ lagging,
1116
+ leading,
1117
+ (0, import_crypto2.randomUUID)(),
1118
+ leaseMillis
1119
+ );
1120
+ if (!leased.length)
1121
+ return { fetched: [], leased: [], acked: [], blocked: [] };
1102
1122
  const fetched = await Promise.all(
1103
- polled.map(async ({ stream, source, at, lagging: lagging2 }) => {
1123
+ leased.map(async ({ stream, source, at, lagging: lagging2 }) => {
1104
1124
  const events = await this.query_array({
1105
1125
  stream: source,
1106
1126
  after: at,
@@ -1109,71 +1129,60 @@ var Act = class {
1109
1129
  return { stream, source, at, lagging: lagging2, events };
1110
1130
  })
1111
1131
  );
1112
- if (fetched.length) {
1113
- tracer.fetched(fetched);
1114
- const leases = /* @__PURE__ */ new Map();
1115
- const fetch_window_at = fetched.reduce(
1116
- (max, { at, events }) => Math.max(max, events.at(-1)?.id || at),
1117
- 0
1118
- );
1119
- fetched.forEach(({ stream, lagging: lagging2, events }) => {
1120
- const payloads = events.flatMap((event) => {
1121
- const register = this.registry.events[event.name];
1122
- if (!register) return [];
1123
- return [...register.reactions.values()].filter((reaction) => {
1124
- const resolved = typeof reaction.resolver === "function" ? reaction.resolver(event) : reaction.resolver;
1125
- return resolved && resolved.target === stream;
1126
- }).map((reaction) => ({ ...reaction, event }));
1127
- });
1128
- leases.set(stream, {
1129
- lease: {
1130
- stream,
1131
- by: (0, import_crypto2.randomUUID)(),
1132
- at: events.at(-1)?.id || fetch_window_at,
1133
- // ff when no matching events
1134
- retry: 0,
1135
- lagging: lagging2
1136
- },
1137
- payloads
1138
- });
1132
+ tracer.fetched(fetched);
1133
+ const payloadsMap = /* @__PURE__ */ new Map();
1134
+ const fetch_window_at = fetched.reduce(
1135
+ (max, { at, events }) => Math.max(max, events.at(-1)?.id || at),
1136
+ 0
1137
+ );
1138
+ fetched.forEach(({ stream, events }) => {
1139
+ const payloads = events.flatMap((event) => {
1140
+ const register = this.registry.events[event.name];
1141
+ if (!register) return [];
1142
+ return [...register.reactions.values()].filter((reaction) => {
1143
+ const resolved = typeof reaction.resolver === "function" ? reaction.resolver(event) : reaction.resolver;
1144
+ return resolved && resolved.target === stream;
1145
+ }).map((reaction) => ({ ...reaction, event }));
1139
1146
  });
1140
- const leased = await store().lease(
1141
- [...leases.values()].map(({ lease }) => lease),
1142
- leaseMillis
1143
- );
1144
- tracer.leased(leased);
1145
- const handled = await Promise.all(
1146
- leased.map(
1147
- (lease) => this.handle(lease, leases.get(lease.stream).payloads)
1148
- )
1149
- );
1150
- const [lagging_handled, leading_handled] = handled.reduce(
1151
- ([lagging_handled2, leading_handled2], { lease, handled: handled2 }) => [
1152
- lagging_handled2 + (lease.lagging ? handled2 : 0),
1153
- leading_handled2 + (lease.lagging ? 0 : handled2)
1154
- ],
1155
- [0, 0]
1156
- );
1157
- const lagging_avg = lagging > 0 ? lagging_handled / lagging : 0;
1158
- const leading_avg = leading > 0 ? leading_handled / leading : 0;
1159
- const total = lagging_avg + leading_avg;
1160
- this._drain_lag2lead_ratio = total > 0 ? Math.max(0.2, Math.min(0.8, lagging_avg / total)) : 0.5;
1161
- const acked = await store().ack(
1162
- handled.filter(({ error }) => !error).map(({ at, lease }) => ({ ...lease, at }))
1163
- );
1164
- if (acked.length) {
1165
- tracer.acked(acked);
1166
- this.emit("acked", acked);
1167
- }
1168
- const blocked = await store().block(
1169
- handled.filter(({ block }) => block).map(({ lease, error }) => ({ ...lease, error }))
1170
- );
1171
- if (blocked.length) {
1172
- tracer.blocked(blocked);
1173
- this.emit("blocked", blocked);
1174
- }
1175
- return { fetched, leased, acked, blocked };
1147
+ payloadsMap.set(stream, payloads);
1148
+ });
1149
+ tracer.leased(leased);
1150
+ const handled = await Promise.all(
1151
+ leased.map((lease) => {
1152
+ const streamFetch = fetched.find((f) => f.stream === lease.stream);
1153
+ const at = streamFetch?.events.at(-1)?.id || fetch_window_at;
1154
+ return this.handle(
1155
+ { ...lease, at },
1156
+ payloadsMap.get(lease.stream) || []
1157
+ );
1158
+ })
1159
+ );
1160
+ const [lagging_handled, leading_handled] = handled.reduce(
1161
+ ([lagging_handled2, leading_handled2], { lease, handled: handled2 }) => [
1162
+ lagging_handled2 + (lease.lagging ? handled2 : 0),
1163
+ leading_handled2 + (lease.lagging ? 0 : handled2)
1164
+ ],
1165
+ [0, 0]
1166
+ );
1167
+ const lagging_avg = lagging > 0 ? lagging_handled / lagging : 0;
1168
+ const leading_avg = leading > 0 ? leading_handled / leading : 0;
1169
+ const total = lagging_avg + leading_avg;
1170
+ this._drain_lag2lead_ratio = total > 0 ? Math.max(0.2, Math.min(0.8, lagging_avg / total)) : 0.5;
1171
+ const acked = await store().ack(
1172
+ handled.filter(({ error }) => !error).map(({ at, lease }) => ({ ...lease, at }))
1173
+ );
1174
+ if (acked.length) {
1175
+ tracer.acked(acked);
1176
+ this.emit("acked", acked);
1177
+ }
1178
+ const blocked = await store().block(
1179
+ handled.filter(({ block }) => block).map(({ lease, error }) => ({ ...lease, error }))
1180
+ );
1181
+ if (blocked.length) {
1182
+ tracer.blocked(blocked);
1183
+ this.emit("blocked", blocked);
1176
1184
  }
1185
+ return { fetched, leased, acked, blocked };
1177
1186
  } catch (error) {
1178
1187
  logger.error(error);
1179
1188
  } finally {
@@ -1236,26 +1245,31 @@ var Act = class {
1236
1245
  if (register) {
1237
1246
  for (const reaction of register.reactions.values()) {
1238
1247
  const resolved = typeof reaction.resolver === "function" ? reaction.resolver(event) : reaction.resolver;
1239
- resolved && (correlated.get(resolved.target) || correlated.set(resolved.target, []).get(resolved.target)).push({ ...reaction, source: resolved.source, event });
1248
+ if (resolved) {
1249
+ const entry = correlated.get(resolved.target) || {
1250
+ source: resolved.source,
1251
+ payloads: []
1252
+ };
1253
+ entry.payloads.push({
1254
+ ...reaction,
1255
+ source: resolved.source,
1256
+ event
1257
+ });
1258
+ correlated.set(resolved.target, entry);
1259
+ }
1240
1260
  }
1241
1261
  }
1242
1262
  }, query);
1243
1263
  if (correlated.size) {
1244
- const leases = [...correlated.entries()].map(([stream, payloads]) => ({
1264
+ const streams = [...correlated.entries()].map(([stream, { source }]) => ({
1245
1265
  stream,
1246
- // TODO: by convention, the first defined source wins (this can be tricky)
1247
- source: payloads.find((p) => p.source)?.source || void 0,
1248
- by: (0, import_crypto2.randomUUID)(),
1249
- at: 0,
1250
- retry: 0,
1251
- lagging: true,
1252
- payloads
1266
+ source
1253
1267
  }));
1254
- const leased = await store().lease(leases, 0);
1255
- leased.length && tracer.correlated(leased);
1256
- return { leased, last_id };
1268
+ const subscribed = await store().subscribe(streams);
1269
+ subscribed && tracer.correlated(streams);
1270
+ return { subscribed, last_id };
1257
1271
  }
1258
- return { leased: [], last_id };
1272
+ return { subscribed: 0, last_id };
1259
1273
  }
1260
1274
  /**
1261
1275
  * Starts automatic periodic correlation worker for discovering new streams.
@@ -1319,7 +1333,7 @@ var Act = class {
1319
1333
  this._correlation_timer = setInterval(
1320
1334
  () => this.correlate({ ...query, after, limit }).then((result) => {
1321
1335
  after = result.last_id;
1322
- if (callback && result.leased.length) callback(result.leased);
1336
+ if (callback && result.subscribed) callback(result.subscribed);
1323
1337
  }).catch(console.error),
1324
1338
  frequency
1325
1339
  );
@@ -1403,8 +1417,8 @@ var Act = class {
1403
1417
  (async () => {
1404
1418
  let lastDrain;
1405
1419
  for (let i = 0; i < maxPasses; i++) {
1406
- const { leased } = await this.correlate(correlateQuery);
1407
- if (leased.length === 0 && i > 0) break;
1420
+ const { subscribed } = await this.correlate(correlateQuery);
1421
+ if (subscribed === 0 && i > 0) break;
1408
1422
  lastDrain = await this.drain(drainOptions);
1409
1423
  if (!lastDrain.acked.length && !lastDrain.blocked.length) break;
1410
1424
  }