@rotorsoft/act 0.19.0 → 0.20.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.
package/dist/index.js CHANGED
@@ -1,6 +1,42 @@
1
1
  // src/ports.ts
2
2
  import { pino } from "pino";
3
3
 
4
+ // src/adapters/InMemoryCache.ts
5
+ var InMemoryCache = class {
6
+ _entries = /* @__PURE__ */ new Map();
7
+ _maxSize;
8
+ constructor(options) {
9
+ this._maxSize = options?.maxSize ?? 1e3;
10
+ }
11
+ async get(stream) {
12
+ const entry = this._entries.get(stream);
13
+ if (!entry) return void 0;
14
+ this._entries.delete(stream);
15
+ this._entries.set(stream, entry);
16
+ return entry;
17
+ }
18
+ async set(stream, entry) {
19
+ this._entries.delete(stream);
20
+ if (this._entries.size >= this._maxSize) {
21
+ const first = this._entries.keys().next().value;
22
+ this._entries.delete(first);
23
+ }
24
+ this._entries.set(stream, entry);
25
+ }
26
+ async invalidate(stream) {
27
+ this._entries.delete(stream);
28
+ }
29
+ async clear() {
30
+ this._entries.clear();
31
+ }
32
+ async dispose() {
33
+ this._entries.clear();
34
+ }
35
+ get size() {
36
+ return this._entries.size;
37
+ }
38
+ };
39
+
4
40
  // src/types/errors.ts
5
41
  var Errors = {
6
42
  ValidationError: "ERR_VALIDATION",
@@ -455,6 +491,9 @@ var SNAP_EVENT = "__snapshot__";
455
491
  var store = port(function store2(adapter) {
456
492
  return adapter || new InMemoryStore();
457
493
  });
494
+ var cache = port(function cache2(adapter) {
495
+ return adapter || new InMemoryCache();
496
+ });
458
497
  function build_tracer(logLevel2) {
459
498
  if (logLevel2 === "trace") {
460
499
  return {
@@ -556,11 +595,12 @@ async function snap(snapshot) {
556
595
  }
557
596
  }
558
597
  async function load(me, stream, callback) {
559
- let state2 = me.init ? me.init() : {};
560
- let patches = 0;
561
- let snaps = 0;
598
+ const cached = await cache().get(stream);
599
+ let state2 = cached?.state ?? (me.init ? me.init() : {});
600
+ let patches = cached?.patches ?? 0;
601
+ let snaps = cached?.snaps ?? 0;
562
602
  let event;
563
- await store().query(
603
+ const count = await store().query(
564
604
  (e) => {
565
605
  event = e;
566
606
  if (e.name === SNAP_EVENT) {
@@ -573,9 +613,12 @@ async function load(me, stream, callback) {
573
613
  }
574
614
  callback && callback({ event, state: state2, patches, snaps });
575
615
  },
576
- { stream, with_snaps: true }
616
+ { stream, with_snaps: !cached, after: cached?.event_id }
617
+ );
618
+ logger.trace(
619
+ state2,
620
+ `\u{1F7E2} load ${stream}${cached && count === 0 ? " (cached)" : ""}`
577
621
  );
578
- logger.trace(state2, `\u{1F7E2} load ${stream}`);
579
622
  return { event, state: state2, patches, snaps };
580
623
  }
581
624
  async function action(me, action2, target, payload, reactingTo, skipValidation = false) {
@@ -631,13 +674,21 @@ async function action(me, action2, target, payload, reactingTo, skipValidation =
631
674
  emitted.map((e) => e.data),
632
675
  `\u{1F534} commit ${stream}.${emitted.map((e) => e.name).join(", ")}`
633
676
  );
634
- const committed = await store().commit(
635
- stream,
636
- emitted,
637
- meta,
638
- // TODO: review reactions not enforcing expected version
639
- reactingTo ? void 0 : expected
640
- );
677
+ let committed;
678
+ try {
679
+ committed = await store().commit(
680
+ stream,
681
+ emitted,
682
+ meta,
683
+ // TODO: review reactions not enforcing expected version
684
+ reactingTo ? void 0 : expected
685
+ );
686
+ } catch (error) {
687
+ if (error.name === "ERR_CONCURRENCY") {
688
+ void cache().invalidate(stream);
689
+ }
690
+ throw error;
691
+ }
641
692
  let { state: state2, patches } = snapshot;
642
693
  const snapshots = committed.map((event) => {
643
694
  const p = me.patch[event.name](event, state2);
@@ -646,7 +697,15 @@ async function action(me, action2, target, payload, reactingTo, skipValidation =
646
697
  return { event, state: state2, patches, snaps: snapshot.snaps, patch: p };
647
698
  });
648
699
  const last = snapshots.at(-1);
649
- me.snap && me.snap(last) && void snap(last);
700
+ const snapped = me.snap && me.snap(last);
701
+ void cache().set(stream, {
702
+ state: last.state,
703
+ version: last.event.version,
704
+ event_id: last.event.id,
705
+ patches: snapped ? 0 : last.patches,
706
+ snaps: snapped ? last.snaps + 1 : last.snaps
707
+ });
708
+ if (snapped) void snap(last);
650
709
  return snapshots;
651
710
  }
652
711
 
@@ -1705,6 +1764,8 @@ export {
1705
1764
  Errors,
1706
1765
  EventMetaSchema,
1707
1766
  ExitCodes,
1767
+ InMemoryCache,
1768
+ InMemoryStore,
1708
1769
  InvariantError,
1709
1770
  LogLevels,
1710
1771
  PackageSchema,
@@ -1715,6 +1776,7 @@ export {
1715
1776
  ZodEmpty,
1716
1777
  act,
1717
1778
  build_tracer,
1779
+ cache,
1718
1780
  config,
1719
1781
  dispose,
1720
1782
  disposeAndExit,