@kairos-es/core 0.0.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.
Files changed (89) hide show
  1. package/LICENSE +28 -0
  2. package/README.md +33 -0
  3. package/dist/cjs/AppendCondition.js +26 -0
  4. package/dist/cjs/AppendCondition.js.map +1 -0
  5. package/dist/cjs/ContractStore.js +80 -0
  6. package/dist/cjs/ContractStore.js.map +1 -0
  7. package/dist/cjs/DcbEventStore.js +10 -0
  8. package/dist/cjs/DcbEventStore.js.map +1 -0
  9. package/dist/cjs/Event.js +89 -0
  10. package/dist/cjs/Event.js.map +1 -0
  11. package/dist/cjs/Projection.js +73 -0
  12. package/dist/cjs/Projection.js.map +1 -0
  13. package/dist/cjs/Query.js +221 -0
  14. package/dist/cjs/Query.js.map +1 -0
  15. package/dist/cjs/SubscribeMachine.js +235 -0
  16. package/dist/cjs/SubscribeMachine.js.map +1 -0
  17. package/dist/cjs/errors.js +22 -0
  18. package/dist/cjs/errors.js.map +1 -0
  19. package/dist/cjs/inMemory.js +191 -0
  20. package/dist/cjs/inMemory.js.map +1 -0
  21. package/dist/cjs/index.js +124 -0
  22. package/dist/cjs/index.js.map +1 -0
  23. package/dist/cjs/retryOnConflict.js +95 -0
  24. package/dist/cjs/retryOnConflict.js.map +1 -0
  25. package/dist/cjs/testing.js +54 -0
  26. package/dist/cjs/testing.js.map +1 -0
  27. package/dist/dts/AppendCondition.d.ts +23 -0
  28. package/dist/dts/AppendCondition.d.ts.map +1 -0
  29. package/dist/dts/ContractStore.d.ts +56 -0
  30. package/dist/dts/ContractStore.d.ts.map +1 -0
  31. package/dist/dts/DcbEventStore.d.ts +64 -0
  32. package/dist/dts/DcbEventStore.d.ts.map +1 -0
  33. package/dist/dts/Event.d.ts +104 -0
  34. package/dist/dts/Event.d.ts.map +1 -0
  35. package/dist/dts/Projection.d.ts +108 -0
  36. package/dist/dts/Projection.d.ts.map +1 -0
  37. package/dist/dts/Query.d.ts +145 -0
  38. package/dist/dts/Query.d.ts.map +1 -0
  39. package/dist/dts/SubscribeMachine.d.ts +179 -0
  40. package/dist/dts/SubscribeMachine.d.ts.map +1 -0
  41. package/dist/dts/errors.d.ts +17 -0
  42. package/dist/dts/errors.d.ts.map +1 -0
  43. package/dist/dts/inMemory.d.ts +76 -0
  44. package/dist/dts/inMemory.d.ts.map +1 -0
  45. package/dist/dts/index.d.ts +35 -0
  46. package/dist/dts/index.d.ts.map +1 -0
  47. package/dist/dts/retryOnConflict.d.ts +70 -0
  48. package/dist/dts/retryOnConflict.d.ts.map +1 -0
  49. package/dist/dts/testing.d.ts +39 -0
  50. package/dist/dts/testing.d.ts.map +1 -0
  51. package/dist/esm/AppendCondition.js +19 -0
  52. package/dist/esm/AppendCondition.js.map +1 -0
  53. package/dist/esm/ContractStore.js +73 -0
  54. package/dist/esm/ContractStore.js.map +1 -0
  55. package/dist/esm/DcbEventStore.js +3 -0
  56. package/dist/esm/DcbEventStore.js.map +1 -0
  57. package/dist/esm/Event.js +81 -0
  58. package/dist/esm/Event.js.map +1 -0
  59. package/dist/esm/Projection.js +66 -0
  60. package/dist/esm/Projection.js.map +1 -0
  61. package/dist/esm/Query.js +209 -0
  62. package/dist/esm/Query.js.map +1 -0
  63. package/dist/esm/SubscribeMachine.js +227 -0
  64. package/dist/esm/SubscribeMachine.js.map +1 -0
  65. package/dist/esm/errors.js +14 -0
  66. package/dist/esm/errors.js.map +1 -0
  67. package/dist/esm/inMemory.js +184 -0
  68. package/dist/esm/inMemory.js.map +1 -0
  69. package/dist/esm/index.js +38 -0
  70. package/dist/esm/index.js.map +1 -0
  71. package/dist/esm/package.json +4 -0
  72. package/dist/esm/retryOnConflict.js +87 -0
  73. package/dist/esm/retryOnConflict.js.map +1 -0
  74. package/dist/esm/testing.js +46 -0
  75. package/dist/esm/testing.js.map +1 -0
  76. package/package.json +39 -0
  77. package/src/AppendCondition.ts +18 -0
  78. package/src/ContractStore.ts +148 -0
  79. package/src/DcbEventStore.ts +77 -0
  80. package/src/Event.ts +135 -0
  81. package/src/Projection.ts +168 -0
  82. package/src/Query.ts +237 -0
  83. package/src/SubscribeMachine.ts +316 -0
  84. package/src/errors.ts +19 -0
  85. package/src/inMemory.ts +356 -0
  86. package/src/index.ts +37 -0
  87. package/src/retryOnConflict.ts +100 -0
  88. package/src/testing.ts +47 -0
  89. package/testing/package.json +6 -0
