@loomwork/event-runtime 0.0.0-stage → 0.1.1

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 (153) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +8 -0
  3. package/README.md +95 -2
  4. package/dist/BranchRegistry.d.ts +140 -0
  5. package/dist/BranchRegistry.d.ts.map +1 -0
  6. package/dist/BranchRegistry.js +66 -0
  7. package/dist/BranchRegistry.js.map +1 -0
  8. package/dist/CoalescingEventStore.d.ts +97 -0
  9. package/dist/CoalescingEventStore.d.ts.map +1 -0
  10. package/dist/CoalescingEventStore.js +180 -0
  11. package/dist/CoalescingEventStore.js.map +1 -0
  12. package/dist/InMemoryArchiveStore.d.ts +19 -0
  13. package/dist/InMemoryArchiveStore.d.ts.map +1 -0
  14. package/dist/InMemoryArchiveStore.js +49 -0
  15. package/dist/InMemoryArchiveStore.js.map +1 -0
  16. package/dist/InMemoryAsyncEventStore.d.ts +111 -0
  17. package/dist/InMemoryAsyncEventStore.d.ts.map +1 -0
  18. package/dist/InMemoryAsyncEventStore.js +374 -0
  19. package/dist/InMemoryAsyncEventStore.js.map +1 -0
  20. package/dist/InMemoryBranchRegistry.d.ts +31 -0
  21. package/dist/InMemoryBranchRegistry.d.ts.map +1 -0
  22. package/dist/InMemoryBranchRegistry.js +167 -0
  23. package/dist/InMemoryBranchRegistry.js.map +1 -0
  24. package/dist/ProfilingEventStore.d.ts +75 -0
  25. package/dist/ProfilingEventStore.d.ts.map +1 -0
  26. package/dist/ProfilingEventStore.js +133 -0
  27. package/dist/ProfilingEventStore.js.map +1 -0
  28. package/dist/ShardPlan.d.ts +87 -0
  29. package/dist/ShardPlan.d.ts.map +1 -0
  30. package/dist/ShardPlan.js +193 -0
  31. package/dist/ShardPlan.js.map +1 -0
  32. package/dist/ShardedEventStore.d.ts +149 -0
  33. package/dist/ShardedEventStore.d.ts.map +1 -0
  34. package/dist/ShardedEventStore.js +468 -0
  35. package/dist/ShardedEventStore.js.map +1 -0
  36. package/dist/SubscriberRegistry.d.ts +59 -0
  37. package/dist/SubscriberRegistry.d.ts.map +1 -0
  38. package/dist/SubscriberRegistry.js +113 -0
  39. package/dist/SubscriberRegistry.js.map +1 -0
  40. package/dist/TenantScopedArchiveStore.d.ts +36 -0
  41. package/dist/TenantScopedArchiveStore.d.ts.map +1 -0
  42. package/dist/TenantScopedArchiveStore.js +96 -0
  43. package/dist/TenantScopedArchiveStore.js.map +1 -0
  44. package/dist/TenantScopedEventStore.d.ts +59 -0
  45. package/dist/TenantScopedEventStore.d.ts.map +1 -0
  46. package/dist/TenantScopedEventStore.js +227 -0
  47. package/dist/TenantScopedEventStore.js.map +1 -0
  48. package/dist/archive.d.ts +68 -0
  49. package/dist/archive.d.ts.map +1 -0
  50. package/dist/archive.js +207 -0
  51. package/dist/archive.js.map +1 -0
  52. package/dist/archiveSpi.d.ts +165 -0
  53. package/dist/archiveSpi.d.ts.map +1 -0
  54. package/dist/archiveSpi.js +184 -0
  55. package/dist/archiveSpi.js.map +1 -0
  56. package/dist/creationMarker.d.ts +13 -0
  57. package/dist/creationMarker.d.ts.map +1 -0
  58. package/dist/creationMarker.js +17 -0
  59. package/dist/creationMarker.js.map +1 -0
  60. package/dist/decoratorPlan.typecheck.d.ts +2 -0
  61. package/dist/decoratorPlan.typecheck.d.ts.map +1 -0
  62. package/dist/decoratorPlan.typecheck.js +41 -0
  63. package/dist/decoratorPlan.typecheck.js.map +1 -0
  64. package/dist/eventKindClass.d.ts +40 -0
  65. package/dist/eventKindClass.d.ts.map +1 -0
  66. package/dist/eventKindClass.js +99 -0
  67. package/dist/eventKindClass.js.map +1 -0
  68. package/dist/executionIdOrder.d.ts +21 -0
  69. package/dist/executionIdOrder.d.ts.map +1 -0
  70. package/dist/executionIdOrder.js +43 -0
  71. package/dist/executionIdOrder.js.map +1 -0
  72. package/dist/fencing.d.ts +21 -0
  73. package/dist/fencing.d.ts.map +1 -0
  74. package/dist/fencing.js +36 -0
  75. package/dist/fencing.js.map +1 -0
  76. package/dist/index.d.ts +39 -0
  77. package/dist/index.d.ts.map +1 -0
  78. package/dist/index.js +126 -0
  79. package/dist/index.js.map +1 -0
  80. package/dist/installOptional.d.ts +52 -0
  81. package/dist/installOptional.d.ts.map +1 -0
  82. package/dist/installOptional.js +112 -0
  83. package/dist/installOptional.js.map +1 -0
  84. package/dist/keyUnavailable.d.ts +67 -0
  85. package/dist/keyUnavailable.d.ts.map +1 -0
  86. package/dist/keyUnavailable.js +87 -0
  87. package/dist/keyUnavailable.js.map +1 -0
  88. package/dist/leases.d.ts +177 -0
  89. package/dist/leases.d.ts.map +1 -0
  90. package/dist/leases.js +142 -0
  91. package/dist/leases.js.map +1 -0
  92. package/dist/payloadShredded.d.ts +30 -0
  93. package/dist/payloadShredded.d.ts.map +1 -0
  94. package/dist/payloadShredded.js +67 -0
  95. package/dist/payloadShredded.js.map +1 -0
  96. package/dist/scaleDecorators.bench.d.ts +2 -0
  97. package/dist/scaleDecorators.bench.d.ts.map +1 -0
  98. package/dist/scaleDecorators.bench.js +93 -0
  99. package/dist/scaleDecorators.bench.js.map +1 -0
  100. package/dist/sequenceRange.bench.d.ts +2 -0
  101. package/dist/sequenceRange.bench.d.ts.map +1 -0
  102. package/dist/sequenceRange.bench.js +46 -0
  103. package/dist/sequenceRange.bench.js.map +1 -0
  104. package/dist/sequenceRange.d.ts +10 -0
  105. package/dist/sequenceRange.d.ts.map +1 -0
  106. package/dist/sequenceRange.js +35 -0
  107. package/dist/sequenceRange.js.map +1 -0
  108. package/dist/timers.d.ts +87 -0
  109. package/dist/timers.d.ts.map +1 -0
  110. package/dist/timers.js +68 -0
  111. package/dist/timers.js.map +1 -0
  112. package/dist/types.d.ts +634 -0
  113. package/dist/types.d.ts.map +1 -0
  114. package/dist/types.js +429 -0
  115. package/dist/types.js.map +1 -0
  116. package/dist/writeConflicts.d.ts +46 -0
  117. package/dist/writeConflicts.d.ts.map +1 -0
  118. package/dist/writeConflicts.js +63 -0
  119. package/dist/writeConflicts.js.map +1 -0
  120. package/memory.d.ts +4 -0
  121. package/memory.js +13 -0
  122. package/package.json +67 -3
  123. package/sequence.d.ts +1 -0
  124. package/sequence.js +5 -0
  125. package/src/BranchRegistry.ts +161 -0
  126. package/src/CoalescingEventStore.ts +214 -0
  127. package/src/InMemoryArchiveStore.ts +69 -0
  128. package/src/InMemoryAsyncEventStore.ts +425 -0
  129. package/src/InMemoryBranchRegistry.ts +178 -0
  130. package/src/ProfilingEventStore.ts +153 -0
  131. package/src/ShardPlan.ts +235 -0
  132. package/src/ShardedEventStore.ts +557 -0
  133. package/src/SubscriberRegistry.ts +115 -0
  134. package/src/TenantScopedArchiveStore.ts +114 -0
  135. package/src/TenantScopedEventStore.ts +266 -0
  136. package/src/archive.ts +248 -0
  137. package/src/archiveSpi.ts +308 -0
  138. package/src/creationMarker.ts +15 -0
  139. package/src/decoratorPlan.typecheck.ts +52 -0
  140. package/src/eventKindClass.ts +127 -0
  141. package/src/executionIdOrder.ts +38 -0
  142. package/src/fencing.ts +31 -0
  143. package/src/index.ts +151 -0
  144. package/src/installOptional.ts +136 -0
  145. package/src/keyUnavailable.ts +98 -0
  146. package/src/leases.ts +319 -0
  147. package/src/payloadShredded.ts +63 -0
  148. package/src/scaleDecorators.bench.ts +107 -0
  149. package/src/sequenceRange.bench.ts +51 -0
  150. package/src/sequenceRange.ts +35 -0
  151. package/src/timers.ts +150 -0
  152. package/src/types.ts +857 -0
  153. package/src/writeConflicts.ts +56 -0
