@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.
- package/LICENSE +28 -0
- package/README.md +33 -0
- package/dist/cjs/AppendCondition.js +26 -0
- package/dist/cjs/AppendCondition.js.map +1 -0
- package/dist/cjs/ContractStore.js +80 -0
- package/dist/cjs/ContractStore.js.map +1 -0
- package/dist/cjs/DcbEventStore.js +10 -0
- package/dist/cjs/DcbEventStore.js.map +1 -0
- package/dist/cjs/Event.js +89 -0
- package/dist/cjs/Event.js.map +1 -0
- package/dist/cjs/Projection.js +73 -0
- package/dist/cjs/Projection.js.map +1 -0
- package/dist/cjs/Query.js +221 -0
- package/dist/cjs/Query.js.map +1 -0
- package/dist/cjs/SubscribeMachine.js +235 -0
- package/dist/cjs/SubscribeMachine.js.map +1 -0
- package/dist/cjs/errors.js +22 -0
- package/dist/cjs/errors.js.map +1 -0
- package/dist/cjs/inMemory.js +191 -0
- package/dist/cjs/inMemory.js.map +1 -0
- package/dist/cjs/index.js +124 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/retryOnConflict.js +95 -0
- package/dist/cjs/retryOnConflict.js.map +1 -0
- package/dist/cjs/testing.js +54 -0
- package/dist/cjs/testing.js.map +1 -0
- package/dist/dts/AppendCondition.d.ts +23 -0
- package/dist/dts/AppendCondition.d.ts.map +1 -0
- package/dist/dts/ContractStore.d.ts +56 -0
- package/dist/dts/ContractStore.d.ts.map +1 -0
- package/dist/dts/DcbEventStore.d.ts +64 -0
- package/dist/dts/DcbEventStore.d.ts.map +1 -0
- package/dist/dts/Event.d.ts +104 -0
- package/dist/dts/Event.d.ts.map +1 -0
- package/dist/dts/Projection.d.ts +108 -0
- package/dist/dts/Projection.d.ts.map +1 -0
- package/dist/dts/Query.d.ts +145 -0
- package/dist/dts/Query.d.ts.map +1 -0
- package/dist/dts/SubscribeMachine.d.ts +179 -0
- package/dist/dts/SubscribeMachine.d.ts.map +1 -0
- package/dist/dts/errors.d.ts +17 -0
- package/dist/dts/errors.d.ts.map +1 -0
- package/dist/dts/inMemory.d.ts +76 -0
- package/dist/dts/inMemory.d.ts.map +1 -0
- package/dist/dts/index.d.ts +35 -0
- package/dist/dts/index.d.ts.map +1 -0
- package/dist/dts/retryOnConflict.d.ts +70 -0
- package/dist/dts/retryOnConflict.d.ts.map +1 -0
- package/dist/dts/testing.d.ts +39 -0
- package/dist/dts/testing.d.ts.map +1 -0
- package/dist/esm/AppendCondition.js +19 -0
- package/dist/esm/AppendCondition.js.map +1 -0
- package/dist/esm/ContractStore.js +73 -0
- package/dist/esm/ContractStore.js.map +1 -0
- package/dist/esm/DcbEventStore.js +3 -0
- package/dist/esm/DcbEventStore.js.map +1 -0
- package/dist/esm/Event.js +81 -0
- package/dist/esm/Event.js.map +1 -0
- package/dist/esm/Projection.js +66 -0
- package/dist/esm/Projection.js.map +1 -0
- package/dist/esm/Query.js +209 -0
- package/dist/esm/Query.js.map +1 -0
- package/dist/esm/SubscribeMachine.js +227 -0
- package/dist/esm/SubscribeMachine.js.map +1 -0
- package/dist/esm/errors.js +14 -0
- package/dist/esm/errors.js.map +1 -0
- package/dist/esm/inMemory.js +184 -0
- package/dist/esm/inMemory.js.map +1 -0
- package/dist/esm/index.js +38 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/package.json +4 -0
- package/dist/esm/retryOnConflict.js +87 -0
- package/dist/esm/retryOnConflict.js.map +1 -0
- package/dist/esm/testing.js +46 -0
- package/dist/esm/testing.js.map +1 -0
- package/package.json +39 -0
- package/src/AppendCondition.ts +18 -0
- package/src/ContractStore.ts +148 -0
- package/src/DcbEventStore.ts +77 -0
- package/src/Event.ts +135 -0
- package/src/Projection.ts +168 -0
- package/src/Query.ts +237 -0
- package/src/SubscribeMachine.ts +316 -0
- package/src/errors.ts +19 -0
- package/src/inMemory.ts +356 -0
- package/src/index.ts +37 -0
- package/src/retryOnConflict.ts +100 -0
- package/src/testing.ts +47 -0
- 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":[]}
|