@@ -0,0 +1,235 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.subscriptionTuningFields = exports.subscribeStream = exports.DEFAULT_POLL_INTERVAL_MILLIS = exports.DEFAULT_CATCH_UP_PAGE_SIZE = void 0;
7
+ var _effect = require("effect");
8
+ var _Event = require("./Event.js");
9
+ /**
10
+ * The subscribe machine every engine's `subscribe` is built from — the in-memory
11
+ * store, `@kairos-es/store-postgres` and `@kairos-es/store-sqlite`: the wake queue,
12
+ * the wake-source drain, the paged catch-up reconcile, the `> boundary` de-dup (via
13
+ * the cursor's exclusive lower bound) and the poll loop that together turn a paged
14
+ * read into a live subscription.
15
+ *
16
+ * It lives in core because delivery semantics are contract semantics. An engine
17
+ * supplies TRANSPORT through two STUBBABLE seams — `fetch`, a paged read strictly
18
+ * after a cursor, and `listen`, an optional wake source — and inherits the delivery
19
+ * behaviour whole, exactly as it supplies mechanics to `makeContractStore` and
20
+ * inherits the contract policy whole. Two engines that each grew their own wake
21
+ * loop would be identical only by inspection, and `subscribe` is the verb where
22
+ * that is least affordable: a divergence there loses events rather than failing.
23
+ * Both seams take plain in-memory values in a test, so the wake/poll/de-dup logic
24
+ * is exercisable with no live backend at all.
25
+ *
26
+ * All THREE are the callers, and the count matters to a reader here: it means there
27
+ * is exactly ONE delivery algorithm in this repo, and it is the code below. The
28
+ * in-memory store is a caller like the rest — it hands in a `fetch` over its log
29
+ * `Ref` and its append `PubSub` as a wake source and keeps no delivery logic of its
30
+ * own — which is what makes the shared contract suite's subscribe cases a comparison
31
+ * of two BACKENDS rather than of two delivery algorithms.
32
+ *
33
+ * Correctness rests on the periodic position-based reconcile — a re-read from the
34
+ * cursor every poll interval — and NEVER on the wake source, which only lowers
35
+ * delivery latency below that interval. A subscription with no wake source at all
36
+ * is therefore complete and correct, merely slower, which is why `listen` is
37
+ * optional in the TYPE rather than by the convention of passing `Stream.never`:
38
+ * poll-only delivery is a supported shape, not a degraded one.
39
+ *
40
+ * ## The precondition every engine inherits: ASCENDING COMMIT ORDER
41
+ *
42
+ * A position that is committed and VISIBLE must never be below one already
43
+ * delivered. Gaps are fine: the cursor is an ascending exclusive lower bound, so a
44
+ * number that is allocated and never committed, or never allocated at all, is
45
+ * simply a number the machine never sees. Out-of-order commits are not fine. If one
46
+ * writer allocates position 5 and another allocates 6, and 6 commits first, a poll
47
+ * landing between the two commits delivers 6 and advances the cursor past it — and
48
+ * 5 is then lost forever, because no later read looks below the cursor and nothing
49
+ * anywhere notices the hole. An engine whose concurrent writers can commit out of
50
+ * order MUST serialise them, or this machine will silently skip. An engine that
51
+ * takes an exclusive lock on both of its append paths discharges the obligation
52
+ * that way; an engine whose append is a single statement discharges it
53
+ * structurally.
54
+ *
55
+ * The obligation is written down HERE, in the algorithm that depends on it, rather
56
+ * than in whichever engine happens to satisfy it. It is a property of this delivery
57
+ * loop and of nothing else, so an engine author reading only their own source has
58
+ * no way to discover that anything downstream needs it — and the failure mode is
59
+ * the worst kind there is: no error, no defect, no failing test, just an event that
60
+ * a subscriber never receives. A single engine owning both its append path and its
61
+ * own wake loop can leave the assumption implicit; a shared machine cannot.
62
+ *
63
+ * ## `catchUpPageSize` bounds the READ, not the emission
64
+ *
65
+ * `drainFrom` below PAGES the catch-up read — `catchUpPageSize` bounds each
66
+ * `fetch` — but it COLLECTS every page into one array, which is emitted as a SINGLE
67
+ * chunk. So peak memory at subscription start is O(backlog) rather than O(page): a
68
+ * subscriber joining behind a large log materialises the whole backlog before its
69
+ * consumer sees the first element.
70
+ *
71
+ * That is a memory characteristic and nothing more, which is why ONE chunk is
72
+ * enough here: downstream commit boundaries do not depend on the upstream chunking
73
+ * at all, because the read side's `Stream.groupedWithin` re-chunks the stream into
74
+ * bounded micro-batches whatever arrives (ADR-0007), so a projection's transactions
75
+ * stay small even against a one-chunk catch-up. The cost therefore lands on backlog
76
+ * memory alone, and it lands hardest on the durable-log-with-in-memory-view mode,
77
+ * where an ephemeral view re-catches-up the entire log on every boot.
78
+ */
79
+
80
+ /**
81
+ * A short catch-up page size default for the reconcile loop. Reads page by page
82
+ * until a short page signals the tail is drained, so a large backlog is streamed in
83
+ * bounded chunks rather than one unbounded read. Every engine takes its
84
+ * `catchUpPageSize` from here — each SQL engine as its config's default, the
85
+ * in-memory store as its options' — so backends cannot drift on tuning.
86
+ */
87
+ const DEFAULT_CATCH_UP_PAGE_SIZE = exports.DEFAULT_CATCH_UP_PAGE_SIZE = 512;
88
+ /**
89
+ * The default upper bound a subscriber waits for a wake before re-reading from its
90
+ * cursor ANYWAY (milliseconds). Every engine takes its `pollInterval` from here —
91
+ * each SQL engine as its config's default, the in-memory store as its options' — so
92
+ * backends cannot drift on tuning.
93
+ *
94
+ * This periodic position-based poll — not the wake source — IS the correctness
95
+ * guarantee: every committed position is reconciled within this interval whether or
96
+ * not a wake for it was ever heard. That covers a wake fired before the source was
97
+ * fully established, a coalesced or dropped wake, and a wake source that died
98
+ * silently and never said so. A wake source only lowers delivery latency BELOW this
99
+ * interval; it never carries delivery, so no engine's wake mechanism can make the
100
+ * right figure here engine-specific. It trades worst-case delivery latency against
101
+ * idle read volume and nothing else. Upstream `postgres_tt.py` picks the same
102
+ * one-second fallback poll (`conn.wait(..., interval=1)`).
103
+ */
104
+ const DEFAULT_POLL_INTERVAL_MILLIS = exports.DEFAULT_POLL_INTERVAL_MILLIS = 1000;
105
+ /**
106
+ * The two subscribe-tuning config FIELDS, for an engine whose config is a `Schema`
107
+ * to spread into its own struct.
108
+ *
109
+ * These knobs are the machine's, not any engine's: they name what the loop above
110
+ * does, the figures they fall back to are the two constants declared beside them,
111
+ * and neither is derivable from a backend's own properties — which is why the
112
+ * defaults already live here. Shipping the FIELD rather than only the default is
113
+ * what closes the last gap in that arrangement. An engine that spreads these gets
114
+ * the key NAME, the VALIDATION and the DEFAULT from one place, so a caller who has
115
+ * tuned one engine's subscribe reads another's without translating, and the two
116
+ * cannot drift in what they ACCEPT any more than in what they assume. Two engines
117
+ * hand-authoring the identical `Schema.optionalWith(…)` twice were identical only
118
+ * by inspection.
119
+ *
120
+ * The bounds differ between the two because the quantities do. `pollInterval` is a
121
+ * duration, so a fraction of a millisecond is meaningful and only `positive` and
122
+ * `finite` matter: at zero or below the loop would spin without ever waiting for a
123
+ * wake, and at `Infinity` the periodic re-read — the half that carries delivery —
124
+ * would never come, which silently converts the wake source from an optimisation
125
+ * into the guarantee. `catchUpPageSize` is a COUNT, so it must be an integer
126
+ * (`Schema.Int` excludes `Infinity` with it): the reconcile loop compares a page's
127
+ * length against it to decide the tail is drained, and a page of zero would report
128
+ * "drained" forever without reading anything.
129
+ *
130
+ * `exact: true` on both keeps the decoded type at `key?: T` rather than
131
+ * `T | undefined`, matching the repo's `exactOptionalPropertyTypes` discipline — an
132
+ * absent key, never an explicit `undefined`.
133
+ */
134
+ const subscriptionTuningFields = exports.subscriptionTuningFields = {
135
+ pollInterval: /*#__PURE__*/_effect.Schema.optionalWith(/*#__PURE__*/_effect.Schema.Number.pipe(/*#__PURE__*/_effect.Schema.positive(), /*#__PURE__*/_effect.Schema.finite()), {
136
+ exact: true
137
+ }),
138
+ catchUpPageSize: /*#__PURE__*/_effect.Schema.optionalWith(/*#__PURE__*/_effect.Schema.Int.pipe(/*#__PURE__*/_effect.Schema.positive()), {
139
+ exact: true
140
+ })
141
+ };
142
+ /**
143
+ * Retry a TRANSIENT poll fault (an `E` from one reconcile read) on a capped
144
+ * exponential backoff rather than letting `Stream.orDie` kill a subscription that
145
+ * may have been alive for days over a single connection blip. A fault that PERSISTS
146
+ * past the cap propagates (the decorator dies it) — infrastructure stays off the
147
+ * contract channel while the stream survives ordinary transients.
148
+ */
149
+ const POLL_RETRY_SCHEDULE = /*#__PURE__*/_effect.Schedule.exponential('100 millis', 2).pipe(/*#__PURE__*/_effect.Schedule.union(/*#__PURE__*/_effect.Schedule.spaced('2 seconds')), /*#__PURE__*/_effect.Schedule.intersect(/*#__PURE__*/_effect.Schedule.recurs(20)));
150
+ /**
151
+ * Build the subscription `Stream`: catch up from `after`, then track the live tail.
152
+ * The cursor threads through the `unfoldChunkEffect` unfold state, starting at
153
+ * `after` and advancing to the last delivered position each batch; the stream never
154
+ * completes on its own (always `Option.some`), so the enclosing scope interrupts it
155
+ * on close. An `E` mid-stream stays on the channel; `makeContractStore` dies it
156
+ * (subscribe is `E = never` on the contract).
157
+ */
158
+ const subscribeStream = (deps, after) => _effect.Stream.unwrapScoped(_effect.Effect.gen(function* () {
159
+ // The wake primitive: a sliding(1) queue holding at most one pending
160
+ // signal. The wake source `offer`s an opaque wake on every notification;
161
+ // the poll loop `take`s (with a timeout). The lost-wakeup guard is
162
+ // STRUCTURAL — drain the queue BEFORE reading, so a wake that lands
163
+ // mid-read leaves a fresh signal that makes the next `take` return at once
164
+ // rather than sleeping through a real change.
165
+ const wake = yield* _effect.Queue.sliding(1);
166
+ // Tap every notification into the wake queue. If the wake source DOES
167
+ // surface an error, re-subscribe with capped-exponential backoff. Many wake
168
+ // sources do not error on a dropped connection at all — they simply go
169
+ // quiet — so this retry is NOT the reconnect guarantee: the poll fallback
170
+ // below is. The reconcile loop re-reads from the cursor on every poll, so a
171
+ // silently-dropped (and later re-established) wake source loses no
172
+ // positions. Absent a wake source entirely, `Stream.never` makes this a
173
+ // fibre that parks forever and delivery falls to the poll alone.
174
+ const listener = (deps.listen ?? _effect.Stream.never).pipe(_effect.Stream.tap(() => _effect.Queue.offer(wake, undefined)), _effect.Stream.retry(_effect.Schedule.exponential('50 millis').pipe(_effect.Schedule.union(_effect.Schedule.spaced('1 seconds')))));
175
+ // Drain the wake source into the wake queue on a background fibre; the
176
+ // scope releases it. We never read its elements directly — every
177
+ // notification is an opaque wake signal.
178
+ yield* listener.pipe(_effect.Stream.runDrain, _effect.Effect.forkScoped);
179
+ // Reconcile: page-read from `from` until a short page, advancing to the last
180
+ // delivered position. Retries a TRANSIENT poll fault on a capped schedule so
181
+ // a single connection blip does not kill a days-long subscription; a
182
+ // persistent fault propagates and dies.
183
+ const drainFrom = from => _effect.Effect.gen(function* () {
184
+ const collected = [];
185
+ let cursor = from;
186
+ // Loop pages until a short page signals the tail is drained.
187
+ while (true) {
188
+ const events = yield* deps.fetch(cursor, _Event.ReadLimit.make(deps.catchUpPageSize));
189
+ for (const event of events) {
190
+ collected.push(event);
191
+ }
192
+ const lastEvent = events.at(-1);
193
+ if (lastEvent === undefined || events.length < deps.catchUpPageSize) {
194
+ break;
195
+ }
196
+ cursor = lastEvent.position;
197
+ }
198
+ const last = collected.at(-1)?.position ?? from;
199
+ return {
200
+ events: collected,
201
+ last
202
+ };
203
+ }).pipe(_effect.Effect.retry(POLL_RETRY_SCHEDULE));
204
+ /**
205
+ * Produce the NEXT non-empty batch from a cursor position, together with
206
+ * the advanced cursor — a pure `Position → Effect<[Chunk, next]>`. The
207
+ * `> boundary` de-dup is enforced by `fetch`'s exclusive lower bound, so a
208
+ * live re-read after a wake never re-emits an already-delivered position.
209
+ *
210
+ * Drain the wake queue BEFORE reading (lost-wakeup guard), then drain from
211
+ * the cursor. If a drain yields nothing, wait for a wake but only up to the
212
+ * poll interval, then loop and re-read ANYWAY — the periodic position-based
213
+ * poll that makes delivery correct independently of any wake. This effect
214
+ * only completes by returning a non-empty chunk; the scope interrupts it on
215
+ * close.
216
+ */
217
+ const nextBatch = from => _effect.Effect.gen(function* () {
218
+ while (true) {
219
+ yield* _effect.Queue.takeAll(wake);
220
+ const {
221
+ events,
222
+ last
223
+ } = yield* drainFrom(from);
224
+ if (events.length > 0) {
225
+ return [_effect.Chunk.fromIterable(events), last];
226
+ }
227
+ // Nothing new: block on a wake, but only up to the poll interval — on
228
+ // timeout we fall through and the loop re-reads regardless.
229
+ yield* _effect.Effect.ignore(_effect.Effect.timeout(_effect.Queue.take(wake), deps.pollInterval));
230
+ }
231
+ });
232
+ return _effect.Stream.unfoldChunkEffect(after ?? _Event.ORIGIN, from => _effect.Effect.map(nextBatch(from), _effect.Option.some));
233
+ }));
234
+ exports.subscribeStream = subscribeStream;
235
+ //# sourceMappingURL=SubscribeMachine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SubscribeMachine.js","names":["_effect","require","_Event","DEFAULT_CATCH_UP_PAGE_SIZE","exports","DEFAULT_POLL_INTERVAL_MILLIS","subscriptionTuningFields","pollInterval","Schema","optionalWith","Number","pipe","positive","finite","exact","catchUpPageSize","Int","POLL_RETRY_SCHEDULE","Schedule","exponential","union","spaced","intersect","recurs","subscribeStream","deps","after","Stream","unwrapScoped","Effect","gen","wake","Queue","sliding","listener","listen","never","tap","offer","undefined","retry","runDrain","forkScoped","drainFrom","from","collected","cursor","events","fetch","ReadLimit","make","event","push","lastEvent","at","length","position","last","nextBatch","takeAll","Chunk","fromIterable","ignore","timeout","take","unfoldChunkEffect","ORIGIN","map","Option","some"],"sources":["../../src/SubscribeMachine.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.AppendConditionFailed = void 0;
7
+ var _effect = require("effect");
8
+ /**
9
+ * Tagged errors for the store contract. Conflicts are values on the error
10
+ * channel, never defects.
11
+ */
12
+
13
+ /**
14
+ * Raised by `append` when the append condition's `failIfEventsMatch` query
15
+ * matches at least one event after `condition.after`. Carries only the
16
+ * offending condition: a correct retry re-reads the store to its new head and
17
+ * rebuilds its condition from there, so no conflicting position is carried (it
18
+ * would already be stale by the time it was acted on).
19
+ */
20
+ class AppendConditionFailed extends /*#__PURE__*/_effect.Data.TaggedError('AppendConditionFailed') {}
21
+ exports.AppendConditionFailed = AppendConditionFailed;
22
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","names":["_effect","require","AppendConditionFailed","Data","TaggedError","exports"],"sources":["../../src/errors.ts"],"sourcesContent":[null],"mappings":";;;;;;AAIA,IAAAA,OAAA,GAAAC,OAAA;AAJA;;;;;AAOA;;;;;;;AAOM,MAAOC,qBAAsB,sBAAQC,YAAI,CAACC,WAAW,CACzD,uBAAuB,CAGvB;AAAAC,OAAA,CAAAH,qBAAA,GAAAA,qBAAA","ignoreList":[]}
@@ -0,0 +1,191 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.makeInMemoryTestLayer = exports.DcbEventStoreInMemory = void 0;
7
+ var _effect = require("effect");
8
+ var _ContractStore = require("./ContractStore.js");
9
+ var _DcbEventStore = require("./DcbEventStore.js");
10
+ var _Event = require("./Event.js");
11
+ var _errors = require("./errors.js");
12
+ var _Query = require("./Query.js");
13
+ var _SubscribeMachine = require("./SubscribeMachine.js");
14
+ /** Filter a snapshot by `query` and `after` (strict `position > after`). */
15
+ const filterLog = (log, query, after) => log.filter(sequenced => (after === undefined || sequenced.position > after) && (0, _Query.matchesSequenced)(sequenced, query));
16
+ /** The position of the last event in a slice, or `undefined` when empty. */
17
+ const lastPosition = events => events.at(-1)?.position;
18
+ /**
19
+ * Compute the read result over a snapshot: filter, apply the limit, and derive
20
+ * `head` per the contract (no limit => global last position or ORIGIN; limit =>
21
+ * last returned position or ORIGIN).
22
+ */
23
+ const readSnapshot = (log, query, options) => {
24
+ const matched = filterLog(log, query, options?.after);
25
+ const limited = options?.limit === undefined ? matched : matched.slice(0, options.limit);
26
+ // No limit => head is the global last position (ignoring the filter). With a
27
+ // limit => head is the last returned event's position. Either way, ORIGIN
28
+ // when there is nothing to report.
29
+ const head = (options?.limit === undefined ? lastPosition(log) : lastPosition(limited)) ?? _Event.ORIGIN;
30
+ return {
31
+ events: _effect.Stream.fromIterable(limited),
32
+ head
33
+ };
34
+ };
35
+ /**
36
+ * The index of the first event strictly after `after`, by BINARY SEARCH.
37
+ *
38
+ * The log is append-only and ascending by position, so the cursor cut is a boundary
39
+ * in a sorted array and costs O(log n). That is what makes a live subscription's
40
+ * idle poll affordable at any log size: the poll re-reads from its cursor every
41
+ * interval whether or not anything arrived, so a linear cut would charge every open
42
+ * subscription O(n) per interval for as long as it stayed open.
43
+ */
44
+ const firstIndexAfter = (log, after) => {
45
+ let low = 0;
46
+ let high = log.length;
47
+ while (low < high) {
48
+ // `>>> 1` rather than a divide: an integer midpoint with no rounding step.
49
+ const mid = low + high >>> 1;
50
+ if (log[mid].position > after) {
51
+ high = mid;
52
+ } else {
53
+ low = mid + 1;
54
+ }
55
+ }
56
+ return low;
57
+ };
58
+ /**
59
+ * `subscribeStream`'s `fetch` seam: up to `limit` events matching `query` strictly
60
+ * after `from`, ascending.
61
+ *
62
+ * The cursor cut comes FIRST and the query match second, so the predicate only ever
63
+ * sees candidates the cursor admits, and the scan stops the moment `limit` of them
64
+ * have matched rather than filtering a tail it would discard.
65
+ *
66
+ * Deliberately not expressed through `filterLog`, and the reason is COST rather than
67
+ * the answer: that form returns the same events and scans the whole log per page.
68
+ *
69
+ * What is not interchangeable is what the cap COUNTS. The machine's paging contract
70
+ * reads a SHORT page as "the tail is drained", so the cap has to count MATCHES and a
71
+ * short page has to mean the scan ran off the end of the log. A cap counting
72
+ * CANDIDATES — `limit` events taken by POSITION, with the predicate applied within
73
+ * them — reports a short page for a window that merely held few matches; and a window
74
+ * holding NONE reports a drained tail while advancing the cursor nowhere, so the
75
+ * subscription is WEDGED rather than delayed, with no later poll able to move it.
76
+ * `InMemoryStoreOptions.catchUpPageSize` is what puts a test at that boundary.
77
+ */
78
+ const fetchPage = (log, query, from, limit) => {
79
+ const page = [];
80
+ for (let index = firstIndexAfter(log, from); index < log.length && page.length < limit; index += 1) {
81
+ const sequenced = log[index];
82
+ if ((0, _Query.matchesSequenced)(sequenced, query)) {
83
+ page.push(sequenced);
84
+ }
85
+ }
86
+ return page;
87
+ };
88
+ /**
89
+ * Build the in-memory store MECHANICS (a `RawDcbEventStore`), wiring the Ref,
90
+ * semaphore and hub. The contract-enforcement policy (`assertServableQuery`,
91
+ * `ReadLimit` decode, error-vs-defect classification) is NOT here — it is added
92
+ * uniformly by `makeContractStore`, so this engine is pure mechanics.
93
+ */
94
+ const make = options => _effect.Effect.gen(function* () {
95
+ const beforeCommit = options?.beforeCommit ?? _effect.Effect.void;
96
+ const suppressWake = options?.suppressWake ?? false;
97
+ const catchUpPageSize = options?.catchUpPageSize ?? _SubscribeMachine.DEFAULT_CATCH_UP_PAGE_SIZE;
98
+ const pollInterval = options?.pollInterval ?? _SubscribeMachine.DEFAULT_POLL_INTERVAL_MILLIS;
99
+ const log = yield* _effect.Ref.make([]);
100
+ const mutex = yield* _effect.Effect.makeSemaphore(1);
101
+ const hub = yield* _effect.PubSub.unbounded();
102
+ const nextPosition = yield* _effect.Ref.make(1n);
103
+ const read = (query, options) =>
104
+ // The lock keeps read consistent with concurrent appends; popo.py's RLock
105
+ // is reentrant, so append's inner read re-enters. Here append inlines the
106
+ // read logic instead, so a plain lock suffices.
107
+ mutex.withPermits(1)(_effect.Effect.map(_effect.Ref.get(log), snapshot => readSnapshot(snapshot, query, options)));
108
+ const append = (events, condition) =>
109
+ // Critical section: check + commit are atomic (the exactly-one-wins guarantee).
110
+ mutex.withPermits(1)(_effect.Effect.gen(function* () {
111
+ const snapshot = yield* _effect.Ref.get(log);
112
+ if (condition !== undefined) {
113
+ const conflicts = filterLog(snapshot, condition.failIfEventsMatch, condition.after);
114
+ // Detect by presence: any matching event after `condition.after`
115
+ // fails the append. The error carries only the condition (see
116
+ // `AppendConditionFailed`); a correct retry re-reads to the new head.
117
+ if (conflicts.length > 0) {
118
+ return yield* new _errors.AppendConditionFailed({
119
+ condition
120
+ });
121
+ }
122
+ }
123
+ // Optional test seam between the conflict-check and the commit (see
124
+ // `InMemoryStoreOptions.beforeCommit`). Defaults to `Effect.void`, a
125
+ // synchronous no-op, so the shipped critical section stays atomic by
126
+ // construction; the concurrency contract test injects `Effect.yieldNow()`
127
+ // here to make the exactly-one-wins guard genuinely depend on the mutex.
128
+ yield* beforeCommit;
129
+ const start = yield* _effect.Ref.get(nextPosition);
130
+ const appended = events.map((event, index) => ({
131
+ event,
132
+ position: start + BigInt(index)
133
+ }));
134
+ const end = start + BigInt(events.length);
135
+ yield* _effect.Ref.set(log, [...snapshot, ...appended]);
136
+ yield* _effect.Ref.set(nextPosition, end);
137
+ // The hub is a WAKE SOURCE and nothing else: the subscribe machine never
138
+ // reads what it carries, and its poll delivers with or without one. That
139
+ // is why suppressing the publish is a legitimate test seam rather than a
140
+ // broken store (see `InMemoryStoreOptions.suppressWake`).
141
+ if (!suppressWake) {
142
+ yield* _effect.PubSub.publishAll(hub, appended);
143
+ }
144
+ // `events` is non-empty, so the last new position is `end - 1`.
145
+ return end - 1n;
146
+ }));
147
+ const subscribe = (query, after) =>
148
+ // Take the hub seat HERE, before handing the machine its wake source, so the
149
+ // subscription is established no later than the machine's first `fetch`. That
150
+ // ordering is what keeps delivery independent of the poll's timer: an append
151
+ // either lands before that first read, and the read sees it, or after the seat
152
+ // exists, and its wake is queued. The machine drains a wake source on a forked
153
+ // fibre, so a seat taken inside that fibre would leave a window in which an
154
+ // append publishes to nobody — recoverable by the next poll, but only on a
155
+ // real clock, and much of this store's use is under `TestClock`.
156
+ //
157
+ // No mutex: `Ref.get` already reads one committed snapshot, and the machine's
158
+ // exclusive cursor is what makes the catch-up/live seam exactly-once, so there
159
+ // is nothing left here for a critical section to protect. `append` keeps its
160
+ // permit, which is the whole exactly-one-wins guarantee.
161
+ _effect.Stream.unwrapScoped(_effect.Effect.gen(function* () {
162
+ const wakes = yield* _effect.PubSub.subscribe(hub);
163
+ return (0, _SubscribeMachine.subscribeStream)({
164
+ fetch: (from, limit) => _effect.Effect.map(_effect.Ref.get(log), snapshot => fetchPage(snapshot, query, from, limit)),
165
+ listen: _effect.Stream.fromQueue(wakes),
166
+ pollInterval,
167
+ catchUpPageSize
168
+ }, after);
169
+ }));
170
+ return {
171
+ read,
172
+ append,
173
+ subscribe
174
+ };
175
+ });
176
+ /** The in-memory `DcbEventStore` layer (production; no test seam). */
177
+ const DcbEventStoreInMemory = exports.DcbEventStoreInMemory = /*#__PURE__*/_effect.Layer.effect(_DcbEventStore.DcbEventStore, /*#__PURE__*/_effect.Effect.map(/*#__PURE__*/make(), _ContractStore.makeContractStore));
178
+ /**
179
+ * Test-only in-memory layer factory: the same store as `DcbEventStoreInMemory`, but
180
+ * with `InMemoryStoreOptions`' seams open. Kept off the package's public surface
181
+ * (deliberately not re-exported from `index.ts`); production code always uses
182
+ * `DcbEventStoreInMemory`. Every seam exists to make a claim about this store
183
+ * FALSIFIABLE rather than merely commented — the store contract suite forces the
184
+ * check/commit interleaving the exactly-one-wins case needs, one core test takes the
185
+ * wake away and shortens the poll so that what delivers can only be the poll, and
186
+ * another lowers the catch-up page to reach the second-page boundary the shipped page
187
+ * size puts out of reach.
188
+ */
189
+ const makeInMemoryTestLayer = options => _effect.Layer.effect(_DcbEventStore.DcbEventStore, _effect.Effect.map(make(options), _ContractStore.makeContractStore));
190
+ exports.makeInMemoryTestLayer = makeInMemoryTestLayer;
191
+ //# sourceMappingURL=inMemory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inMemory.js","names":["_effect","require","_ContractStore","_DcbEventStore","_Event","_errors","_Query","_SubscribeMachine","filterLog","log","query","after","filter","sequenced","undefined","position","matchesSequenced","lastPosition","events","at","readSnapshot","options","matched","limited","limit","slice","head","ORIGIN","Stream","fromIterable","firstIndexAfter","low","high","length","mid","fetchPage","from","page","index","push","make","Effect","gen","beforeCommit","void","suppressWake","catchUpPageSize","DEFAULT_CATCH_UP_PAGE_SIZE","pollInterval","DEFAULT_POLL_INTERVAL_MILLIS","Ref","mutex","makeSemaphore","hub","PubSub","unbounded","nextPosition","read","withPermits","map","get","snapshot","append","condition","conflicts","failIfEventsMatch","AppendConditionFailed","start","appended","event","BigInt","end","set","publishAll","subscribe","unwrapScoped","wakes","subscribeStream","fetch","listen","fromQueue","DcbEventStoreInMemory","exports","Layer","effect","DcbEventStore","makeContractStore","makeInMemoryTestLayer"],"sources":["../../src/inMemory.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ var _exportNames = {
7
+ DcbEventStoreInMemory: true
8
+ };
9
+ Object.defineProperty(exports, "DcbEventStoreInMemory", {
10
+ enumerable: true,
11
+ get: function () {
12
+ return _inMemory.DcbEventStoreInMemory;
13
+ }
14
+ });
15
+ var _AppendCondition = require("./AppendCondition.js");
16
+ Object.keys(_AppendCondition).forEach(function (key) {
17
+ if (key === "default" || key === "__esModule") return;
18
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
19
+ if (key in exports && exports[key] === _AppendCondition[key]) return;
20
+ Object.defineProperty(exports, key, {
21
+ enumerable: true,
22
+ get: function () {
23
+ return _AppendCondition[key];
24
+ }
25
+ });
26
+ });
27
+ var _ContractStore = require("./ContractStore.js");
28
+ Object.keys(_ContractStore).forEach(function (key) {
29
+ if (key === "default" || key === "__esModule") return;
30
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
31
+ if (key in exports && exports[key] === _ContractStore[key]) return;
32
+ Object.defineProperty(exports, key, {
33
+ enumerable: true,
34
+ get: function () {
35
+ return _ContractStore[key];
36
+ }
37
+ });
38
+ });
39
+ var _DcbEventStore = require("./DcbEventStore.js");
40
+ Object.keys(_DcbEventStore).forEach(function (key) {
41
+ if (key === "default" || key === "__esModule") return;
42
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
43
+ if (key in exports && exports[key] === _DcbEventStore[key]) return;
44
+ Object.defineProperty(exports, key, {
45
+ enumerable: true,
46
+ get: function () {
47
+ return _DcbEventStore[key];
48
+ }
49
+ });
50
+ });
51
+ var _Event = require("./Event.js");
52
+ Object.keys(_Event).forEach(function (key) {
53
+ if (key === "default" || key === "__esModule") return;
54
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
55
+ if (key in exports && exports[key] === _Event[key]) return;
56
+ Object.defineProperty(exports, key, {
57
+ enumerable: true,
58
+ get: function () {
59
+ return _Event[key];
60
+ }
61
+ });
62
+ });
63
+ var _errors = require("./errors.js");
64
+ Object.keys(_errors).forEach(function (key) {
65
+ if (key === "default" || key === "__esModule") return;
66
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
67
+ if (key in exports && exports[key] === _errors[key]) return;
68
+ Object.defineProperty(exports, key, {
69
+ enumerable: true,
70
+ get: function () {
71
+ return _errors[key];
72
+ }
73
+ });
74
+ });
75
+ var _inMemory = require("./inMemory.js");
76
+ var _Projection = require("./Projection.js");
77
+ Object.keys(_Projection).forEach(function (key) {
78
+ if (key === "default" || key === "__esModule") return;
79
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
80
+ if (key in exports && exports[key] === _Projection[key]) return;
81
+ Object.defineProperty(exports, key, {
82
+ enumerable: true,
83
+ get: function () {
84
+ return _Projection[key];
85
+ }
86
+ });
87
+ });
88
+ var _Query = require("./Query.js");
89
+ Object.keys(_Query).forEach(function (key) {
90
+ if (key === "default" || key === "__esModule") return;
91
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
92
+ if (key in exports && exports[key] === _Query[key]) return;
93
+ Object.defineProperty(exports, key, {
94
+ enumerable: true,
95
+ get: function () {
96
+ return _Query[key];
97
+ }
98
+ });
99
+ });
100
+ var _retryOnConflict = require("./retryOnConflict.js");
101
+ Object.keys(_retryOnConflict).forEach(function (key) {
102
+ if (key === "default" || key === "__esModule") return;
103
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
104
+ if (key in exports && exports[key] === _retryOnConflict[key]) return;
105
+ Object.defineProperty(exports, key, {
106
+ enumerable: true,
107
+ get: function () {
108
+ return _retryOnConflict[key];
109
+ }
110
+ });
111
+ });
112
+ var _SubscribeMachine = require("./SubscribeMachine.js");
113
+ Object.keys(_SubscribeMachine).forEach(function (key) {
114
+ if (key === "default" || key === "__esModule") return;
115
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
116
+ if (key in exports && exports[key] === _SubscribeMachine[key]) return;
117
+ Object.defineProperty(exports, key, {
118
+ enumerable: true,
119
+ get: function () {
120
+ return _SubscribeMachine[key];
121
+ }
122
+ });
123
+ });
124
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["_AppendCondition","require","Object","keys","forEach","key","prototype","hasOwnProperty","call","_exportNames","exports","defineProperty","enumerable","get","_ContractStore","_DcbEventStore","_Event","_errors","_inMemory","_Projection","_Query","_retryOnConflict","_SubscribeMachine"],"sources":["../../src/index.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}