effect-dynamodb 1.28.0 → 1.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/dist/Batch.d.ts.map +1 -1
  2. package/dist/Batch.js +3 -2
  3. package/dist/Batch.js.map +1 -1
  4. package/dist/Entity.d.ts +24 -1
  5. package/dist/Entity.d.ts.map +1 -1
  6. package/dist/Entity.js +29 -15
  7. package/dist/Entity.js.map +1 -1
  8. package/dist/EventStore.d.ts +8 -2
  9. package/dist/EventStore.d.ts.map +1 -1
  10. package/dist/EventStore.js +35 -12
  11. package/dist/EventStore.js.map +1 -1
  12. package/dist/Transaction.d.ts.map +1 -1
  13. package/dist/Transaction.js +5 -2
  14. package/dist/Transaction.js.map +1 -1
  15. package/dist/change-feed/ChangeFeed.d.ts +203 -0
  16. package/dist/change-feed/ChangeFeed.d.ts.map +1 -0
  17. package/dist/change-feed/ChangeFeed.js +498 -0
  18. package/dist/change-feed/ChangeFeed.js.map +1 -0
  19. package/dist/change-feed/CheckpointStore.d.ts +113 -0
  20. package/dist/change-feed/CheckpointStore.d.ts.map +1 -0
  21. package/dist/change-feed/CheckpointStore.js +247 -0
  22. package/dist/change-feed/CheckpointStore.js.map +1 -0
  23. package/dist/change-feed/DynamoStreamsClient.d.ts +71 -0
  24. package/dist/change-feed/DynamoStreamsClient.d.ts.map +1 -0
  25. package/dist/change-feed/DynamoStreamsClient.js +92 -0
  26. package/dist/change-feed/DynamoStreamsClient.js.map +1 -0
  27. package/dist/change-feed/Errors.d.ts +84 -0
  28. package/dist/change-feed/Errors.d.ts.map +1 -0
  29. package/dist/change-feed/Errors.js +40 -0
  30. package/dist/change-feed/Errors.js.map +1 -0
  31. package/dist/change-feed/index.d.ts +36 -0
  32. package/dist/change-feed/index.d.ts.map +1 -0
  33. package/dist/change-feed/index.js +36 -0
  34. package/dist/change-feed/index.js.map +1 -0
  35. package/dist/index.d.ts +1 -1
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +1 -1
  38. package/dist/index.js.map +1 -1
  39. package/dist/internal/EntityOps.d.ts +1 -1
  40. package/dist/internal/EntityOps.d.ts.map +1 -1
  41. package/dist/internal/EntityOps.js.map +1 -1
  42. package/dist/internal/EventProjection.d.ts +212 -27
  43. package/dist/internal/EventProjection.d.ts.map +1 -1
  44. package/dist/internal/EventProjection.js +221 -308
  45. package/dist/internal/EventProjection.js.map +1 -1
  46. package/dist/internal/MultiProjection.d.ts +255 -0
  47. package/dist/internal/MultiProjection.d.ts.map +1 -0
  48. package/dist/internal/MultiProjection.js +377 -0
  49. package/dist/internal/MultiProjection.js.map +1 -0
  50. package/dist/internal/ProjectionEngine.d.ts +253 -0
  51. package/dist/internal/ProjectionEngine.d.ts.map +1 -0
  52. package/dist/internal/ProjectionEngine.js +837 -0
  53. package/dist/internal/ProjectionEngine.js.map +1 -0
  54. package/dist/internal/TransactWriteOps.d.ts.map +1 -1
  55. package/dist/internal/TransactWriteOps.js +12 -3
  56. package/dist/internal/TransactWriteOps.js.map +1 -1
  57. package/dist/internal/TransactableOps.d.ts +44 -1
  58. package/dist/internal/TransactableOps.d.ts.map +1 -1
  59. package/dist/internal/TransactableOps.js +52 -2
  60. package/dist/internal/TransactableOps.js.map +1 -1
  61. package/package.json +14 -3
