@photon-grove/evt 0.1.1 → 0.2.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/README.md +51 -4
- package/dist/aggregate.d.ts +26 -0
- package/dist/aggregate.d.ts.map +1 -1
- package/dist/aggregate.js.map +1 -1
- package/dist/dynamodb/head.d.ts +6 -0
- package/dist/dynamodb/head.d.ts.map +1 -1
- package/dist/dynamodb/head.js +11 -0
- package/dist/dynamodb/head.js.map +1 -1
- package/dist/dynamodb/index.d.ts +2 -1
- package/dist/dynamodb/index.d.ts.map +1 -1
- package/dist/dynamodb/index.js +2 -1
- package/dist/dynamodb/index.js.map +1 -1
- package/dist/dynamodb/repository.d.ts +9 -2
- package/dist/dynamodb/repository.d.ts.map +1 -1
- package/dist/dynamodb/repository.js +123 -27
- package/dist/dynamodb/repository.js.map +1 -1
- package/dist/dynamodb/requests.d.ts +37 -3
- package/dist/dynamodb/requests.d.ts.map +1 -1
- package/dist/dynamodb/requests.js +67 -9
- package/dist/dynamodb/requests.js.map +1 -1
- package/dist/dynamodb/views.d.ts +18 -0
- package/dist/dynamodb/views.d.ts.map +1 -0
- package/dist/dynamodb/views.js +56 -0
- package/dist/dynamodb/views.js.map +1 -0
- package/dist/errors.d.ts +51 -4
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +60 -4
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/memory/repository.d.ts +3 -2
- package/dist/memory/repository.d.ts.map +1 -1
- package/dist/memory/repository.js +78 -29
- package/dist/memory/repository.js.map +1 -1
- package/dist/postgres/client.d.ts +32 -0
- package/dist/postgres/client.d.ts.map +1 -0
- package/dist/postgres/client.js +4 -0
- package/dist/postgres/client.js.map +1 -0
- package/dist/postgres/index.d.ts +4 -0
- package/dist/postgres/index.d.ts.map +1 -0
- package/dist/postgres/index.js +6 -0
- package/dist/postgres/index.js.map +1 -0
- package/dist/postgres/repository.d.ts +62 -0
- package/dist/postgres/repository.d.ts.map +1 -0
- package/dist/postgres/repository.js +598 -0
- package/dist/postgres/repository.js.map +1 -0
- package/dist/postgres/schema.d.ts +81 -0
- package/dist/postgres/schema.d.ts.map +1 -0
- package/dist/postgres/schema.js +249 -0
- package/dist/postgres/schema.js.map +1 -0
- package/dist/repository.d.ts +101 -6
- package/dist/repository.d.ts.map +1 -1
- package/dist/repository.js +108 -6
- package/dist/repository.js.map +1 -1
- package/dist/staging.d.ts +28 -0
- package/dist/staging.d.ts.map +1 -0
- package/dist/staging.js +89 -0
- package/dist/staging.js.map +1 -0
- package/dist/store.d.ts +15 -3
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +38 -54
- package/dist/store.js.map +1 -1
- package/dist/transaction.d.ts +113 -0
- package/dist/transaction.d.ts.map +1 -0
- package/dist/transaction.js +207 -0
- package/dist/transaction.js.map +1 -0
- package/package.json +5 -1
- package/src/aggregate.ts +28 -0
- package/src/dynamodb/head.ts +15 -0
- package/src/dynamodb/index.ts +2 -0
- package/src/dynamodb/repository.ts +177 -33
- package/src/dynamodb/requests.ts +114 -10
- package/src/dynamodb/views.ts +67 -0
- package/src/errors.ts +86 -4
- package/src/index.ts +19 -6
- package/src/memory/repository.ts +93 -32
- package/src/postgres/client.ts +37 -0
- package/src/postgres/index.ts +23 -0
- package/src/postgres/repository.ts +858 -0
- package/src/postgres/schema.ts +302 -0
- package/src/repository.ts +220 -8
- package/src/staging.ts +138 -0
- package/src/store.ts +66 -65
- package/src/transaction.ts +322 -0
package/dist/repository.js
CHANGED
|
@@ -1,11 +1,71 @@
|
|
|
1
1
|
// The storage contract every backend implements, and the commit rules every backend applies the
|
|
2
2
|
// same way: validation, the reserved namespaces, and the transaction budget.
|
|
3
|
-
import { headActionSize, headUpdate } from './dynamodb/head.js';
|
|
3
|
+
import { headActionSize, headFence, headUpdate } from './dynamodb/head.js';
|
|
4
4
|
import { eventItem, itemSize, snapshotItem } from './dynamodb/item.js';
|
|
5
5
|
import { FEATURES_PK, REBUILD_LOCK_PK } from './dynamodb/marker.js';
|
|
6
|
-
import { CommitTooLargeError, EvtError, ReservedEntityIdError } from './errors.js';
|
|
6
|
+
import { CommitTooLargeError, EvtError, ProjectorOnlyCommitError, ReservedEntityIdError, RetentionConflictError, SequenceGapError, StreamHeadDriftError, } from './errors.js';
|
|
7
7
|
import { eventId } from './event.js';
|
|
8
8
|
import { MAX_COMMIT_ITEM_BYTES } from './snapshots.js';
|
|
9
|
+
import { compareUtf8 } from './utf8.js';
|
|
10
|
+
/**
|
|
11
|
+
* Validates a transaction and puts it in the order every backend writes it: the written streams,
|
|
12
|
+
* then the fences, each sorted by entity ID bytes, the order that pins a DynamoDB transaction and
|
|
13
|
+
* PostgreSQL's locks. The projector groups keep the order the streams were declared in. Streams
|
|
14
|
+
* without events are dropped, and so are the fences on streams that write events, whose head
|
|
15
|
+
* updates condition on the head they read. A fence on a stream listed without events stays.
|
|
16
|
+
*/
|
|
17
|
+
export function normalizeTransaction(transaction) {
|
|
18
|
+
const listed = new Set();
|
|
19
|
+
for (const stream of transaction.streams) {
|
|
20
|
+
validateCommit(stream);
|
|
21
|
+
checkNotReserved(stream.entityId);
|
|
22
|
+
if (listed.has(stream.entityId)) {
|
|
23
|
+
throw invalidCommit(`duplicate stream ${stream.entityId}`);
|
|
24
|
+
}
|
|
25
|
+
listed.add(stream.entityId);
|
|
26
|
+
}
|
|
27
|
+
const fenced = new Set();
|
|
28
|
+
for (const fence of transaction.fences ?? []) {
|
|
29
|
+
checkNotReserved(fence.entityId);
|
|
30
|
+
if (fence.head < 0n || fence.head >= MAX_INT64 || fenced.has(fence.entityId)) {
|
|
31
|
+
throw invalidCommit(`invalid or duplicate fence ${fence.entityId}`);
|
|
32
|
+
}
|
|
33
|
+
fenced.add(fence.entityId);
|
|
34
|
+
}
|
|
35
|
+
for (const stream of transaction.streams) {
|
|
36
|
+
if (stream.snapshot && stream.events.length === 0) {
|
|
37
|
+
throw invalidCommit(`the snapshot of ${stream.entityId} must cover this commit's last event`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const written = transaction.streams.filter((stream) => stream.events.length > 0);
|
|
41
|
+
const projections = written.flatMap((stream) => stream.projections ?? []);
|
|
42
|
+
const streams = written.map((stream) => Object.assign({}, stream, { projections: undefined }));
|
|
43
|
+
streams.sort(byId);
|
|
44
|
+
const writes = new Set(streams.map((stream) => stream.entityId));
|
|
45
|
+
const fences = (transaction.fences ?? []).filter((fence) => !writes.has(fence.entityId));
|
|
46
|
+
fences.sort(byId);
|
|
47
|
+
return { streams, fences, projections };
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Refuses a transaction that fences a retained entity type, by the store's manifest or the
|
|
51
|
+
* repository's own configuration.
|
|
52
|
+
*/
|
|
53
|
+
export function checkFenceRetention(transaction, retained) {
|
|
54
|
+
for (const fence of transaction.fences) {
|
|
55
|
+
if (retained(fence.entityType)) {
|
|
56
|
+
throw new RetentionConflictError(fence.entityType);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* The error a failed transaction reports from the failures of its streams and fences, given in
|
|
62
|
+
* transaction order: the first drift, else the first gap, else the first of the rest.
|
|
63
|
+
*/
|
|
64
|
+
export function rankFailures(failures) {
|
|
65
|
+
return (failures.find((failure) => failure instanceof StreamHeadDriftError) ??
|
|
66
|
+
failures.find((failure) => failure instanceof SequenceGapError) ??
|
|
67
|
+
failures[0]);
|
|
68
|
+
}
|
|
9
69
|
/** The most actions one commit may carry, DynamoDB's transaction limit. */
|
|
10
70
|
export const MAX_COMMIT_ACTIONS = 100;
|
|
11
71
|
/** The most bytes one commit may carry, summed over its actions: 95% of DynamoDB's 4 MB. */
|
|
@@ -29,11 +89,23 @@ export function checkNotReserved(entityId) {
|
|
|
29
89
|
* Checks that a commit's events can be stored as written: each belongs to the commit's entity and
|
|
30
90
|
* has the ID `{entityId}:{sequence}`, they share one entity type, the first sequence is at least
|
|
31
91
|
* 1, and the sequences are contiguous. A snapshot must have the events' entity type and a
|
|
32
|
-
* sequence of at least 1
|
|
92
|
+
* sequence of at least 1, and each projector group a size per operation. A commit with no events
|
|
93
|
+
* is valid, and its snapshot isn't checked, but its projector operations are refused.
|
|
33
94
|
*/
|
|
34
95
|
export function validateCommit(commit) {
|
|
96
|
+
let operations = 0;
|
|
97
|
+
for (const group of commit.projections ?? []) {
|
|
98
|
+
if (group.sizes.length !== group.operations.length) {
|
|
99
|
+
throw invalidCommit(`a ${group.backend} projector group has ${group.operations.length} operations but ` +
|
|
100
|
+
`${group.sizes.length} sizes`);
|
|
101
|
+
}
|
|
102
|
+
operations += group.operations.length;
|
|
103
|
+
}
|
|
35
104
|
const [first] = commit.events;
|
|
36
105
|
if (first === undefined) {
|
|
106
|
+
if (operations > 0) {
|
|
107
|
+
throw new ProjectorOnlyCommitError(operations);
|
|
108
|
+
}
|
|
37
109
|
return;
|
|
38
110
|
}
|
|
39
111
|
for (const event of commit.events) {
|
|
@@ -72,13 +144,37 @@ export function validateCommit(commit) {
|
|
|
72
144
|
}
|
|
73
145
|
/**
|
|
74
146
|
* The size of each action a commit's transaction carries, in order: the feature-marker and
|
|
75
|
-
* rebuild-lock checks, then the stream's head update, its event puts,
|
|
76
|
-
* it writes one. `ttl` gives the expiry an entity type's items carry, if
|
|
77
|
-
* backend budgets a commit by these sizes, so an oversized commit fails the
|
|
147
|
+
* rebuild-lock checks, the projector operations, then the stream's head update, its event puts,
|
|
148
|
+
* and its snapshot put when it writes one. `ttl` gives the expiry an entity type's items carry, if
|
|
149
|
+
* it's retained. Every backend budgets a commit by these sizes, so an oversized commit fails the
|
|
150
|
+
* same way on each.
|
|
78
151
|
*/
|
|
79
152
|
export function commitSizes(commit, ttl) {
|
|
153
|
+
const transaction = { streams: [commit], fences: [], projections: commit.projections ?? [] };
|
|
154
|
+
return transactionSizes(transaction, ttl);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* The size of each action a transaction carries: the two control checks, every stream's projector
|
|
158
|
+
* operations, every written stream's head update, event puts and snapshot put, then a check on
|
|
159
|
+
* every fenced stream's head. Every backend budgets a transaction by these sizes.
|
|
160
|
+
*/
|
|
161
|
+
export function transactionSizes(transaction, ttl) {
|
|
80
162
|
// The control rows every commit checks: the feature marker and the rebuild lock.
|
|
81
163
|
const sizes = [controlCheckSize(FEATURES_PK), controlCheckSize(REBUILD_LOCK_PK)];
|
|
164
|
+
for (const group of transaction.projections) {
|
|
165
|
+
sizes.push(...group.sizes);
|
|
166
|
+
}
|
|
167
|
+
for (const stream of transaction.streams) {
|
|
168
|
+
sizes.push(...streamSizes(stream, ttl));
|
|
169
|
+
}
|
|
170
|
+
for (const fence of transaction.fences) {
|
|
171
|
+
sizes.push(headActionSize(headFence(fence.entityId, fence.head)));
|
|
172
|
+
}
|
|
173
|
+
return sizes;
|
|
174
|
+
}
|
|
175
|
+
// A written stream's actions: its head update, its event puts and its snapshot put.
|
|
176
|
+
function streamSizes(commit, ttl) {
|
|
177
|
+
const sizes = [];
|
|
82
178
|
const first = commit.events[0];
|
|
83
179
|
const last = commit.events.at(-1);
|
|
84
180
|
if (first === undefined || last === undefined) {
|
|
@@ -120,6 +216,12 @@ export function checkBudget(sizes) {
|
|
|
120
216
|
throw new CommitTooLargeError(sizes.length, bytes, largestItem);
|
|
121
217
|
}
|
|
122
218
|
}
|
|
219
|
+
// Orders streams and fences by their entity IDs' UTF-8 bytes.
|
|
220
|
+
function byId(a, b) {
|
|
221
|
+
return compareUtf8(a.entityId, b.entityId);
|
|
222
|
+
}
|
|
223
|
+
// The largest int64, whose successor no head can reach.
|
|
224
|
+
const MAX_INT64 = 2n ** 63n - 1n;
|
|
123
225
|
// A control check is sized by its key: `pk` and `sk = 0`.
|
|
124
226
|
function controlCheckSize(pk) {
|
|
125
227
|
return itemSize({ pk: { S: pk }, sk: { N: '0' } });
|
package/dist/repository.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repository.js","sourceRoot":"","sources":["../src/repository.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,6EAA6E;AAE7E,OAAO,EAAC,cAAc,EAAE,UAAU,EAAC,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"repository.js","sourceRoot":"","sources":["../src/repository.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type Aggregate, type EventDefinitions, type EventOf } from './aggregate.js';
|
|
2
|
+
import { type SerializedEvent } from './event.js';
|
|
3
|
+
import type { Metadata } from './metadata.js';
|
|
4
|
+
import type { NewSnapshot, ProjectorGroup } from './repository.js';
|
|
5
|
+
/**
|
|
6
|
+
* Serializes decided events continuing the stream after `after`, each with its own copy of
|
|
7
|
+
* `metadata`, and then folds them into `state`. Every event is encoded before any is applied, so
|
|
8
|
+
* when one fails to encode, `state` is untouched, even for an aggregate whose `apply` changes the
|
|
9
|
+
* state it's given.
|
|
10
|
+
*/
|
|
11
|
+
export declare function serializeEvents<S, C, D extends EventDefinitions>(aggregate: Aggregate<S, C, D>, entityId: string, after: bigint, state: S, decided: readonly EventOf<D>[], metadata: Metadata): {
|
|
12
|
+
events: SerializedEvent[];
|
|
13
|
+
state: S;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* The snapshot a commit of `appended` events after `loadedSequence` carries, or null when the
|
|
17
|
+
* interval calls for none. A snapshot whose item is over the per-item commit budget is left out
|
|
18
|
+
* too, since it would fail every commit that carries it.
|
|
19
|
+
*/
|
|
20
|
+
export declare function commitSnapshot<S, C, D extends EventDefinitions>(aggregate: Aggregate<S, C, D>, entityId: string, interval: number, loaded: {
|
|
21
|
+
readonly sequence: bigint;
|
|
22
|
+
readonly snapshotSequence: bigint;
|
|
23
|
+
}, appended: number, state: S): NewSnapshot | null;
|
|
24
|
+
/** The operations the aggregate's projectors add to a commit, in declaration order. */
|
|
25
|
+
export declare function projectCommit<S, C, D extends EventDefinitions>(aggregate: Aggregate<S, C, D>, entityId: string, state: S, events: readonly SerializedEvent[], snapshot: NewSnapshot | null): ProjectorGroup[];
|
|
26
|
+
/** A copy of the metadata, so changing one event's changes no other. */
|
|
27
|
+
export declare function copyMetadata(metadata: Metadata): Metadata;
|
|
28
|
+
//# sourceMappingURL=staging.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"staging.d.ts","sourceRoot":"","sources":["../src/staging.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,KAAK,SAAS,EACd,KAAK,gBAAgB,EACrB,KAAK,OAAO,EAGb,MAAM,gBAAgB,CAAA;AAEvB,OAAO,EAAC,KAAK,eAAe,EAAU,MAAM,YAAY,CAAA;AACxD,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,eAAe,CAAA;AAC3C,OAAO,KAAK,EAAC,WAAW,EAAE,cAAc,EAAC,MAAM,iBAAiB,CAAA;AAKhE;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,SAAS,gBAAgB,EAC9D,SAAS,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC7B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,CAAC,EACR,OAAO,EAAE,SAAS,OAAO,CAAC,CAAC,CAAC,EAAE,EAC9B,QAAQ,EAAE,QAAQ,GACjB;IAAC,MAAM,EAAE,eAAe,EAAE,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAC,CA+BvC;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,SAAS,gBAAgB,EAC7D,SAAS,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC7B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAA;CAAC,EACtE,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,CAAC,GACP,WAAW,GAAG,IAAI,CAcpB;AAED,uFAAuF;AACvF,wBAAgB,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,SAAS,gBAAgB,EAC5D,SAAS,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC7B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,CAAC,EACR,MAAM,EAAE,SAAS,eAAe,EAAE,EAClC,QAAQ,EAAE,WAAW,GAAG,IAAI,GAC3B,cAAc,EAAE,CA2BlB;AAED,wEAAwE;AACxE,wBAAgB,YAAY,CAAC,QAAQ,EAAE,QAAQ,GAAG,QAAQ,CAOzD"}
|
package/dist/staging.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// What a commit of one stream carries beyond its decided events, the same for a single command
|
|
2
|
+
// and for a transaction: the stored events, the snapshot the policy calls for, and the projectors'
|
|
3
|
+
// operations.
|
|
4
|
+
import { encodeEventData, } from './aggregate.js';
|
|
5
|
+
import { EvtError } from './errors.js';
|
|
6
|
+
import { eventId } from './event.js';
|
|
7
|
+
import { MAX_COMMIT_ITEM_BYTES, snapshotCommitSize, snapshotEventsDue } from './snapshots.js';
|
|
8
|
+
const INT64_MAX = 2n ** 63n - 1n;
|
|
9
|
+
/**
|
|
10
|
+
* Serializes decided events continuing the stream after `after`, each with its own copy of
|
|
11
|
+
* `metadata`, and then folds them into `state`. Every event is encoded before any is applied, so
|
|
12
|
+
* when one fails to encode, `state` is untouched, even for an aggregate whose `apply` changes the
|
|
13
|
+
* state it's given.
|
|
14
|
+
*/
|
|
15
|
+
export function serializeEvents(aggregate, entityId, after, state, decided, metadata) {
|
|
16
|
+
let sequence = after;
|
|
17
|
+
const events = [];
|
|
18
|
+
for (const event of decided) {
|
|
19
|
+
if (sequence >= INT64_MAX) {
|
|
20
|
+
throw new EvtError('invalidCommit', `invalid commit: entity ${entityId} is at the maximum event sequence`);
|
|
21
|
+
}
|
|
22
|
+
sequence++;
|
|
23
|
+
const { version, payload } = encodeEventData(aggregate.events, event);
|
|
24
|
+
events.push({
|
|
25
|
+
id: eventId(entityId, sequence),
|
|
26
|
+
sequence,
|
|
27
|
+
type: event.type,
|
|
28
|
+
version,
|
|
29
|
+
entityId,
|
|
30
|
+
entityType: aggregate.type,
|
|
31
|
+
payload,
|
|
32
|
+
metadata: copyMetadata(metadata),
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
for (const event of decided) {
|
|
36
|
+
state = aggregate.apply(state, event);
|
|
37
|
+
}
|
|
38
|
+
return { events, state };
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The snapshot a commit of `appended` events after `loadedSequence` carries, or null when the
|
|
42
|
+
* interval calls for none. A snapshot whose item is over the per-item commit budget is left out
|
|
43
|
+
* too, since it would fail every commit that carries it.
|
|
44
|
+
*/
|
|
45
|
+
export function commitSnapshot(aggregate, entityId, interval, loaded, appended, state) {
|
|
46
|
+
if (snapshotEventsDue(loaded.sequence, appended, interval) === 0) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
const snapshot = {
|
|
50
|
+
entityType: aggregate.type,
|
|
51
|
+
sequence: loaded.snapshotSequence + 1n,
|
|
52
|
+
payload: aggregate.state.encode(state),
|
|
53
|
+
};
|
|
54
|
+
const eventSequence = loaded.sequence + BigInt(appended);
|
|
55
|
+
const size = snapshotCommitSize({ ...snapshot, entityId, eventSequence });
|
|
56
|
+
return size > MAX_COMMIT_ITEM_BYTES ? null : snapshot;
|
|
57
|
+
}
|
|
58
|
+
/** The operations the aggregate's projectors add to a commit, in declaration order. */
|
|
59
|
+
export function projectCommit(aggregate, entityId, state, events, snapshot) {
|
|
60
|
+
const projectors = aggregate.projectors ?? [];
|
|
61
|
+
if (projectors.length === 0) {
|
|
62
|
+
return [];
|
|
63
|
+
}
|
|
64
|
+
// Each projector gets its own frozen copy of the events, their metadata and every byte array,
|
|
65
|
+
// so none can change what another one sees, or what the commit writes.
|
|
66
|
+
const encodedState = snapshot?.payload ?? aggregate.state.encode(state);
|
|
67
|
+
const detached = () => Object.freeze({
|
|
68
|
+
entityType: aggregate.type,
|
|
69
|
+
entityId,
|
|
70
|
+
state,
|
|
71
|
+
encodedState: encodedState.slice(),
|
|
72
|
+
events: Object.freeze(events.map((event) => Object.freeze({
|
|
73
|
+
...event,
|
|
74
|
+
payload: event.payload && event.payload.slice(),
|
|
75
|
+
metadata: Object.freeze(copyMetadata(event.metadata)),
|
|
76
|
+
}))),
|
|
77
|
+
});
|
|
78
|
+
return projectors.flatMap((projector) => projector.project(detached()) ?? []);
|
|
79
|
+
}
|
|
80
|
+
/** A copy of the metadata, so changing one event's changes no other. */
|
|
81
|
+
export function copyMetadata(metadata) {
|
|
82
|
+
return {
|
|
83
|
+
...metadata,
|
|
84
|
+
trace: metadata.trace && new Map(metadata.trace),
|
|
85
|
+
origin: metadata.origin && { ...metadata.origin },
|
|
86
|
+
extensions: new Map(metadata.extensions),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=staging.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"staging.js","sourceRoot":"","sources":["../src/staging.ts"],"names":[],"mappings":"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"}
|
package/dist/store.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { type Aggregate, type EventDefinitions, type Rejection } from './aggregate.js';
|
|
2
|
-
import {
|
|
2
|
+
import type { SerializedEvent } from './event.js';
|
|
3
3
|
import { type Metadata } from './metadata.js';
|
|
4
4
|
import type { CallOptions, Repository } from './repository.js';
|
|
5
5
|
import { type RetryPolicy } from './retry.js';
|
|
6
|
+
import { Transaction } from './transaction.js';
|
|
6
7
|
/** The default number of events between snapshots, as in Go and Rust. */
|
|
7
8
|
export declare const DEFAULT_SNAPSHOT_INTERVAL = 5;
|
|
8
9
|
/** How a {@link Store} fills in what commands leave out. */
|
|
@@ -85,8 +86,10 @@ export declare class Store {
|
|
|
85
86
|
load<S, C, D extends EventDefinitions>(aggregate: Aggregate<S, C, D>, entityId: string, options?: CallOptions): Promise<Loaded<S>>;
|
|
86
87
|
/**
|
|
87
88
|
* Loads the aggregate, runs the command, and commits its events, with a snapshot when the
|
|
88
|
-
* commit reaches the snapshot interval
|
|
89
|
-
* is left out, so the commit still succeeds and
|
|
89
|
+
* commit reaches the snapshot interval, and the aggregate's projector operations. A snapshot
|
|
90
|
+
* whose item is over the per-item commit budget is left out, so the commit still succeeds and
|
|
91
|
+
* later loads replay from the one before, but a projector's own items are budgeted as they are:
|
|
92
|
+
* a view row of a state that large fails the commit.
|
|
90
93
|
*
|
|
91
94
|
* A command ID already carried by an event folded in since the latest snapshot makes the
|
|
92
95
|
* command a `duplicate`, and the handler doesn't run. A conflict with another writer throws;
|
|
@@ -99,5 +102,14 @@ export declare class Store {
|
|
|
99
102
|
* the last error is thrown. A rejection or a duplicate is a result, never retried.
|
|
100
103
|
*/
|
|
101
104
|
executeWithRetry<S, C, D extends EventDefinitions>(aggregate: Aggregate<S, C, D>, entityId: string, command: C, options?: RetryOptions): Promise<ExecuteResult<S>>;
|
|
105
|
+
/**
|
|
106
|
+
* Begins a transaction that reads streams of any aggregate types, appends to some of them, and
|
|
107
|
+
* commits them all at once, with a read fence on every stream it reads but doesn't write. The
|
|
108
|
+
* store's region, clock, commit IDs and snapshot interval apply to it, and each stream's
|
|
109
|
+
* aggregate projectors run in its commit. The repository must be a
|
|
110
|
+
* {@link TransactionalRepository}, as every one this package ships is, or this throws
|
|
111
|
+
* `invalidArgument`. {@link execute} stays the shortcut for one stream.
|
|
112
|
+
*/
|
|
113
|
+
transaction(): Transaction;
|
|
102
114
|
}
|
|
103
115
|
//# sourceMappingURL=store.d.ts.map
|
package/dist/store.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,SAAS,EACd,KAAK,gBAAgB,EAErB,KAAK,SAAS,
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
|
package/dist/store.js
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
// The Store: loads aggregates, runs commands, and commits their events with the snapshots the
|
|
2
2
|
// snapshot policy calls for.
|
|
3
|
-
import {
|
|
3
|
+
import { replayEvent, } from './aggregate.js';
|
|
4
4
|
import { commitIds } from './commit-id.js';
|
|
5
5
|
import { EvtError, SequenceGapError, SnapshotError, isConflict, isRetryable } from './errors.js';
|
|
6
|
-
import { eventId } from './event.js';
|
|
7
6
|
import { emptyMetadata } from './metadata.js';
|
|
8
7
|
import { DEFAULT_RETRY_POLICY, checkRetryPolicy, retryDelay, sleep, } from './retry.js';
|
|
9
|
-
import {
|
|
8
|
+
import { commitSnapshot, projectCommit, serializeEvents } from './staging.js';
|
|
9
|
+
import { Transaction } from './transaction.js';
|
|
10
10
|
/** The default number of events between snapshots, as in Go and Rust. */
|
|
11
11
|
export const DEFAULT_SNAPSHOT_INTERVAL = 5;
|
|
12
12
|
// How many times a load reads the stream when it finds a sequence gap.
|
|
13
13
|
const LOAD_ATTEMPTS = 3;
|
|
14
|
-
const INT64_MAX = 2n ** 63n - 1n;
|
|
15
14
|
export class Store {
|
|
16
15
|
repository;
|
|
17
16
|
#region;
|
|
@@ -59,8 +58,10 @@ export class Store {
|
|
|
59
58
|
}
|
|
60
59
|
/**
|
|
61
60
|
* Loads the aggregate, runs the command, and commits its events, with a snapshot when the
|
|
62
|
-
* commit reaches the snapshot interval
|
|
63
|
-
* is left out, so the commit still succeeds and
|
|
61
|
+
* commit reaches the snapshot interval, and the aggregate's projector operations. A snapshot
|
|
62
|
+
* whose item is over the per-item commit budget is left out, so the commit still succeeds and
|
|
63
|
+
* later loads replay from the one before, but a projector's own items are budgeted as they are:
|
|
64
|
+
* a view row of a state that large fails the commit.
|
|
64
65
|
*
|
|
65
66
|
* A command ID already carried by an event folded in since the latest snapshot makes the
|
|
66
67
|
* command a `duplicate`, and the handler doesn't run. A conflict with another writer throws;
|
|
@@ -80,8 +81,8 @@ export class Store {
|
|
|
80
81
|
if (decision.events.length === 0) {
|
|
81
82
|
return { kind: 'committed', state: loaded, events: [] };
|
|
82
83
|
}
|
|
83
|
-
const { state, events, snapshot } = this.#stage(aggregate, loaded, decision.events, metadata);
|
|
84
|
-
await this.repository.commit({ entityId, events, snapshot }, options);
|
|
84
|
+
const { state, events, snapshot, projections } = this.#stage(aggregate, loaded, decision.events, metadata);
|
|
85
|
+
await this.repository.commit({ entityId, events, snapshot, projections }, options);
|
|
85
86
|
return { kind: 'committed', state, events };
|
|
86
87
|
}
|
|
87
88
|
/**
|
|
@@ -108,6 +109,26 @@ export class Store {
|
|
|
108
109
|
}
|
|
109
110
|
/* oxlint-enable no-await-in-loop */
|
|
110
111
|
}
|
|
112
|
+
/**
|
|
113
|
+
* Begins a transaction that reads streams of any aggregate types, appends to some of them, and
|
|
114
|
+
* commits them all at once, with a read fence on every stream it reads but doesn't write. The
|
|
115
|
+
* store's region, clock, commit IDs and snapshot interval apply to it, and each stream's
|
|
116
|
+
* aggregate projectors run in its commit. The repository must be a
|
|
117
|
+
* {@link TransactionalRepository}, as every one this package ships is, or this throws
|
|
118
|
+
* `invalidArgument`. {@link execute} stays the shortcut for one stream.
|
|
119
|
+
*/
|
|
120
|
+
transaction() {
|
|
121
|
+
const repository = this.repository;
|
|
122
|
+
if (!isTransactional(repository)) {
|
|
123
|
+
throw new EvtError('invalidArgument', 'the repository has no commitTransaction');
|
|
124
|
+
}
|
|
125
|
+
return new Transaction({
|
|
126
|
+
repository,
|
|
127
|
+
load: (aggregate, entityId, options) => this.load(aggregate, entityId, options),
|
|
128
|
+
snapshotInterval: (aggregate) => this.snapshotInterval(aggregate),
|
|
129
|
+
metadata: (partial) => this.#metadata(partial),
|
|
130
|
+
});
|
|
131
|
+
}
|
|
111
132
|
async #loadOnce(aggregate, entityId, options) {
|
|
112
133
|
const snapshot = await this.repository.snapshot(entityId, options);
|
|
113
134
|
let state = aggregate.initial();
|
|
@@ -148,45 +169,13 @@ export class Store {
|
|
|
148
169
|
}
|
|
149
170
|
return { entityId, state, sequence, snapshotSequence, seenCommandIds };
|
|
150
171
|
}
|
|
151
|
-
// Applies the decided events, and builds the stored events
|
|
152
|
-
//
|
|
172
|
+
// Applies the decided events, and builds the stored events, the snapshot the policy calls for,
|
|
173
|
+
// and the projectors' operations. The state is only used once the commit succeeds.
|
|
153
174
|
#stage(aggregate, loaded, decided, metadata) {
|
|
154
175
|
const entityId = loaded.entityId;
|
|
155
|
-
|
|
156
|
-
let state = loaded.state;
|
|
157
|
-
const events = [];
|
|
158
|
-
for (const event of decided) {
|
|
159
|
-
if (sequence >= INT64_MAX) {
|
|
160
|
-
throw new EvtError('invalidCommit', `invalid commit: entity ${entityId} is at the maximum event sequence`);
|
|
161
|
-
}
|
|
162
|
-
sequence++;
|
|
163
|
-
const { version, payload } = encodeEventData(aggregate.events, event);
|
|
164
|
-
events.push({
|
|
165
|
-
id: eventId(entityId, sequence),
|
|
166
|
-
sequence,
|
|
167
|
-
type: event.type,
|
|
168
|
-
version,
|
|
169
|
-
entityId,
|
|
170
|
-
entityType: aggregate.type,
|
|
171
|
-
payload,
|
|
172
|
-
metadata: copyMetadata(metadata),
|
|
173
|
-
});
|
|
174
|
-
state = aggregate.apply(state, event);
|
|
175
|
-
}
|
|
176
|
+
const { events, state } = serializeEvents(aggregate, entityId, loaded.sequence, loaded.state, decided, metadata);
|
|
176
177
|
const interval = this.snapshotInterval(aggregate);
|
|
177
|
-
|
|
178
|
-
if (snapshotEventsDue(loaded.sequence, decided.length, interval) > 0) {
|
|
179
|
-
snapshot = {
|
|
180
|
-
entityType: aggregate.type,
|
|
181
|
-
sequence: loaded.snapshotSequence + 1n,
|
|
182
|
-
payload: aggregate.state.encode(state),
|
|
183
|
-
};
|
|
184
|
-
// A snapshot over the per-item budget would fail every commit that carries it.
|
|
185
|
-
const size = snapshotCommitSize({ ...snapshot, entityId, eventSequence: sequence });
|
|
186
|
-
if (size > MAX_COMMIT_ITEM_BYTES) {
|
|
187
|
-
snapshot = null;
|
|
188
|
-
}
|
|
189
|
-
}
|
|
178
|
+
const snapshot = commitSnapshot(aggregate, entityId, interval, loaded, events.length, state);
|
|
190
179
|
const seenCommandIds = new Set(loaded.seenCommandIds);
|
|
191
180
|
if (metadata.commandId !== null && metadata.commandId !== '') {
|
|
192
181
|
seenCommandIds.add(metadata.commandId);
|
|
@@ -195,12 +184,13 @@ export class Store {
|
|
|
195
184
|
state: {
|
|
196
185
|
entityId,
|
|
197
186
|
state,
|
|
198
|
-
sequence,
|
|
187
|
+
sequence: loaded.sequence + BigInt(events.length),
|
|
199
188
|
snapshotSequence: snapshot ? snapshot.sequence : loaded.snapshotSequence,
|
|
200
189
|
seenCommandIds,
|
|
201
190
|
},
|
|
202
191
|
events,
|
|
203
192
|
snapshot,
|
|
193
|
+
projections: projectCommit(aggregate, entityId, state, events, snapshot),
|
|
204
194
|
};
|
|
205
195
|
}
|
|
206
196
|
// The command's metadata with the store's region and the clock's timestamp where it has none,
|
|
@@ -230,17 +220,11 @@ export class Store {
|
|
|
230
220
|
return metadata;
|
|
231
221
|
}
|
|
232
222
|
}
|
|
233
|
-
// Each stored event gets its own metadata, so changing one changes no other.
|
|
234
|
-
function copyMetadata(metadata) {
|
|
235
|
-
return {
|
|
236
|
-
...metadata,
|
|
237
|
-
trace: metadata.trace && new Map(metadata.trace),
|
|
238
|
-
origin: metadata.origin && { ...metadata.origin },
|
|
239
|
-
extensions: new Map(metadata.extensions),
|
|
240
|
-
};
|
|
241
|
-
}
|
|
242
223
|
// RFC 3339 in UTC, to the second, as Go's time.RFC3339 formats a UTC time.
|
|
243
224
|
function rfc3339Seconds(ms) {
|
|
244
225
|
return new Date(ms).toISOString().replace(/\.\d{3}Z$/, 'Z');
|
|
245
226
|
}
|
|
227
|
+
function isTransactional(repository) {
|
|
228
|
+
return typeof repository.commitTransaction === 'function';
|
|
229
|
+
}
|
|
246
230
|
//# sourceMappingURL=store.js.map
|
package/dist/store.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,6BAA6B;AAE7B,OAAO,EAKL,
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
|