@rotorsoft/act 0.21.0 → 0.23.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;;;;;;;;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"}
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;IA8CxE;;;;OAIG;IACG,SAAS,CAAC,OAAO,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;;;;IAgBnE;;;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"}
@@ -225,16 +225,18 @@ export interface Store extends Disposable {
225
225
  * Upserts stream entries so they become visible to {@link claim}. Used by
226
226
  * `correlate()` to register dynamically discovered reaction target streams.
227
227
  *
228
+ * Also returns the current maximum watermark across all subscribed streams,
229
+ * used internally for correlation checkpoint initialization on cold start.
230
+ *
228
231
  * @param streams - Streams to register with optional source hint
229
- * @returns Number of newly registered streams (excludes already-known streams)
232
+ * @returns `subscribed` count of newly registered streams, `watermark` max `at` across all streams
230
233
  *
231
234
  * @example
232
235
  * ```typescript
233
- * const count = await store().subscribe([
236
+ * const { subscribed, watermark } = await store().subscribe([
234
237
  * { stream: "stats-user-1", source: "user-1" },
235
238
  * { stream: "stats-user-2", source: "user-2" },
236
239
  * ]);
237
- * console.log(`Registered ${count} new streams`);
238
240
  * ```
239
241
  *
240
242
  * @see {@link claim} for discovering and leasing registered streams
@@ -242,7 +244,10 @@ export interface Store extends Disposable {
242
244
  subscribe: (streams: Array<{
243
245
  stream: string;
244
246
  source?: string;
245
- }>) => Promise<number>;
247
+ }>) => Promise<{
248
+ subscribed: number;
249
+ watermark: number;
250
+ }>;
246
251
  /**
247
252
  * Blocks streams after persistent processing failures.
248
253
  *
@@ -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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"}
package/dist/index.cjs CHANGED
@@ -470,7 +470,11 @@ var InMemoryStore = class {
470
470
  */