@@ -0,0 +1,377 @@
1
+ /**
2
+ * Multi-source projections (#153): read-model rows that several streams
3
+ * contribute to, with a checkpoint per source instance, gap-filling per
4
+ * instance, and one write per row guarded by the row's revision.
5
+ *
6
+ * Re-exported from `EventStore`; built on `ProjectionEngine`.
7
+ *
8
+ * @internal
9
+ */
10
+ import { Duration, Effect, Option, Pipeable, Result } from "effect";
11
+ import { ProjectionRoutes, refuseReadModel, resolveOutbox, resolveRevision, runBatch, } from "./EventProjection.js";
12
+ import { addressed, instanceKey, keyId, makeEngine, retrySchedule, } from "./ProjectionEngine.js";
13
+ const MultiSourceTypeId = Symbol.for("effect-dynamodb/MultiProjection/Source");
14
+ const MultiProjectionTypeId = Symbol.for("effect-dynamodb/MultiProjection");
15
+ /** @internal */
16
+ export const isMultiProjection = (u) => typeof u === "object" && u !== null && MultiProjectionTypeId in u;
17
+ // ---------------------------------------------------------------------------
18
+ // multiProjection
19
+ // ---------------------------------------------------------------------------
20
+ /**
21
+ * A projection of several source streams into one read model: each row keeps
22
+ * a checkpoint per contributing source instance (`checkpoints`), and every
23
+ * write is guarded by the row's `revision`, so writers serving different
24
+ * sources serialise. See {@link MultiProjection}.
25
+ *
26
+ * @example
27
+ * ```ts
28
+ * const Shipments = EventStore.multiProjection({
29
+ * readModel: ShipmentSummaries,
30
+ * initial: (key) => ShipmentSummary.empty(key),
31
+ * sources: (source) => ({
32
+ * order: source(OrderEvents, { key: (id, e) => …, evolve: … }),
33
+ * scan: source(ScanEvents, { key: …, evolve: …, mode: "latest" }),
34
+ * }),
35
+ * checkpoints: { field: "checkpoints" },
36
+ * revision: "revision",
37
+ * })
38
+ * ```
39
+ */
40
+ export const multiProjection = (config) => {
41
+ const { readModel } = config;
42
+ const sources = config.sources((stream, source) => ({
43
+ [MultiSourceTypeId]: undefined,
44
+ stream,
45
+ key: source.key,
46
+ evolve: source.evolve,
47
+ mode: source.mode ?? "fold",
48
+ terminal: source.terminal ?? (() => false),
49
+ }));
50
+ const names = Object.keys(sources);
51
+ const label = `EventStore.multiProjection("${readModel.entityType}")`;
52
+ const mapped = (config.checkpoints.sources ?? {});
53
+ if (config.checkpoints.field === undefined && Object.keys(mapped).length === 0) {
54
+ throw new Error(`[EDD-9081] ${label}: \`checkpoints\` declares neither \`field\` nor \`sources\`.`);
55
+ }
56
+ for (const name of Object.keys(mapped)) {
57
+ if (!names.includes(name)) {
58
+ throw new Error(`[EDD-9081] ${label}: \`checkpoints.sources.${name}\` names no source.`);
59
+ }
60
+ }
61
+ if (config.checkpoints.field === undefined) {
62
+ for (const name of names) {
63
+ if (mapped[name] === undefined) {
64
+ throw new Error(`[EDD-9081] ${label}: source "${name}" has no checkpoint — declare \`checkpoints.field\` ` +
65
+ "(a map for every source) or a field for it in `checkpoints.sources`.");
66
+ }
67
+ }
68
+ }
69
+ const revision = resolveRevision(config.revision);
70
+ refuseReadModel(label, readModel, {
71
+ fields: [
72
+ revision.field,
73
+ ...(config.checkpoints.field === undefined ? [] : [config.checkpoints.field]),
74
+ ...Object.values(mapped).flatMap((f) => [f.field, f.instanceField]),
75
+ ],
76
+ removal: config.removal !== undefined,
77
+ outbox: config.outbox !== undefined,
78
+ revision: revision.field,
79
+ });
80
+ const engineSources = {};
81
+ for (const name of names) {
82
+ const src = sources[name];
83
+ engineSources[name] = {
84
+ name,
85
+ stream: src.stream,
86
+ key: src.key,
87
+ evolve: src.evolve,
88
+ mode: src.mode,
89
+ terminal: src.terminal,
90
+ };
91
+ }
92
+ const engine = makeEngine({
93
+ label,
94
+ readModel: readModel,
95
+ sources: names.map((n) => engineSources[n]),
96
+ initial: (key) => config.initial(key),
97
+ checkpoints: {
98
+ kind: "sources",
99
+ map: config.checkpoints.field,
100
+ fields: Object.fromEntries(Object.entries(mapped).map(([n, f]) => [
101
+ n,
102
+ { field: f.field, offset: f.offset ?? 0, instanceField: f.instanceField },
103
+ ])),
104
+ },
105
+ revision,
106
+ toItem: config.toItem,
107
+ toItemContext: (key) => ({ key }),
108
+ retry: retrySchedule(config.retry),
109
+ removal: config.removal === undefined
110
+ ? undefined
111
+ : {
112
+ ttl: config.removal.ttl === undefined
113
+ ? undefined
114
+ : Duration.fromInputUnsafe(config.removal.ttl),
115
+ },
116
+ outbox: resolveOutbox(config.outbox),
117
+ });
118
+ const appliedOf = (result) => ({
119
+ key: result.key,
120
+ instances: result.instances,
121
+ state: result.state,
122
+ removed: result.removed,
123
+ revision: result.revision,
124
+ enqueued: result.enqueued,
125
+ undelivered: Option.none(),
126
+ });
127
+ const deliverAfter = (applied, deliver) => deliver === undefined || config.outbox === undefined || applied.enqueued === 0
128
+ ? Effect.succeed(applied)
129
+ : engine.drain(applied.key, deliver).pipe(Effect.map((drained) => ({
130
+ ...applied,
131
+ undelivered: drained.undelivered,
132
+ })));
133
+ const applyBatch = (events, options) => Effect.gen(function* () {
134
+ // By source instance, in order of first delivery.
135
+ const instances = new Map();
136
+ events.forEach((tagged, position) => {
137
+ const source = engineSources[tagged.stream];
138
+ if (source === undefined)
139
+ return;
140
+ const id = `${tagged.stream}\u0000${tagged.event.streamId}`;
141
+ const group = instances.get(id);
142
+ if (group === undefined) {
143
+ instances.set(id, {
144
+ source,
145
+ streamIdStr: tagged.event.streamId,
146
+ positions: [position],
147
+ events: [tagged.event],
148
+ });
149
+ }
150
+ else {
151
+ group.positions.push(position);
152
+ group.events.push(tagged.event);
153
+ }
154
+ });
155
+ const ignored = [];
156
+ const failed = [];
157
+ // Rows across sources: each row's work, one entry per instance.
158
+ const rows = new Map();
159
+ for (const group of instances.values()) {
160
+ const placed = yield* Effect.result(Effect.gen(function* () {
161
+ const streamId = yield* group.source.stream.parseStreamId(group.streamIdStr);
162
+ const byRow = new Map();
163
+ for (let i = 0; i < group.events.length; i++) {
164
+ const event = group.events[i];
165
+ const key = addressed(yield* engine.call("key", () => group.source.key(streamId, event)));
166
+ if (Option.isNone(key)) {
167
+ ignored.push(group.positions[i]);
168
+ continue;
169
+ }
170
+ const id = keyId(key.value);
171
+ const row = byRow.get(id);
172
+ if (row === undefined)
173
+ byRow.set(id, { key: key.value, positions: [group.positions[i]], events: [event] });
174
+ else {
175
+ row.positions.push(group.positions[i]);
176
+ row.events.push(event);
177
+ }
178
+ }
179
+ return { streamId, byRow };
180
+ }));
181
+ if (Result.isFailure(placed)) {
182
+ failed.push({
183
+ _tag: "Failed",
184
+ key: undefined,
185
+ positions: group.positions,
186
+ error: placed.failure,
187
+ });
188
+ continue;
189
+ }
190
+ const delivered = new Set(group.events.map((e) => e.version));
191
+ for (const [id, row] of placed.success.byRow) {
192
+ const ordered = [...row.events]
193
+ .sort((a, b) => a.version - b.version)
194
+ .filter((e, i, sorted) => i === 0 || sorted[i - 1].version !== e.version);
195
+ const entry = rows.get(id) ?? {
196
+ key: row.key,
197
+ positions: [],
198
+ work: [],
199
+ byInstance: new Map(),
200
+ };
201
+ entry.positions.push(...row.positions);
202
+ entry.byInstance.set(`${group.source.name}\u0000${group.streamIdStr}`, row.positions);
203
+ entry.work.push({
204
+ source: group.source,
205
+ streamIdStr: group.streamIdStr,
206
+ streamId: placed.success.streamId,
207
+ events: ordered,
208
+ top: 0,
209
+ delivered,
210
+ });
211
+ rows.set(id, entry);
212
+ }
213
+ }
214
+ const tasks = [...rows.values()].map((row) => {
215
+ const positions = row.positions.sort((a, b) => a - b);
216
+ return {
217
+ first: positions[0],
218
+ run: Effect.result(Effect.gen(function* () {
219
+ const result = (yield* engine.applyRow(row.key, row.work));
220
+ return { result, applied: yield* deliverAfter(appliedOf(result), options?.deliver) };
221
+ })).pipe(Effect.map((outcome) => {
222
+ if (Result.isFailure(outcome)) {
223
+ return [{ _tag: "Failed", key: row.key, positions, error: outcome.failure }];
224
+ }
225
+ // The instances that failed are their own outcomes; the rest applied.
226
+ const failedAt = new Set();
227
+ const instanceFailures = outcome.success.result.failed.map((f) => {
228
+ const at = row.byInstance.get(`${f.source}\u0000${f.streamId}`) ?? [];
229
+ for (const p of at)
230
+ failedAt.add(p);
231
+ return { _tag: "Failed", key: row.key, positions: at, error: f.error };
232
+ });
233
+ return [
234
+ {
235
+ _tag: "Applied",
236
+ positions: positions.filter((p) => !failedAt.has(p)),
237
+ ...outcome.success.applied,
238
+ },
239
+ ...instanceFailures,
240
+ ];
241
+ })),
242
+ };
243
+ });
244
+ tasks.sort((a, b) => a.first - b.first);
245
+ const outcomes = [
246
+ ...failed,
247
+ ...(yield* Effect.forEach(tasks, (task) => task.run, {
248
+ concurrency: options?.concurrency ?? 10,
249
+ })).flat(),
250
+ ]
251
+ .filter((o) => o._tag === "Failed" || o.positions.length > 0 || o.instances.length > 0)
252
+ .sort((a, b) => (a.positions[0] ?? 0) - (b.positions[0] ?? 0));
253
+ return {
254
+ outcomes,
255
+ failedPositions: outcomes
256
+ .filter((o) => o._tag === "Failed")
257
+ .map((o) => o.positions[0])
258
+ .sort((a, b) => a - b),
259
+ ignored: ignored.sort((a, b) => a - b),
260
+ };
261
+ });
262
+ /** The instances a row's checkpoints know: map entries, and field owners. */
263
+ const knownInstances = (values) => {
264
+ const known = [];
265
+ const map = config.checkpoints.field === undefined
266
+ ? {}
267
+ : (values[config.checkpoints.field] ?? {});
268
+ for (const entry of Object.keys(map)) {
269
+ const at = entry.indexOf("#");
270
+ if (at > 0)
271
+ known.push([entry.slice(0, at), entry.slice(at + 1)]);
272
+ }
273
+ for (const [name, f] of Object.entries(mapped)) {
274
+ const owner = values[f.instanceField];
275
+ if (typeof owner === "string" && owner !== "")
276
+ known.push([name, owner]);
277
+ }
278
+ return known.filter(([name]) => engineSources[name] !== undefined);
279
+ };
280
+ const catchUp = (key) => Effect.gen(function* () {
281
+ const row = yield* engine.readRow(key);
282
+ if (Option.isNone(row)) {
283
+ return appliedOf({
284
+ key,
285
+ instances: [],
286
+ state: Option.none(),
287
+ removed: false,
288
+ revision: undefined,
289
+ enqueued: 0,
290
+ failed: [],
291
+ });
292
+ }
293
+ const work = [];
294
+ for (const [name, streamIdStr] of knownInstances(row.value.values)) {
295
+ const source = engineSources[name];
296
+ const streamId = yield* source.stream.parseStreamId(streamIdStr);
297
+ const head = yield* source.stream.currentVersion(streamId, {
298
+ consistentRead: true,
299
+ });
300
+ work.push({
301
+ source,
302
+ streamIdStr,
303
+ streamId,
304
+ events: undefined,
305
+ top: head,
306
+ delivered: new Set(),
307
+ });
308
+ }
309
+ return appliedOf((yield* engine.applyRow(key, work)));
310
+ });
311
+ const rebuild = (key, options) => Effect.gen(function* () {
312
+ const named = options?.instances ??
313
+ (config.sourcesOf === undefined
314
+ ? yield* Effect.die(new Error(`[EDD-9081] ${label}.rebuild: pass \`instances\`, or declare \`sourcesOf\`.`))
315
+ : (yield* config.sourcesOf(key)));
316
+ const rowId = keyId(key);
317
+ const work = [];
318
+ for (const name of names) {
319
+ const ids = (named[name] ??
320
+ []);
321
+ const source = engineSources[name];
322
+ for (const streamId of ids) {
323
+ const events = (yield* source.stream.read(streamId, { consistentRead: true }));
324
+ const mine = [];
325
+ for (const event of events) {
326
+ const k = addressed(yield* engine.call("key", () => source.key(streamId, event)));
327
+ if (Option.isSome(k) && keyId(k.value) === rowId)
328
+ mine.push(event);
329
+ }
330
+ if (mine.length === 0)
331
+ continue;
332
+ work.push({
333
+ source,
334
+ streamIdStr: source.stream.streamIdFields.map((f) => streamId[f]).join("#"),
335
+ streamId,
336
+ events: mine,
337
+ top: mine[mine.length - 1].version,
338
+ delivered: new Set(events.map((e) => e.version)),
339
+ });
340
+ }
341
+ }
342
+ return appliedOf((yield* engine.applyRow(key, work, { fromScratch: true })));
343
+ });
344
+ const routes = (name) => names.map((tag) => ({
345
+ name,
346
+ tag,
347
+ stream: engineSources[tag].stream,
348
+ decode: (image) => engineSources[tag].stream.decodeStreamImage(image),
349
+ applyBatch: (events, applyOptions) => applyBatch(events, applyOptions),
350
+ }));
351
+ const processBatch = (records, options) => runBatch(`${label}.processBatch`, records, options, routes("projection")).pipe(Effect.map(({ outcomes, unrouted: _, ...rest }) => ({
352
+ ...rest,
353
+ outcomes: outcomes.projection,
354
+ })));
355
+ return {
356
+ [MultiProjectionTypeId]: MultiProjectionTypeId,
357
+ pipe() {
358
+ // eslint-disable-next-line prefer-rest-params
359
+ return Pipeable.pipeArguments(this, arguments);
360
+ },
361
+ [ProjectionRoutes]: routes,
362
+ entityType: readModel.entityType,
363
+ sources,
364
+ applyBatch,
365
+ catchUp,
366
+ rebuild,
367
+ processBatch,
368
+ drain: (key, deliver) => config.outbox === undefined
369
+ ? Effect.die(new Error(`[EDD-9081] ${label}.drain: the projection declares no \`outbox\`.`))
370
+ : engine.drain(key, deliver),
371
+ drainPending: (deliver) => config.outbox === undefined
372
+ ? Effect.die(new Error(`[EDD-9081] ${label}.drainPending: the projection declares no \`outbox\`.`))
373
+ : engine.drainPending(deliver),
374
+ };
375
+ };
376
+ export { instanceKey };
377
+ //# sourceMappingURL=MultiProjection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MultiProjection.js","sourceRoot":"","sources":["../../src/internal/MultiProjection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,253 @@
1
+ /**
2
+ * The row engine behind EventStore projections (#151, #153, #154, #155).
3
+ *
4
+ * One engine serves single-source projections (`EventStore.projection`, one
5
+ * source and a scalar checkpoint) and multi-source projections
6
+ * (`EventStore.multiProjection`, a checkpoint per source instance): a row is
7
+ * read strongly consistent, each contributing instance's events are ordered,
8
+ * deduplicated and gap-filled from the store, folded, and written once —
9
+ * conditioned on the row's revision (or, without one, its checkpoint) — as
10
+ * the row, a tombstone (#154), or either together with outbox items in one
11
+ * transaction (#155).
12
+ *
13
+ * Internal: the public shapes live in `EventProjection.ts` / `MultiProjection.ts`.
14
+ *
15
+ * @internal
16
+ */
17
+ import { ConcurrentModification, type ConditionalCheckFailed, ValidationError } from "@effect-dynamodb/schema/Errors.js";
18
+ import { type Duration, Effect, Option, Schedule, type Schema } from "effect";
19
+ import type { StreamEvent } from "../EventStore.js";
20
+ import type * as Query from "../Query.js";
21
+ declare const RemoveRowTypeId: unique symbol;
22
+ /** What `evolve` returns to remove the row — see {@link removeRow}. */
23
+ export interface RemoveRow {
24
+ readonly [RemoveRowTypeId]: typeof RemoveRowTypeId;
25
+ }
26
+ /**
27
+ * Returned from a projection's `evolve`, removes the row: the library writes a
28
+ * tombstone at the row's key that keeps its checkpoints (and revision), so a
29
+ * redelivery can't recreate it. A later event starts the row again from
30
+ * `initial`. Requires `removal` on the projection.
31
+ */
32
+ export declare const removeRow: RemoveRow;
33
+ /** @internal */
34
+ export declare const isRemoveRow: (u: unknown) => u is RemoveRow;
35
+ /** The `__edd_e__` of a read model's tombstones. */
36
+ export declare const tombstoneMarker: (entityType: string) => string;
37
+ /** The `__edd_e__` of a read model's outbox items. */
38
+ export declare const outboxMarker: (entityType: string) => string;
39
+ /** Attribute names the engine owns on tombstones and outbox items. */
40
+ export declare const REMOVED_AT = "__edd_removed__";
41
+ type AnyEvent = StreamEvent<unknown, unknown>;
42
+ /** @internal The read-model entity, as far as the engine uses it. */
43
+ export interface EngineEntity {
44
+ readonly entityType: string;
45
+ readonly model: Schema.Top;
46
+ readonly indexes: {
47
+ readonly primary?: {
48
+ readonly pk: {
49
+ readonly field: string;
50
+ };
51
+ readonly sk: {
52
+ readonly field: string;
53
+ };
54
+ };
55
+ };
56
+ readonly systemFields: {
57
+ readonly createdAt: string | null;
58
+ readonly createdAtEncoding: unknown;
59
+ };
60
+ readonly put: (input: any) => any;
61
+ readonly create: (input: any) => any;
62
+ readonly _tableTag: any;
63
+ readonly _renameToDynamo: (item: Record<string, unknown>) => void;
64
+ readonly _attachPrototype?: ((decoded: any) => any) | undefined;
65
+ readonly _multiItemWriteFeatures?: ReadonlyArray<string> | undefined;
66
+ readonly schemas: any;
67
+ }
68
+ /** @internal One source a row engine reads. */
69
+ export interface EngineSource {
70
+ readonly name: string;
71
+ readonly stream: {
72
+ readonly streamName: string;
73
+ readonly eventMarker: string;
74
+ readonly streamIdFields: ReadonlyArray<string>;
75
+ parseStreamId(id: string): Effect.Effect<any, ValidationError>;
76
+ readFrom(id: any, after: number, options?: any): Effect.Effect<ReadonlyArray<any>, any, any>;
77
+ read(id: any, options?: any): Effect.Effect<ReadonlyArray<any>, any, any>;
78
+ readonly query: {
79
+ events(id: any): Query.Query<any>;
80
+ };
81
+ decodeStreamImage(image: any): Effect.Effect<Option.Option<any>, ValidationError, any>;
82
+ };
83
+ /** `K`, or `Option<K>` (none: the event addresses no row). */
84
+ readonly key: (streamId: any, event: any) => unknown;
85
+ readonly evolve: (state: any, event: any, context: EvolveContext) => Effect.Effect<any, any, any>;
86
+ readonly mode: "fold" | "latest";
87
+ readonly terminal: ((error: any) => boolean) | undefined;
88
+ }
89
+ /** What `evolve` is told about the event it folds. */
90
+ export interface EvolveContext {
91
+ /** The source (a multi-source projection's name for it; `"projection"` otherwise). */
92
+ readonly source: string;
93
+ /** The stream instance (`StreamEvent.streamId`). */
94
+ readonly streamId: string;
95
+ }
96
+ /** @internal Where a row keeps its checkpoints. */
97
+ export type CheckpointLayout = {
98
+ readonly kind: "scalar";
99
+ readonly field: string;
100
+ readonly offset: number;
101
+ } | {
102
+ readonly kind: "sources";
103
+ /** A `Record<string, number>` model field, keyed `<source>#<streamId>`. */
104
+ readonly map: string | undefined;
105
+ readonly fields: Readonly<Record<string, {
106
+ readonly field: string;
107
+ readonly offset: number;
108
+ readonly instanceField: string;
109
+ }>>;
110
+ };
111
+ /** @internal */
112
+ export interface EngineOutbox {
113
+ readonly schema: Schema.Codec<any, any>;
114
+ readonly effects: (event: any, next: any, context: EvolveContext) => ReadonlyArray<any>;
115
+ readonly table: {
116
+ readonly Tag: any;
117
+ } | undefined;
118
+ readonly pk: string;
119
+ readonly sk: string;
120
+ readonly index: {
121
+ readonly name: string;
122
+ readonly pk: string;
123
+ readonly sk: string;
124
+ } | undefined;
125
+ readonly claimFor: Duration.Duration;
126
+ }
127
+ /** @internal */
128
+ export interface EngineConfig {
129
+ readonly label: string;
130
+ readonly readModel: EngineEntity;
131
+ readonly sources: ReadonlyArray<EngineSource>;
132
+ readonly initial: (key: any, context: {
133
+ readonly source: string;
134
+ readonly streamId: any;
135
+ readonly event: any;
136
+ }) => any;
137
+ readonly checkpoints: CheckpointLayout;
138
+ /**
139
+ * The library-owned revision field, incremented and conditioned on by every
140
+ * write; `initial` is the value a row without one is written with.
141
+ */
142
+ readonly revision: {
143
+ readonly field: string;
144
+ readonly initial: number;
145
+ } | undefined;
146
+ readonly toItem: ((state: any, context: any) => any) | undefined;
147
+ readonly retry: Schedule.Schedule<unknown, unknown>;
148
+ readonly removal: {
149
+ readonly ttl: Duration.Duration | undefined;
150
+ } | undefined;
151
+ readonly outbox: EngineOutbox | undefined;
152
+ /** Builds the context `toItem` receives for a row. */
153
+ readonly toItemContext: (key: any, instances: ReadonlyArray<InstanceWork>) => any;
154
+ }
155
+ /** @internal One source instance's share of a row's work. */
156
+ export interface InstanceWork {
157
+ readonly source: EngineSource;
158
+ readonly streamIdStr: string;
159
+ readonly streamId: any;
160
+ /** The batch's events of this instance for this row, sorted and deduplicated; none: catch up to `top`. */
161
+ readonly events: ReadonlyArray<AnyEvent> | undefined;
162
+ /** The highest version wanted when catching up (or rebuilding). */
163
+ readonly top: number;
164
+ /** Versions of every batch event of this instance (any row, or none). */
165
+ readonly delivered: ReadonlySet<number>;
166
+ }
167
+ /** @internal One instance's result. */
168
+ export interface InstanceResult {
169
+ readonly source: string;
170
+ readonly streamId: string;
171
+ readonly applied: ReadonlyArray<AnyEvent>;
172
+ readonly alreadyApplied: ReadonlyArray<AnyEvent>;
173
+ readonly rejected: ReadonlyArray<{
174
+ readonly event: AnyEvent;
175
+ readonly error: unknown;
176
+ }>;
177
+ readonly superseded: ReadonlyArray<AnyEvent>;
178
+ /** The instance's checkpoint after this call, in store numbering. */
179
+ readonly version: number;
180
+ }
181
+ /** @internal A row's result. */
182
+ export interface RowResult {
183
+ readonly key: unknown;
184
+ readonly instances: ReadonlyArray<InstanceResult>;
185
+ readonly state: Option.Option<unknown>;
186
+ readonly removed: boolean;
187
+ readonly revision: number | undefined;
188
+ /** Outbox effects committed with this write. */
189
+ readonly enqueued: number;
190
+ /** Instances that failed and were left out of the write (the others applied). */
191
+ readonly failed: ReadonlyArray<{
192
+ readonly source: string;
193
+ readonly streamId: string;
194
+ readonly error: unknown;
195
+ }>;
196
+ }
197
+ /** A key's identity: its fields, sorted, as JSON. */
198
+ export declare const keyId: (key: unknown) => string;
199
+ /** `K | Option<K>` → `Option<K>`. */
200
+ export declare const addressed: <K>(key: unknown) => Option.Option<K>;
201
+ /** A map checkpoint's key. */
202
+ export declare const instanceKey: (source: string, streamId: string) => string;
203
+ /** @internal */
204
+ export declare const modelFields: (model: Schema.Top) => ReadonlyArray<string> | undefined;
205
+ /** A row as read. */
206
+ interface Row {
207
+ /** The model fields (with `Hidden` ones), or — for a tombstone — the kept checkpoint fields. */
208
+ readonly values: Record<string, unknown>;
209
+ readonly tombstone: boolean;
210
+ readonly createdAt: unknown;
211
+ }
212
+ /** @internal */
213
+ export declare const makeEngine: (config: EngineConfig) => {
214
+ readRow: (key: unknown) => Effect.Effect<Option.Option<Row>, any, any>;
215
+ applyRow: (key: unknown, work: ReadonlyArray<InstanceWork>, options?: {
216
+ readonly fromScratch?: boolean | undefined;
217
+ }) => Effect.Effect<RowResult, any, any>;
218
+ drain: <E, R>(key: unknown, deliver: (effect: any, meta: OutboxMeta) => Effect.Effect<void, E, R>) => Effect.Effect<DrainResult<E>, any, any>;
219
+ drainPending: <E, R>(deliver: (effect: any, meta: OutboxMeta) => Effect.Effect<void, E, R>) => Effect.Effect<{
220
+ delivered: number;
221
+ undelivered: {
222
+ readonly meta: OutboxMeta;
223
+ readonly error: E;
224
+ }[];
225
+ }, any, any>;
226
+ call: <X>(name: string, f: () => X) => Effect.Effect<X, ValidationError>;
227
+ };
228
+ /** What `deliver` is told about an effect. */
229
+ export interface OutboxMeta {
230
+ readonly source: string;
231
+ readonly streamId: string;
232
+ readonly version: number;
233
+ readonly eventType: string;
234
+ }
235
+ /** Result of draining a row's outbox. */
236
+ export interface DrainResult<E> {
237
+ /** Effects delivered (and removed). */
238
+ readonly delivered: number;
239
+ /** The effect `deliver` failed on — it stays pending, at the head. */
240
+ readonly undelivered: Option.Option<{
241
+ readonly meta: OutboxMeta;
242
+ readonly error: E;
243
+ }>;
244
+ }
245
+ /**
246
+ * The default lost-race policy: up to 12 retries after a jittered delay
247
+ * growing from 5 ms by 1.5× (about 1.3 s in all).
248
+ */
249
+ export declare const defaultRetry: Schedule.Schedule<unknown, unknown>;
250
+ /** The `retry` option as a schedule. */
251
+ export declare const retrySchedule: (retry: number | Schedule.Schedule<unknown, ConcurrentModification> | undefined) => Schedule.Schedule<unknown, unknown>;
252
+ export type { ConditionalCheckFailed };
253
+ //# sourceMappingURL=ProjectionEngine.d.ts.map