@kairos-es/read 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 +538 -0
- package/dist/cjs/EventLogDurability.js +184 -0
- package/dist/cjs/EventLogDurability.js.map +1 -0
- package/dist/cjs/ProjectionRunner.js +478 -0
- package/dist/cjs/ProjectionRunner.js.map +1 -0
- package/dist/cjs/ProjectionStore.js +233 -0
- package/dist/cjs/ProjectionStore.js.map +1 -0
- package/dist/cjs/foldIntoRef.js +36 -0
- package/dist/cjs/foldIntoRef.js.map +1 -0
- package/dist/cjs/inMemoryProjectionStore.js +138 -0
- package/dist/cjs/inMemoryProjectionStore.js.map +1 -0
- package/dist/cjs/index.js +128 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/projectionWiringFault.js +532 -0
- package/dist/cjs/projectionWiringFault.js.map +1 -0
- package/dist/cjs/runProjection.js +117 -0
- package/dist/cjs/runProjection.js.map +1 -0
- package/dist/cjs/runProjections.js +144 -0
- package/dist/cjs/runProjections.js.map +1 -0
- package/dist/cjs/superviseOnProgress.js +580 -0
- package/dist/cjs/superviseOnProgress.js.map +1 -0
- package/dist/cjs/testing.js +143 -0
- package/dist/cjs/testing.js.map +1 -0
- package/dist/dts/EventLogDurability.d.ts +182 -0
- package/dist/dts/EventLogDurability.d.ts.map +1 -0
- package/dist/dts/ProjectionRunner.d.ts +557 -0
- package/dist/dts/ProjectionRunner.d.ts.map +1 -0
- package/dist/dts/ProjectionStore.d.ts +475 -0
- package/dist/dts/ProjectionStore.d.ts.map +1 -0
- package/dist/dts/foldIntoRef.d.ts +39 -0
- package/dist/dts/foldIntoRef.d.ts.map +1 -0
- package/dist/dts/inMemoryProjectionStore.d.ts +11 -0
- package/dist/dts/inMemoryProjectionStore.d.ts.map +1 -0
- package/dist/dts/index.d.ts +185 -0
- package/dist/dts/index.d.ts.map +1 -0
- package/dist/dts/projectionWiringFault.d.ts +260 -0
- package/dist/dts/projectionWiringFault.d.ts.map +1 -0
- package/dist/dts/runProjection.d.ts +185 -0
- package/dist/dts/runProjection.d.ts.map +1 -0
- package/dist/dts/runProjections.d.ts +480 -0
- package/dist/dts/runProjections.d.ts.map +1 -0
- package/dist/dts/superviseOnProgress.d.ts +587 -0
- package/dist/dts/superviseOnProgress.d.ts.map +1 -0
- package/dist/dts/testing.d.ts +207 -0
- package/dist/dts/testing.d.ts.map +1 -0
- package/dist/esm/EventLogDurability.js +175 -0
- package/dist/esm/EventLogDurability.js.map +1 -0
- package/dist/esm/ProjectionRunner.js +468 -0
- package/dist/esm/ProjectionRunner.js.map +1 -0
- package/dist/esm/ProjectionStore.js +223 -0
- package/dist/esm/ProjectionStore.js.map +1 -0
- package/dist/esm/foldIntoRef.js +29 -0
- package/dist/esm/foldIntoRef.js.map +1 -0
- package/dist/esm/inMemoryProjectionStore.js +131 -0
- package/dist/esm/inMemoryProjectionStore.js.map +1 -0
- package/dist/esm/index.js +185 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/package.json +4 -0
- package/dist/esm/projectionWiringFault.js +524 -0
- package/dist/esm/projectionWiringFault.js.map +1 -0
- package/dist/esm/runProjection.js +109 -0
- package/dist/esm/runProjection.js.map +1 -0
- package/dist/esm/runProjections.js +137 -0
- package/dist/esm/runProjections.js.map +1 -0
- package/dist/esm/superviseOnProgress.js +571 -0
- package/dist/esm/superviseOnProgress.js.map +1 -0
- package/dist/esm/testing.js +133 -0
- package/dist/esm/testing.js.map +1 -0
- package/package.json +41 -0
- package/src/EventLogDurability.ts +201 -0
- package/src/ProjectionRunner.ts +923 -0
- package/src/ProjectionStore.ts +528 -0
- package/src/foldIntoRef.ts +63 -0
- package/src/inMemoryProjectionStore.ts +163 -0
- package/src/index.ts +218 -0
- package/src/projectionWiringFault.ts +694 -0
- package/src/runProjection.ts +270 -0
- package/src/runProjections.ts +623 -0
- package/src/superviseOnProgress.ts +897 -0
- package/src/testing.ts +290 -0
- package/testing/package.json +6 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runProjection.js","names":["Effect","Layer","buildAndFork","prepareProjection","resolveProjection","runProjection","readModel","options","gen","view","store","resolved","prepared","slices","cursorIdentity","key","projection","partition","query","decode","apply","projectionLayer","scopedDiscard"],"sources":["../../src/runProjection.ts"],"sourcesContent":[null],"mappings":"AAuCA,SAA4BA,MAAM,EAAEC,KAAK,QAAoB,QAAQ;AAErE,SACEC,YAAY,EAGZC,iBAAiB,EACjBC,iBAAiB,QACZ,uBAAoB;AAuF3B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0CA,OAAO,MAAMC,aAAa,GAAGA,CAC3BC,SAA6B,EAC7BC,OAAiC,KAWjCP,MAAM,CAACQ,GAAG,CAAC,aAAS;EAClB;EACA;EACA;EACA;EACA;EACA,MAAMC,IAAI,GAAGH,SAAS,CAACI,KAAK;EAC5B,MAAMC,QAAQ,GAAGP,iBAAiB,CAACK,IAAI,EAAEF,OAAO,CAAC;EAEjD;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,MAAMK,QAAQ,GAAG,OAAOT,iBAAiB,CACvCG,SAAS,CAACO,MAAM,EAChB,CAAC;IAAE,GAAGF,QAAQ;IAAEG,cAAc,EAAEL;EAAI,CAAE,CAAC,EACvC,+CAA+C,GAC7C,IAAIE,QAAQ,CAACI,GAAG,CAACC,UAAU,eAAe,GAC1C,IAAIL,QAAQ,CAACI,GAAG,CAACE,SAAS,IAAI,CACjC;EAED;EACA,OAAO,OAAOf,YAAY,CAACS,QAAQ,EAAE;IACnCO,KAAK,EAAEN,QAAQ,CAACM,KAAK;IACrBC,MAAM,EAAEP,QAAQ,CAACO,MAAM;IACvBC,KAAK,EAAEd,SAAS,CAACc,KAAK;IACtBb;GACD,CAAC;AACJ,CAAC,CAAC;AAEJ;;;;;;;;;;;;;;;;;;;;;;;;;;AA0BA,OAAO,MAAMc,eAAe,GAAGA,CAK7Bf,SAA6B,EAC7BC,OAAiC,KAK9BN,KAAK,CAACqB,aAAa,CAACjB,aAAa,CAACC,SAAS,EAAEC,OAAO,CAAC,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { Array as Arr, Effect } from 'effect';
|
|
2
|
+
import { buildAndFork, prepareProjection, resolveProjection } from "./ProjectionRunner.js";
|
|
3
|
+
import { checkpointKey, forKey } from "./ProjectionStore.js";
|
|
4
|
+
/**
|
|
5
|
+
* Start one daemon per materialisation, all forked into the caller's `Scope`.
|
|
6
|
+
*
|
|
7
|
+
* The returned effect is INFALLIBLE for the reason `runProjection`'s is: starting a
|
|
8
|
+
* projection cannot fail, because everything that can go wrong once one is running
|
|
9
|
+
* belongs to its own supervisor and lives on its own fibre's error channel. The
|
|
10
|
+
* runners come back in ENTRY ORDER, so `runners[i]` is `materialisations[i]`'s.
|
|
11
|
+
*
|
|
12
|
+
* Each runner carries the store THIS call bound for its entry, so `runners[i].store`
|
|
13
|
+
* is that materialisation's cursor and a caller observing one re-derives no binding
|
|
14
|
+
* it never wrote. It is also what tells the N handles apart: under one `ProjectionId`
|
|
15
|
+
* the keys are equal wherever no entry named a partition, so a runner carrying only a
|
|
16
|
+
* key could not name which of the N views it maintains.
|
|
17
|
+
*
|
|
18
|
+
* ## N = 1 is legal and carries nothing inert
|
|
19
|
+
*
|
|
20
|
+
* One entry is `runProjection` with the `forKey` binding done for you, and every
|
|
21
|
+
* field means the same thing it means at N = 3. The two run the identical phases —
|
|
22
|
+
* one `resolveProjection`, one `prepareProjection`, one `buildAndFork` — rather than
|
|
23
|
+
* merely offering the same surface, so there is no threshold at which a caller should
|
|
24
|
+
* switch functions: a read model that grows a second materialisation adds an entry.
|
|
25
|
+
*
|
|
26
|
+
* ## Every rule is judged before ANY entry is forked
|
|
27
|
+
*
|
|
28
|
+
* The construction gate takes the whole call — the shared log, query and slice
|
|
29
|
+
* record, plus the N resolved wirings — and this call reaches it ONCE, through
|
|
30
|
+
* `prepareProjection`, above the `Effect.forEach` below. So a call refused for ANY
|
|
31
|
+
* reason has forked NOTHING,
|
|
32
|
+
* not even the entries that were sound: not the collision, which is a property of
|
|
33
|
+
* the set, and not a degenerate `batchWindow` or an R2 violation on the last entry
|
|
34
|
+
* either. Half a call running is a worse state than none of it, and the pairing of N
|
|
35
|
+
* materialisations is one wiring decision.
|
|
36
|
+
*
|
|
37
|
+
* Two consequences of the gate judging a SET are worth stating rather than leaving
|
|
38
|
+
* to be met.
|
|
39
|
+
*
|
|
40
|
+
* A per-entry rung names its ENTRY. The gate prefixes its verdict with
|
|
41
|
+
* `materialisations[i]` where there is more than one entry, in the vocabulary the
|
|
42
|
+
* collision sentence already uses; this function's preamble names the PROJECTION and
|
|
43
|
+
* no partition, because under one `ProjectionId` the N keys are equal wherever no
|
|
44
|
+
* entry named a partition, so a partition never discriminated them.
|
|
45
|
+
*
|
|
46
|
+
* And the order is over RULES, not over entries. Where two entries break two
|
|
47
|
+
* DIFFERENT rules the earlier RULE wins whatever entry it is in — entry 0's
|
|
48
|
+
* degenerate `batchWindow` beside entry 1's illegal durability pairing reports entry
|
|
49
|
+
* 1's R2 fault, because R2 is the wider mistake wherever it sits. The gate's module
|
|
50
|
+
* doc argues that, and it is why the rules are judged rule-major rather than by
|
|
51
|
+
* walking the entries.
|
|
52
|
+
*/
|
|
53
|
+
export const runProjections = spec => Effect.gen(function* () {
|
|
54
|
+
// ## RESOLVE — everything the gate has to judge, and every figure that runs
|
|
55
|
+
//
|
|
56
|
+
// Each entry's key and its five defaulted figures, through the same pure
|
|
57
|
+
// `resolveProjection` a single wiring goes through. Resolved here and carried,
|
|
58
|
+
// rather than derived twice: the gate below judges these values and the pipelines
|
|
59
|
+
// further down run from these same values, so what was checked cannot differ from
|
|
60
|
+
// what runs.
|
|
61
|
+
//
|
|
62
|
+
// Built as an EXPLICIT literal rather than by spreading the `Materialisation`,
|
|
63
|
+
// so every field on an entry has exactly one meaning and nothing dead rides
|
|
64
|
+
// along. A spread would carry the caller's `store` and `partition` into a record
|
|
65
|
+
// that already holds the BOUND view (from the resolve step) and the UNBOUND port
|
|
66
|
+
// under `cursorIdentity` — two names for one reference, one name for a different
|
|
67
|
+
// one, and a `partition` nothing downstream reads because `key` has absorbed it.
|
|
68
|
+
// That is a near-miss of the very hazard `cursorIdentity` was renamed to close.
|
|
69
|
+
//
|
|
70
|
+
// `cursorIdentity` is the UNBOUND port here, which is the last surface at which
|
|
71
|
+
// sameness is askable — `forKey` returns a fresh literal per call and does not
|
|
72
|
+
// expose what it closed over, so two bound views are never equal even over one
|
|
73
|
+
// store. `runProjection` passes its bound view instead, which is free at an arity
|
|
74
|
+
// where the rung cannot fire. `MaterialisationWiring`'s doc owns that argument.
|
|
75
|
+
const entries = Arr.map(spec.materialisations, materialisation => {
|
|
76
|
+
const key = checkpointKey(spec.projection, materialisation.partition);
|
|
77
|
+
return {
|
|
78
|
+
...resolveProjection(forKey(materialisation.store, key), materialisation.options),
|
|
79
|
+
cursorIdentity: materialisation.store,
|
|
80
|
+
apply: materialisation.apply,
|
|
81
|
+
options: materialisation.options
|
|
82
|
+
};
|
|
83
|
+
});
|
|
84
|
+
// ## PREPARE — the log's durability, the merged query, the gate, the decode
|
|
85
|
+
//
|
|
86
|
+
// The shared middle, and the same call `runProjection` makes with a singleton.
|
|
87
|
+
// It reads the LOG's half of R2 from context — once for the call, because it IS
|
|
88
|
+
// one fact about one log — composes the ONE query the N subscriptions share,
|
|
89
|
+
// judges all five rungs over the whole entry list, and only then builds the ONE
|
|
90
|
+
// decode stage the N pipelines share. All of it above the `Effect.forEach` below,
|
|
91
|
+
// so a refused call has forked nothing.
|
|
92
|
+
//
|
|
93
|
+
// The order of the last two steps is `prepareProjection`'s to own, and it is why
|
|
94
|
+
// `decodeSlices` is not simply hoisted beside the composition: a record wrong in
|
|
95
|
+
// the codec's way AND in one of the gate's must meet the gate's sentence.
|
|
96
|
+
//
|
|
97
|
+
// The preamble is this function's own half of the defect message: the PROJECTION
|
|
98
|
+
// and no partition, because under one `ProjectionId` the N keys are equal wherever
|
|
99
|
+
// no entry named one, so a partition never discriminated them. The gate prefixes
|
|
100
|
+
// the entry index itself, where there is a set to index into.
|
|
101
|
+
const prepared = yield* prepareProjection(spec.slices, entries, `runProjections: invalid wiring for projection '${spec.projection}'`);
|
|
102
|
+
// ## FORK — one runner per entry, SEQUENTIALLY
|
|
103
|
+
//
|
|
104
|
+
// No `concurrency` option, deliberately. `buildAndFork` returns as soon as its
|
|
105
|
+
// daemon is forked into this scope, so it does no waiting for a concurrent pass
|
|
106
|
+
// to overlap: concurrency would buy nothing and would cost the returned ORDER,
|
|
107
|
+
// which is what lets a caller pair a runner with the entry it maintains. The
|
|
108
|
+
// daemons themselves run concurrently regardless — that is what forking them is.
|
|
109
|
+
//
|
|
110
|
+
// A runner naming its own bound cursor does not make that order redundant. The
|
|
111
|
+
// entry hands over an UNBOUND port and `forKey` deliberately does not expose what
|
|
112
|
+
// it closed over, so nothing a caller still holds can be compared against
|
|
113
|
+
// `runners[i].store` to recover which entry it came from. The order is the only
|
|
114
|
+
// statement of that pairing, and it is why this fold stays sequential.
|
|
115
|
+
//
|
|
116
|
+
// Each entry reaches the SAME build step a single wiring reaches, with the same
|
|
117
|
+
// shared query and the same shared decode stage, so the N pipelines differ in
|
|
118
|
+
// nothing but their store, their `apply` and their tuning.
|
|
119
|
+
return yield* Effect.forEach(entries, entry => buildAndFork(entry, {
|
|
120
|
+
query: prepared.query,
|
|
121
|
+
decode: prepared.decode,
|
|
122
|
+
// THE one assertion in this function, and the reason the requirement
|
|
123
|
+
// channel declared above is checked rather than wished for. Inside the
|
|
124
|
+
// body an entry is known only by its constraint, so this `apply` reads as
|
|
125
|
+
// `Effect<void, unknown, unknown>`; naming the alias the return type
|
|
126
|
+
// already names is what carries the entries' real requirement through
|
|
127
|
+
// `buildAndFork`, where a wildcard bound would instead absorb the lot and
|
|
128
|
+
// leave every member of that union unverified. It is narrow on purpose —
|
|
129
|
+
// `entry.apply` alone, to one expression written in one other place —
|
|
130
|
+
// and it cannot be dropped: without it the module does not compile.
|
|
131
|
+
// `MaterialisationAny` owns the mechanic, `MaterialisedProjection` what
|
|
132
|
+
// the compiler is being asked to take on trust.
|
|
133
|
+
apply: entry.apply,
|
|
134
|
+
options: entry.options
|
|
135
|
+
}));
|
|
136
|
+
});
|
|
137
|
+
//# sourceMappingURL=runProjections.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runProjections.js","names":["Array","Arr","Effect","buildAndFork","prepareProjection","resolveProjection","checkpointKey","forKey","runProjections","spec","gen","entries","map","materialisations","materialisation","key","projection","partition","store","options","cursorIdentity","apply","prepared","slices","forEach","entry","query","decode"],"sources":["../../src/runProjections.ts"],"sourcesContent":[null],"mappings":"AA8FA,SAASA,KAAK,IAAIC,GAAG,EAAEC,MAAM,QAAoB,QAAQ;AAEzD,SACEC,YAAY,EAGZC,iBAAiB,EACjBC,iBAAiB,QACZ,uBAAoB;AAC3B,SACEC,aAAa,EACbC,MAAM,QAID,sBAAmB;AAiW1B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiDA,OAAO,MAAMC,cAAc,GAIzBC,IAAmC,IAWnCP,MAAM,CAACQ,GAAG,CAAC,aAAS;EAClB;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,MAAMC,OAAO,GAAGV,GAAG,CAACW,GAAG,CAACH,IAAI,CAACI,gBAAgB,EAAGC,eAAe,IAAI;IACjE,MAAMC,GAAG,GAAGT,aAAa,CAACG,IAAI,CAACO,UAAU,EAAEF,eAAe,CAACG,SAAS,CAAC;IACrE,OAAO;MACL,GAAGZ,iBAAiB,CAClBE,MAAM,CAACO,eAAe,CAACI,KAAK,EAAEH,GAAG,CAAC,EAClCD,eAAe,CAACK,OAAO,CACxB;MACDC,cAAc,EAAEN,eAAe,CAACI,KAAK;MACrCG,KAAK,EAAEP,eAAe,CAACO,KAAK;MAC5BF,OAAO,EAAEL,eAAe,CAACK;KAC1B;EACH,CAAC,CAAC;EAEF;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,MAAMG,QAAQ,GAAG,OAAOlB,iBAAiB,CACvCK,IAAI,CAACc,MAAM,EACXZ,OAAO,EACP,kDAAkDF,IAAI,CAACO,UAAU,GAAG,CACrE;EAED;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,OAAO,OAAOd,MAAM,CAACsB,OAAO,CAACb,OAAO,EAAGc,KAAK,IAC1CtB,YAAY,CAACsB,KAAK,EAAE;IAClBC,KAAK,EAAEJ,QAAQ,CAACI,KAAK;IACrBC,MAAM,EAAEL,QAAQ,CAACK,MAAM;IACvB;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACAN,KAAK,EAAEI,KAAK,CAACJ,KAEgD;IAC7DF,OAAO,EAAEM,KAAK,CAACN;GAChB,CAAC,CACH;AACH,CAAC,CAAC","ignoreList":[]}
|