471
471
  async claim(lagging, leading, by, millis) {
472
472
  await sleep();
473
- const available = [...this._streams.values()].filter((s) => s.is_avaliable);
473
+ const available = [...this._streams.values()].filter(
474
+ (s) => s.is_avaliable && (s.at < 0 || this._events.some(
475
+ (e) => e.id > s.at && e.name !== SNAP_EVENT && (!s.source || RegExp(s.source).test(e.stream))
476
+ ))
477
+ );
474
478
  const lag = available.sort((a, b) => a.at - b.at).slice(0, lagging).map((s) => ({
475
479
  stream: s.stream,
476
480
  source: s.source,
@@ -496,18 +500,22 @@ var InMemoryStore = class {
496
500
  /**
497
501
  * Registers streams for event processing.
498
502
  * @param streams - Streams to register with optional source.
499
- * @returns Number of newly registered streams.
503
+ * @returns subscribed count and current max watermark.
500
504
  */
501
505
  async subscribe(streams) {
502
506
  await sleep();
503
- let count = 0;
507
+ let subscribed = 0;
504
508
  for (const { stream, source } of streams) {
505
509
  if (!this._streams.has(stream)) {
506
510
  this._streams.set(stream, new InMemoryStream(stream, source));
507
- count++;
511
+ subscribed++;
508
512
  }
509
513
  }
510
- return count;
514
+ let watermark = -1;
515
+ for (const s of this._streams.values()) {
516
+ if (s.at > watermark) watermark = s.at;
517
+ }
518
+ return { subscribed, watermark };
511
519
  }
512
520
  /**
513
521
  * Acknowledge completion of processing for leased streams.
@@ -794,15 +802,21 @@ async function action(me, action2, target, payload, reactingTo, skipValidation =
794
802
  // src/act.ts
795
803
  var tracer = build_tracer(config().logLevel);
796
804
  var Act = class {
797
- /**
798
- * Create a new Act orchestrator.
799
- *
800
- * @param registry The registry of state, event, and action schemas
801
- * @param states Map of state names to their (potentially merged) state definitions
802
- */
803
805
  constructor(registry, _states = /* @__PURE__ */ new Map()) {
804
806
  this.registry = registry;
805
807
  this._states = _states;
808
+ const statics = [];
809
+ for (const register of Object.values(this.registry.events)) {
810
+ for (const reaction of register.reactions.values()) {
811
+ if (typeof reaction.resolver === "function") {
812
+ this._has_dynamic_resolvers = true;
813
+ } else if (reaction.resolver) {
814
+ const r = reaction.resolver;
815
+ statics.push({ stream: r.target, source: r.source });
816
+ }
817
+ }
818
+ }
819
+ this._static_targets = statics;
806
820
  dispose(() => {
807
821
  this._emitter.removeAllListeners();
808
822
  this.stop_correlations();
@@ -816,6 +830,10 @@ var Act = class {
816
830
  _correlation_timer = void 0;
817
831
  _settle_timer = void 0;
818
832
  _settling = false;
833
+ _correlation_checkpoint = -1;
834
+ _subscribed_statics = /* @__PURE__ */ new Set();
835
+ _has_dynamic_resolvers = false;
836
+ _correlation_initialized = false;
819
837
  emit(event, args) {
820
838
  return this._emitter.emit(event, args);
821
839
  }
@@ -827,6 +845,14 @@ var Act = class {
827
845
  this._emitter.off(event, listener);
828
846
  return this;
829
847
  }
848
+ /**
849
+ * Create a new Act orchestrator.
850
+ *
851
+ * @param registry The registry of state, event, and action schemas
852
+ * @param states Map of state names to their (potentially merged) state definitions
853
+ */
854
+ /** Static resolver targets collected at build time */
855
+ _static_targets;
830
856
  /**
831
857
  * Executes an action on a state instance, committing resulting events.
832
858
  *
@@ -1236,37 +1262,67 @@ var Act = class {
1236
1262
  * @see {@link start_correlations} for automatic periodic correlation
1237
1263
  * @see {@link stop_correlations} to stop automatic correlation
1238
1264
  */
1265
+ /**
1266
+ * Initialize correlation state on first call.
1267
+ * - Reads max(at) from store as cold-start checkpoint
1268
+ * - Subscribes static resolver targets (idempotent upsert)
1269
+ * - Populates the subscribed statics set
1270
+ * @internal
1271
+ */
1272
+ async _init_correlation() {
1273
+ if (this._correlation_initialized) return;
1274
+ this._correlation_initialized = true;
1275
+ const { watermark } = await store().subscribe(this._static_targets);
1276
+ this._correlation_checkpoint = watermark;
1277
+ for (const { stream } of this._static_targets) {
1278
+ this._subscribed_statics.add(stream);
1279
+ }
1280
+ }
1239
1281
  async correlate(query = { after: -1, limit: 10 }) {
1282
+ await this._init_correlation();
1283
+ if (!this._has_dynamic_resolvers)
1284
+ return { subscribed: 0, last_id: this._correlation_checkpoint };
1285
+ const after = Math.max(this._correlation_checkpoint, query.after || -1);
1240
1286
  const correlated = /* @__PURE__ */ new Map();
1241
- let last_id = query.after || -1;
1242
- await store().query((event) => {
1243
- last_id = event.id;
1244
- const register = this.registry.events[event.name];
1245
- if (register) {
1246
- for (const reaction of register.reactions.values()) {
1247
- const resolved = typeof reaction.resolver === "function" ? reaction.resolver(event) : reaction.resolver;
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);
1287
+ let last_id = after;
1288
+ await store().query(
1289
+ (event) => {
1290
+ last_id = event.id;
1291
+ const register = this.registry.events[event.name];
1292
+ if (register) {
1293
+ for (const reaction of register.reactions.values()) {
1294
+ if (typeof reaction.resolver !== "function") continue;
1295
+ const resolved = reaction.resolver(event);
1296
+ if (resolved && !this._subscribed_statics.has(resolved.target)) {
1297
+ const entry = correlated.get(resolved.target) || {
1298
+ source: resolved.source,
1299
+ payloads: []
1300
+ };
1301
+ entry.payloads.push({
1302
+ ...reaction,
1303
+ source: resolved.source,
1304
+ event
1305
+ });
1306
+ correlated.set(resolved.target, entry);
1307
+ }
1259
1308
  }
1260
1309
  }
1261
- }
1262
- }, query);
1310
+ },
1311
+ { ...query, after }
1312
+ );
1313
+ this._correlation_checkpoint = last_id;
1263
1314
  if (correlated.size) {
1264
1315
  const streams = [...correlated.entries()].map(([stream, { source }]) => ({
1265
1316
  stream,
1266
1317
  source
1267
1318
  }));
1268
- const subscribed = await store().subscribe(streams);
1269
- subscribed && tracer.correlated(streams);
1319
+ const { subscribed } = await store().subscribe(streams);
1320
+ if (subscribed) {
1321
+ tracer.correlated(streams);
1322
+ for (const { stream } of streams) {
1323
+ this._subscribed_statics.add(stream);
1324
+ }
1325
+ }
1270
1326
  return { subscribed, last_id };
1271
1327
  }
1272
1328
  return { subscribed: 0, last_id };
@@ -1329,10 +1385,8 @@ var Act = class {
1329
1385
  start_correlations(query = {}, frequency = 1e4, callback) {
1330
1386
  if (this._correlation_timer) return false;
1331
1387
  const limit = query.limit || 100;
1332
- let after = query.after || -1;
1333
1388
  this._correlation_timer = setInterval(
1334
- () => this.correlate({ ...query, after, limit }).then((result) => {
1335
- after = result.last_id;
1389
+ () => this.correlate({ ...query, after: this._correlation_checkpoint, limit }).then((result) => {
1336
1390
  if (callback && result.subscribed) callback(result.subscribed);
1337
1391
  }).catch(console.error),
1338
1392
  frequency
@@ -1415,9 +1469,13 @@ var Act = class {
1415
1469
  if (this._settling) return;
1416
1470
  this._settling = true;
1417
1471
  (async () => {
1472
+ await this._init_correlation();
1418
1473
  let lastDrain;
1419
1474
  for (let i = 0; i < maxPasses; i++) {
1420
- const { subscribed } = await this.correlate(correlateQuery);
1475
+ const { subscribed } = await this.correlate({
1476
+ ...correlateQuery,
1477
+ after: this._correlation_checkpoint
1478
+ });
1421
1479
  if (subscribed === 0 && i > 0) break;
1422
1480
  lastDrain = await this.drain(drainOptions);
1423
1481
  if (!lastDrain.acked.length && !lastDrain.blocked.length) break;