@@ -0,0 +1,374 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.InMemoryAsyncEventStore = void 0;
4
+ const SubscriberRegistry_1 = require("./SubscriberRegistry");
5
+ const eventKindClass_1 = require("./eventKindClass");
6
+ const executionIdOrder_1 = require("./executionIdOrder");
7
+ const fencing_1 = require("./fencing");
8
+ const sequenceRange_1 = require("./sequenceRange");
9
+ const writeConflicts_1 = require("./writeConflicts");
10
+ /**
11
+ * Reference **async** EventStore: a genuine Promise-returning backend (unlike the
12
+ * synchronous SQLite/in-memory stores, which merely satisfy the async interface).
13
+ * Use it as a starting point for a real network backend, or in tests to exercise
14
+ * the runtime's async write pipeline, ordering, and failure handling.
15
+ */
16
+ class InMemoryAsyncEventStore {
17
+ log = new Map();
18
+ /**
19
+ * The executionIds in SPI order (code point), built lazily by `listExecutionsPage` and
20
+ * dropped only when the SET of executions changes (a new one, or a delete). A full paged
21
+ * walk is then one O(n log n) sort plus O(log n) per page, not a re-sort per page.
22
+ */
23
+ sortedIds;
24
+ /**
25
+ * #309 — every envelope id in the store, the index behind the `id` PRIMARY KEY both SQL
26
+ * backends have. GLOBAL, not per-execution, because that is what the SQL constraint is:
27
+ * two executions may not share an envelope id either.
28
+ *
29
+ * It has to be maintained everywhere the log changes, not just on append — a stale entry
30
+ * after a delete would refuse a legitimate re-append forever, and an un-removed one is a
31
+ * leak in a store whose whole job is to be re-created cheaply in tests. The removal side
32
+ * is only correct BECAUSE the invariant holds: an id belongs to exactly one envelope, so
33
+ * dropping the ids of the events being dropped cannot orphan someone else's claim.
34
+ *
35
+ * Costs one hash-table slot per event; the id strings themselves are already retained by
36
+ * the envelopes in `log`, so this is not a second copy of the data.
37
+ */
38
+ ids = new Set();
39
+ subscribers = new SubscriberRegistry_1.SubscriberRegistry();
40
+ fences = new Map();
41
+ /**
42
+ * ADR 0129 — the store-assigned incarnation of each execution, taken from a store-wide
43
+ * monotonic counter when its sequence 0 first lands and dropped with the log. Store metadata
44
+ * only: never in an envelope, a fold, a snapshot or a hash, so replay stays byte-identical.
45
+ */
46
+ incarnations = new Map();
47
+ nextIncarnation = 1;
48
+ latencyMs;
49
+ failAppendWhen;
50
+ constructor(options = {}) {
51
+ this.latencyMs = options.latencyMs ?? 0;
52
+ this.failAppendWhen = options.failAppendWhen;
53
+ }
54
+ async tick() {
55
+ if (this.latencyMs > 0)
56
+ await new Promise((r) => setTimeout(r, this.latencyMs));
57
+ else
58
+ await Promise.resolve();
59
+ }
60
+ async append(envelope) {
61
+ await this.tick();
62
+ this.assertAppendable(envelope);
63
+ this.commit(envelope);
64
+ this.subscribers.emit(envelope);
65
+ }
66
+ /**
67
+ * ADR 0074 D1 — the reference implementation of the `appendBatch` contract, and what a
68
+ * bring-your-own backend can read to see what it has to honour.
69
+ *
70
+ * One `tick()` for the whole batch, because the point of the method is one round-trip.
71
+ * Atomicity is why validation is a separate pass: EVERY envelope is checked before ANY
72
+ * is committed, so a fenced-out or rejected envelope leaves the log exactly as it was
73
+ * rather than half-applied. Fencing is checked per envelope, since a batch may span
74
+ * executions.
75
+ */
76
+ async appendBatch(envelopes) {
77
+ if (envelopes.length === 0)
78
+ return;
79
+ await this.tick();
80
+ // A batch must be checked against ITSELF as well as the log: two envelopes claiming
81
+ // the same slot — or the same id — are both appendable against the durable state, and
82
+ // only the pairwise check catches them. Tracked lazily, so the common single-execution
83
+ // monotonic batch allocates nothing.
84
+ let claimedSlots;
85
+ let claimedIds;
86
+ for (const envelope of envelopes) {
87
+ this.assertAppendable(envelope);
88
+ const seen = claimedSlots?.get(envelope.executionId);
89
+ if (seen?.has(envelope.sequence) === true) {
90
+ throw new writeConflicts_1.DuplicateSequenceError(envelope.executionId, envelope.sequence);
91
+ }
92
+ if (claimedIds?.has(envelope.id) === true) {
93
+ throw new writeConflicts_1.DuplicateEnvelopeIdError(envelope.id, envelope.executionId);
94
+ }
95
+ claimedSlots ??= new Map();
96
+ const set = seen ?? new Set();
97
+ set.add(envelope.sequence);
98
+ claimedSlots.set(envelope.executionId, set);
99
+ claimedIds ??= new Set();
100
+ claimedIds.add(envelope.id);
101
+ }
102
+ for (const envelope of envelopes)
103
+ this.commit(envelope);
104
+ // Fan out only once the whole batch has landed — a subscriber must never observe a
105
+ // partially applied batch.
106
+ for (const envelope of envelopes)
107
+ this.subscribers.emit(envelope);
108
+ }
109
+ /**
110
+ * Throws if this envelope may not land: a duplicate `(executionId, sequence)`, a
111
+ * duplicate envelope `id`, K9.4 fencing, or an injected failure.
112
+ */
113
+ assertAppendable(envelope, checkFence = true) {
114
+ // K9.4 — fencing: once a token has been acquired for this execution, an
115
+ // append missing the current token is a zombie write and is rejected.
116
+ const currentFence = checkFence ? this.fences.get(envelope.executionId) : undefined;
117
+ if (currentFence !== undefined) {
118
+ const fence = (0, fencing_1.fenceOf)(envelope);
119
+ if (fence === undefined || fence < currentFence) {
120
+ throw new fencing_1.StaleFenceError(envelope.executionId, fence, currentFence);
121
+ }
122
+ }
123
+ // #306 — the same `UNIQUE (execution_id, sequence)` both SQL backends enforce. Not a
124
+ // redundant belt beside fencing: fencing engages only once a token has been ACQUIRED,
125
+ // and sequences are allocated per-process from folded state, so two unfenced writers
126
+ // recovering the same execution allocate the same next sequence with neither a zombie.
127
+ // O(log n) against the sorted log — `commit` maintains that order for exactly this.
128
+ const list = this.log.get(envelope.executionId);
129
+ if (list !== undefined) {
130
+ const at = (0, sequenceRange_1.lowerBoundBySequence)(list, envelope.sequence);
131
+ if (at < list.length && list[at].sequence === envelope.sequence) {
132
+ throw new writeConflicts_1.DuplicateSequenceError(envelope.executionId, envelope.sequence);
133
+ }
134
+ }
135
+ // #309 — the events table's OTHER key. Checked after the slot, so a writer that lost a
136
+ // sequence race is told that (the actionable failure) rather than being told about the
137
+ // id its own naming convention derived from the sequence it lost.
138
+ if (this.ids.has(envelope.id)) {
139
+ throw new writeConflicts_1.DuplicateEnvelopeIdError(envelope.id, envelope.executionId);
140
+ }
141
+ const verdict = this.failAppendWhen?.(envelope);
142
+ if (verdict) {
143
+ throw verdict instanceof Error
144
+ ? verdict
145
+ : new Error(typeof verdict === "string" ? verdict : `append rejected: ${envelope.id}`);
146
+ }
147
+ }
148
+ /** Insert into the execution's log, keeping it sorted by sequence. */
149
+ commit(envelope) {
150
+ this.ids.add(envelope.id);
151
+ const list = this.log.get(envelope.executionId) ?? [];
152
+ // Keep each execution's log sorted by sequence so reads can binary-search.
153
+ // Appends are normally monotonic (a plain end-push); only an out-of-order
154
+ // arrival triggers an insertion.
155
+ if (list.length === 0 ||
156
+ list[list.length - 1].sequence <= envelope.sequence) {
157
+ list.push(envelope);
158
+ }
159
+ else {
160
+ list.splice((0, sequenceRange_1.lowerBoundBySequence)(list, envelope.sequence), 0, envelope);
161
+ }
162
+ this.setLog(envelope.executionId, list);
163
+ }
164
+ async read(executionId) {
165
+ await this.tick();
166
+ // Already sorted by the append invariant — return a defensive copy, no re-sort.
167
+ return [...(this.log.get(executionId) ?? [])];
168
+ }
169
+ async readFrom(executionId, fromSequence) {
170
+ await this.tick();
171
+ const list = this.log.get(executionId) ?? [];
172
+ return list.slice((0, sequenceRange_1.lowerBoundBySequence)(list, fromSequence));
173
+ }
174
+ async head(executionId) {
175
+ await this.tick();
176
+ const list = this.log.get(executionId) ?? [];
177
+ return list.length === 0 ? null : (list[list.length - 1]?.sequence ?? null);
178
+ }
179
+ async readRange(executionId, fromSequence, toSequence) {
180
+ await this.tick();
181
+ return (0, sequenceRange_1.sliceBySequence)(this.log.get(executionId) ?? [], fromSequence, toSequence);
182
+ }
183
+ async copyPrefix(fromExecutionId, toExecutionId, throughSequence, metadata) {
184
+ await this.tick();
185
+ const src = this.log.get(fromExecutionId) ?? [];
186
+ const dst = this.log.get(toExecutionId) ?? [];
187
+ // Built fully before anything is published, so a rejected copy leaves the target
188
+ // untouched — the same all-or-nothing shape the SQL backends get from their INSERT
189
+ // … SELECT, which would abort on the primary key rather than half-populate a fork.
190
+ const copied = [];
191
+ for (const e of src) {
192
+ if (e.sequence > throughSequence)
193
+ continue;
194
+ // Re-stamp only; no payload (de)serialization.
195
+ const stamped = {
196
+ ...e,
197
+ executionId: toExecutionId,
198
+ id: `${toExecutionId}-${e.sequence}`,
199
+ metadata: { ...e.metadata, ...metadata },
200
+ };
201
+ // #309 — the re-stamped ids must be as unique as any other. A fork into a target
202
+ // that already holds events is a broken fork, and this is where it surfaces; the
203
+ // check also keeps the id index single-owner, which is what makes removal on
204
+ // delete/truncate safe.
205
+ if (this.ids.has(stamped.id)) {
206
+ throw new writeConflicts_1.DuplicateEnvelopeIdError(stamped.id, toExecutionId);
207
+ }
208
+ copied.push(stamped);
209
+ }
210
+ for (const e of copied) {
211
+ this.ids.add(e.id);
212
+ dst.push(e);
213
+ }
214
+ this.setLog(toExecutionId, dst);
215
+ }
216
+ async acquireFence(executionId) {
217
+ await this.tick();
218
+ const next = (this.fences.get(executionId) ?? 0) + 1;
219
+ this.fences.set(executionId, next);
220
+ return next;
221
+ }
222
+ /**
223
+ * ADR 0118 D1 — one synchronous step after the tick, so it cannot interleave with an append's
224
+ * own check-and-commit (which is also synchronous after ITS tick): the token compare-and-set
225
+ * plus a scan of the tail past `parkSeq`, which is short (the events appended since the park).
226
+ */
227
+ async acquireFenceIf(executionId, expect) {
228
+ await this.tick();
229
+ const current = this.fences.get(executionId) ?? 0;
230
+ if (current !== expect.fence)
231
+ return { stale: true, fence: current };
232
+ const list = this.log.get(executionId) ?? [];
233
+ for (let i = (0, sequenceRange_1.lowerBoundBySequence)(list, expect.parkSeq + 1); i < list.length; i++) {
234
+ if ((0, eventKindClass_1.isAnsweringKind)(list[i]))
235
+ return { stale: true, fence: current };
236
+ }
237
+ this.fences.set(executionId, current + 1);
238
+ return { fence: current + 1 };
239
+ }
240
+ /**
241
+ * SPI 2.2.0 (ADR 0116 amendment) — one synchronous step after the tick, so the existence,
242
+ * head and token checks and the commit cannot interleave with any other append, acquire or
243
+ * delete. The token is compared, never presented: the fence rule is deliberately skipped.
244
+ */
245
+ async appendIfUnchanged(executionId, event, expect) {
246
+ await this.tick();
247
+ if (event !== null && (expect === undefined || event.executionId !== executionId)) {
248
+ throw new TypeError("appendIfUnchanged: an event needs `expect` and the matching executionId");
249
+ }
250
+ const list = this.log.get(executionId);
251
+ const fence = this.fences.get(executionId) ?? 0;
252
+ if (list === undefined || list.length === 0 || list[0].sequence !== 0) {
253
+ return { appended: false, reason: "gone", head: null, fence, anchor: null };
254
+ }
255
+ const head = list[list.length - 1].sequence;
256
+ const anchor = String(this.incarnations.get(executionId));
257
+ if (event === null)
258
+ return { appended: false, reason: "observed", head, fence, anchor };
259
+ const want = expect;
260
+ if (head !== want.head ||
261
+ fence !== want.fence ||
262
+ anchor !== want.anchor ||
263
+ event.sequence !== head + 1) {
264
+ return { appended: false, reason: "moved", head, fence, anchor };
265
+ }
266
+ this.assertAppendable(event, false);
267
+ this.commit(event);
268
+ this.subscribers.emit(event);
269
+ return { appended: true };
270
+ }
271
+ async deleteExecution(executionId) {
272
+ await this.tick();
273
+ // Release the ids too, or a re-created execution could never re-append the events it
274
+ // just erased — and the index would grow forever across a retention sweep.
275
+ for (const e of this.log.get(executionId) ?? [])
276
+ this.ids.delete(e.id);
277
+ if (this.log.delete(executionId))
278
+ this.sortedIds = undefined;
279
+ this.fences.delete(executionId);
280
+ this.incarnations.delete(executionId);
281
+ }
282
+ async deleteThrough(executionId, through) {
283
+ await this.tick();
284
+ const list = this.log.get(executionId);
285
+ if (list === undefined)
286
+ return;
287
+ // One synchronous pass (no reader sees half of it): sequence 0 goes too, unlike truncatePrefix.
288
+ const kept = [];
289
+ for (const e of list) {
290
+ if (e.sequence > through)
291
+ kept.push(e);
292
+ else
293
+ this.ids.delete(e.id);
294
+ }
295
+ if (kept.length === 0) {
296
+ await this.deleteExecution(executionId);
297
+ return;
298
+ }
299
+ this.log.set(executionId, kept);
300
+ }
301
+ setLog(executionId, list) {
302
+ if (!this.log.has(executionId))
303
+ this.sortedIds = undefined;
304
+ if (list[0]?.sequence === 0 && !this.incarnations.has(executionId)) {
305
+ this.incarnations.set(executionId, this.nextIncarnation++);
306
+ }
307
+ this.log.set(executionId, list);
308
+ }
309
+ async listExecutions() {
310
+ await this.tick();
311
+ return [...this.log.keys()];
312
+ }
313
+ async listExecutionsPage(opts) {
314
+ await this.tick();
315
+ const limit = opts?.limit ?? 1000;
316
+ const cursor = opts?.cursor;
317
+ // SPI 2.0.0 — code point order, and the cursor may be any string: binary-search the
318
+ // first id strictly after it.
319
+ this.sortedIds ??= [...this.log.keys()].sort(executionIdOrder_1.compareExecutionIds);
320
+ const sorted = this.sortedIds;
321
+ let start = 0;
322
+ if (cursor !== undefined) {
323
+ let hi = sorted.length;
324
+ while (start < hi) {
325
+ const mid = (start + hi) >>> 1;
326
+ if ((0, executionIdOrder_1.compareExecutionIds)(sorted[mid], cursor) > 0)
327
+ hi = mid;
328
+ else
329
+ start = mid + 1;
330
+ }
331
+ }
332
+ const executionIds = sorted.slice(start, start + limit);
333
+ const last = executionIds[executionIds.length - 1];
334
+ return {
335
+ executionIds,
336
+ ...(last !== undefined && start + limit < sorted.length && { nextCursor: last }),
337
+ };
338
+ }
339
+ async truncatePrefix(executionId, throughSequence) {
340
+ await this.truncatePrefixKeeping(executionId, throughSequence, []);
341
+ }
342
+ async truncatePrefixKeeping(executionId, throughSequence, keepEventTypes) {
343
+ await this.tick();
344
+ const list = this.log.get(executionId);
345
+ if (list === undefined)
346
+ return;
347
+ const keepTypes = new Set(keepEventTypes);
348
+ // Preserve sequence 0 (bootstrap anchor) and every kept-type event; drop the rest of
349
+ // (0..throughSequence]. One synchronous pass, so no reader sees a half-truncated prefix.
350
+ const kept = [];
351
+ for (const e of list) {
352
+ if (e.sequence === 0 || e.sequence > throughSequence || keepTypes.has(e.eventType)) {
353
+ kept.push(e);
354
+ }
355
+ else {
356
+ this.ids.delete(e.id); // compacted away — its id is free again
357
+ }
358
+ }
359
+ this.setLog(executionId, kept);
360
+ }
361
+ async subscribe(executionId, handler) {
362
+ await this.tick();
363
+ return this.subscribers.add(executionId, handler);
364
+ }
365
+ async close() {
366
+ this.ids.clear();
367
+ this.log.clear();
368
+ this.incarnations.clear();
369
+ this.sortedIds = undefined;
370
+ this.subscribers.clear();
371
+ }
372
+ }
373
+ exports.InMemoryAsyncEventStore = InMemoryAsyncEventStore;
374
+ //# sourceMappingURL=InMemoryAsyncEventStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InMemoryAsyncEventStore.js","sourceRoot":"","sources":["../src/InMemoryAsyncEventStore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import { type BranchRef, type BranchRegistry, type LineageRecord, type ListRefsOptions, type PromoteOptions } from "./BranchRegistry";
2
+ export interface InMemoryBranchRegistryOptions {
3
+ /** Injectable clock for createdAt/updatedAt (defaults to Date.now). */
4
+ now?: () => number;
5
+ }
6
+ /**
7
+ * Ephemeral, Map-based {@link BranchRegistry} — the browser-safe / test reference impl
8
+ * alongside the Sqlite and Postgres ones. Pure JS, no native deps. Behaviour matches
9
+ * the durable backends (verified by `runBranchRegistryConformance` in `@loomwork/testing`).
10
+ */
11
+ export declare class InMemoryBranchRegistry implements BranchRegistry {
12
+ private readonly refs;
13
+ private readonly lineage;
14
+ private readonly now;
15
+ private sortedNames;
16
+ constructor(options?: InMemoryBranchRegistryOptions);
17
+ /** Binary-insert `name` into `sortedNames`, no-op if it is already there (live or a tombstone). */
18
+ private insertSorted;
19
+ putRef(ref: BranchRef): Promise<void>;
20
+ getRef(name: string): Promise<BranchRef | null>;
21
+ listRefs(options?: ListRefsOptions): Promise<BranchRef[]>;
22
+ moveTip(name: string, tip: number): Promise<void>;
23
+ promote(fromName: string, toName: string, options?: PromoteOptions): Promise<void>;
24
+ deleteRef(name: string): Promise<void>;
25
+ recordLineage(rec: Omit<LineageRecord, "createdAt">): Promise<void>;
26
+ getLineage(executionId: string): Promise<LineageRecord | null>;
27
+ removeLineage(executionId: string): Promise<void>;
28
+ children(executionId: string): Promise<LineageRecord[]>;
29
+ close(): Promise<void>;
30
+ }
31
+ //# sourceMappingURL=InMemoryBranchRegistry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InMemoryBranchRegistry.d.ts","sourceRoot":"","sources":["../src/InMemoryBranchRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,cAAc,EAEpB,MAAM,kBAAkB,CAAC;AAG1B,MAAM,WAAW,6BAA6B;IAC5C,uEAAuE;IACvE,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,qBAAa,sBAAuB,YAAW,cAAc;IAC3D,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAgC;IACrD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoC;IAC5D,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IAuBnC,OAAO,CAAC,WAAW,CAAuB;gBAE9B,OAAO,GAAE,6BAAkC;IAIvD,mGAAmG;IACnG,OAAO,CAAC,YAAY;IAad,MAAM,CAAC,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAKrC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAK/C,QAAQ,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAoCzD,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOjD,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IA+BlF,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMtC,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,aAAa,EAAE,WAAW,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAInE,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAK9D,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjD,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAMvD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAC7B"}
@@ -0,0 +1,167 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.InMemoryBranchRegistry = void 0;
4
+ const BranchRegistry_1 = require("./BranchRegistry");
5
+ const executionIdOrder_1 = require("./executionIdOrder");
6
+ /**
7
+ * Ephemeral, Map-based {@link BranchRegistry} — the browser-safe / test reference impl
8
+ * alongside the Sqlite and Postgres ones. Pure JS, no native deps. Behaviour matches
9
+ * the durable backends (verified by `runBranchRegistryConformance` in `@loomwork/testing`).
10
+ */
11
+ class InMemoryBranchRegistry {
12
+ refs = new Map();
13
+ lineage = new Map();
14
+ now;
15
+ // SPI 2.0.0 (L21, ADR 0108 addendum) — ref names in Unicode CODE POINT order
16
+ // (`compareExecutionIds`), kept sorted incrementally rather than re-sorted per call.
17
+ // Mirrors `InMemoryAsyncEventStore`'s `sortedIds` cache, so a page costs a binary search
18
+ // plus the page size, not an O(n log n) re-sort of the whole registry on every call.
19
+ //
20
+ // NOT `String.prototype.localeCompare`: it is locale- and normalization-aware, so two
21
+ // DISTINCT, canonically-equivalent names (an NFC "é", U+00E9, and its NFD decomposition
22
+ // "e\u0301") can compare equal. `listRefs`'s `after` filter used to test
23
+ // `name.localeCompare(after) > 0`, so a name tied with the cursor by that comparator was
24
+ // silently excluded — an L10-style skip at exactly the page boundary `pruneBranchRefs`
25
+ // resumes from.
26
+ //
27
+ // Review round 1 (P3) — `deleteRef` does NOT remove the name from this array; it becomes
28
+ // a TOMBSTONE (absent from `refs`, still present here) that `listRefs` skips while paging,
29
+ // and that gets swept out the next time this array is rebuilt. Deleting never reorders the
30
+ // survivors, so there is nothing to re-sort — `pruneBranchRefs` interleaves one `listRefs`
31
+ // page with N `deleteRef` calls, and invalidating per delete forced a full re-sort on
32
+ // every single page (measured: 100k refs, 179s). New names are binary-INSERTed in place
33
+ // instead, which also keeps a revived name (deleted, then `putRef`-created again under the
34
+ // same string) from producing a duplicate entry — see `insertSorted`. Compacted lazily in
35
+ // `listRefs`, once tombstones make up at least half the array, rather than never (an
36
+ // unbounded array over a long-lived registry) or on every delete (the cost above).
37
+ sortedNames;
38
+ constructor(options = {}) {
39
+ this.now = options.now ?? (() => Date.now());
40
+ }
41
+ /** Binary-insert `name` into `sortedNames`, no-op if it is already there (live or a tombstone). */
42
+ insertSorted(name) {
43
+ if (this.sortedNames === undefined)
44
+ return; // computed fresh, lazily, on the next listRefs
45
+ const arr = this.sortedNames;
46
+ let lo = 0;
47
+ let hi = arr.length;
48
+ while (lo < hi) {
49
+ const mid = (lo + hi) >>> 1;
50
+ if ((0, executionIdOrder_1.compareExecutionIds)(arr[mid], name) < 0)
51
+ lo = mid + 1;
52
+ else
53
+ hi = mid;
54
+ }
55
+ if (arr[lo] !== name)
56
+ arr.splice(lo, 0, name);
57
+ }
58
+ async putRef(ref) {
59
+ if (!this.refs.has(ref.name))
60
+ this.insertSorted(ref.name);
61
+ this.refs.set(ref.name, { ...ref });
62
+ }
63
+ async getRef(name) {
64
+ const ref = this.refs.get(name);
65
+ return ref !== undefined ? { ...ref } : null;
66
+ }
67
+ async listRefs(options) {
68
+ (0, BranchRegistry_1.assertListRefsLimit)(options?.limit);
69
+ // Lazy compaction: `deleteRef` never removes a name from `sortedNames` (see its doc
70
+ // comment), so once tombstones make up at least half the array, drop them by rebuilding
71
+ // from the live map — bounding how long a dead name can inflate every later scan, without
72
+ // paying for a rebuild on every delete.
73
+ if (this.sortedNames !== undefined && this.sortedNames.length >= this.refs.size * 2) {
74
+ this.sortedNames = undefined;
75
+ }
76
+ this.sortedNames ??= [...this.refs.keys()].sort(executionIdOrder_1.compareExecutionIds);
77
+ const sorted = this.sortedNames;
78
+ const after = options?.after;
79
+ // Binary-search the first name strictly after the cursor (any string, not only one
80
+ // this store returned) — the same seek `InMemoryAsyncEventStore.listExecutionsPage`
81
+ // does for execution ids. Tombstones do not disturb this: removing a name from `refs`
82
+ // never changes the relative order of the names that remain in `sortedNames`.
83
+ let start = 0;
84
+ if (after !== undefined) {
85
+ let hi = sorted.length;
86
+ while (start < hi) {
87
+ const mid = (start + hi) >>> 1;
88
+ if ((0, executionIdOrder_1.compareExecutionIds)(sorted[mid], after) > 0)
89
+ hi = mid;
90
+ else
91
+ start = mid + 1;
92
+ }
93
+ }
94
+ const limit = options?.limit;
95
+ const page = [];
96
+ for (let i = start; i < sorted.length; i++) {
97
+ const ref = this.refs.get(sorted[i]);
98
+ if (ref === undefined)
99
+ continue; // a tombstone — deleted since this name was indexed
100
+ page.push({ ...ref });
101
+ if (limit !== undefined && page.length >= limit)
102
+ break;
103
+ }
104
+ return page;
105
+ }
106
+ async moveTip(name, tip) {
107
+ const ref = this.refs.get(name);
108
+ if (ref === undefined)
109
+ return;
110
+ ref.tip = tip;
111
+ ref.updatedAt = this.now();
112
+ }
113
+ async promote(fromName, toName, options) {
114
+ const from = this.refs.get(fromName);
115
+ if (from === undefined) {
116
+ throw new Error(`promote: branch "${fromName}" does not exist`);
117
+ }
118
+ const now = this.now();
119
+ const to = this.refs.get(toName);
120
+ // CAS. Single-threaded by construction here, so read-then-write IS atomic; the durable
121
+ // backends do the same check inside one statement/transaction.
122
+ if (options !== undefined && "expect" in options) {
123
+ const actual = to?.executionId ?? null;
124
+ if (actual !== (options.expect ?? null)) {
125
+ throw new BranchRegistry_1.BranchPromotionConflictError(toName, options.expect ?? null, actual);
126
+ }
127
+ }
128
+ if (to === undefined) {
129
+ this.insertSorted(toName); // a new name enters the order
130
+ this.refs.set(toName, {
131
+ name: toName,
132
+ executionId: from.executionId,
133
+ tip: from.tip,
134
+ createdAt: now,
135
+ updatedAt: now,
136
+ });
137
+ }
138
+ else {
139
+ to.executionId = from.executionId;
140
+ to.tip = from.tip;
141
+ to.updatedAt = now;
142
+ }
143
+ }
144
+ async deleteRef(name) {
145
+ // Deliberately does NOT touch `sortedNames` — see its doc comment. The name becomes a
146
+ // tombstone, skipped by `listRefs` and compacted away lazily.
147
+ this.refs.delete(name);
148
+ }
149
+ async recordLineage(rec) {
150
+ this.lineage.set(rec.executionId, { ...rec, createdAt: this.now() });
151
+ }
152
+ async getLineage(executionId) {
153
+ const rec = this.lineage.get(executionId);
154
+ return rec !== undefined ? { ...rec } : null;
155
+ }
156
+ async removeLineage(executionId) {
157
+ this.lineage.delete(executionId);
158
+ }
159
+ async children(executionId) {
160
+ return [...this.lineage.values()]
161
+ .filter((l) => l.parentExecutionId === executionId)
162
+ .map((l) => ({ ...l }));
163
+ }
164
+ async close() { }
165
+ }
166
+ exports.InMemoryBranchRegistry = InMemoryBranchRegistry;
167
+ //# sourceMappingURL=InMemoryBranchRegistry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InMemoryBranchRegistry.js","sourceRoot":"","sources":["../src/InMemoryBranchRegistry.ts"],"names":[],"mappings":"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"}