@requence/event-sourcing 1.5.0 → 1.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-24xjphpk.js → chunk-06anxtk6.js} +6 -6
- package/dist/{chunk-24xjphpk.js.map → chunk-06anxtk6.js.map} +2 -2
- package/dist/{chunk-263c07sn.js → chunk-1mr4cwpw.js} +8 -8
- package/dist/{chunk-263c07sn.js.map → chunk-1mr4cwpw.js.map} +2 -2
- package/dist/{chunk-zznvzvnv.js → chunk-2wqpktzp.js} +31 -31
- package/dist/{chunk-zznvzvnv.js.map → chunk-2wqpktzp.js.map} +2 -2
- package/dist/{chunk-dgzw1nj9.js → chunk-467qtkth.js} +8 -3
- package/dist/chunk-467qtkth.js.map +10 -0
- package/dist/chunk-6dn6wxg7.js +11 -0
- package/dist/{chunk-jd4q8fcf.js.map → chunk-6dn6wxg7.js.map} +2 -2
- package/dist/{chunk-pc1q4se9.js → chunk-9qtjz725.js} +2 -2
- package/dist/{chunk-pc1q4se9.js.map → chunk-9qtjz725.js.map} +2 -2
- package/dist/{chunk-tfy01fah.js → chunk-c7sytwpp.js} +4 -4
- package/dist/{chunk-tfy01fah.js.map → chunk-c7sytwpp.js.map} +2 -2
- package/dist/{chunk-kqh3q3fj.js → chunk-d6jqbrq2.js} +29 -29
- package/dist/{chunk-kqh3q3fj.js.map → chunk-d6jqbrq2.js.map} +2 -2
- package/dist/{chunk-7akf01zj.js → chunk-f95c3da4.js} +77 -64
- package/dist/chunk-f95c3da4.js.map +10 -0
- package/dist/chunk-fpjnk143.js +13 -0
- package/dist/{chunk-6q8mr1sg.js.map → chunk-fpjnk143.js.map} +2 -2
- package/dist/{chunk-8qn1nqnh.js → chunk-fxb9fbvz.js} +9 -9
- package/dist/{chunk-8qn1nqnh.js.map → chunk-fxb9fbvz.js.map} +2 -2
- package/dist/chunk-hmvwn02w.js +22 -0
- package/dist/{chunk-6yrb30rx.js.map → chunk-hmvwn02w.js.map} +2 -2
- package/dist/{chunk-ty9bhdvx.js → chunk-j4mwjx07.js} +5 -3
- package/dist/chunk-j4mwjx07.js.map +10 -0
- package/dist/{chunk-391m4mfp.js → chunk-jw9e0fr0.js} +13 -13
- package/dist/{chunk-391m4mfp.js.map → chunk-jw9e0fr0.js.map} +2 -2
- package/dist/chunk-mbxxvskx.js +67 -0
- package/dist/{chunk-ak901ckt.js.map → chunk-mbxxvskx.js.map} +2 -2
- package/dist/{chunk-3251p253.js → chunk-nrhw3kde.js} +8 -8
- package/dist/{chunk-3251p253.js.map → chunk-nrhw3kde.js.map} +2 -2
- package/dist/{chunk-8edc30gz.js → chunk-pcggjrxr.js} +32 -32
- package/dist/{chunk-8edc30gz.js.map → chunk-pcggjrxr.js.map} +2 -2
- package/dist/chunk-tkwe4r0y.js +22 -0
- package/dist/{chunk-2fe8jjdc.js.map → chunk-tkwe4r0y.js.map} +2 -2
- package/dist/{chunk-z388cd25.js → chunk-zkz6ew8c.js} +5 -5
- package/dist/{chunk-z388cd25.js.map → chunk-zkz6ew8c.js.map} +2 -2
- package/dist/createAggregateRoot.d.ts +1 -1
- package/dist/createAggregateRoot.d.ts.map +1 -1
- package/dist/createAggregateRoot.js +15 -14
- package/dist/createAggregateRoot.js.map +1 -1
- package/dist/createCheckpointApi.js +5 -5
- package/dist/createCheckpointApi.js.map +1 -1
- package/dist/createEventListener.js +8 -8
- package/dist/createEventListener.js.map +1 -1
- package/dist/createEventStore.js +16 -16
- package/dist/createEventStore.js.map +1 -1
- package/dist/createProcessManager.js +12 -12
- package/dist/createProcessManager.js.map +1 -1
- package/dist/createProjection.js +12 -12
- package/dist/createProjection.js.map +1 -1
- package/dist/drizzle/index.js +132 -132
- package/dist/drizzle/index.js.map +2 -2
- package/dist/drizzle/postgres.js +14 -14
- package/dist/drizzle/postgres.js.map +1 -1
- package/dist/errors.js +24 -24
- package/dist/errors.js.map +1 -1
- package/dist/index.js +63 -63
- package/dist/index.js.map +1 -1
- package/dist/lock.d.ts +11 -3
- package/dist/lock.d.ts.map +1 -1
- package/dist/lock.js +4 -2
- package/dist/lock.js.map +1 -1
- package/dist/memory/index.js +31 -31
- package/dist/memory/index.js.map +2 -2
- package/dist/redis/index.js +5 -4
- package/dist/redis/index.js.map +1 -1
- package/dist/redis/redisLock.d.ts +1 -1
- package/dist/redis/redisLock.d.ts.map +1 -1
- package/dist/redis/redisLock.js +5 -4
- package/dist/redis/redisLock.js.map +1 -1
- package/dist/refresh.js +9 -9
- package/dist/refresh.js.map +1 -1
- package/dist/replay.js +9 -9
- package/dist/replay.js.map +1 -1
- package/dist/snapshotGenerator.js +2 -2
- package/dist/superjson.js +8 -8
- package/dist/superjson.js.map +1 -1
- package/dist/surreal/index.js +73 -73
- package/dist/surreal/index.js.map +2 -2
- package/dist/surreal/schema.js +8 -8
- package/dist/surreal/schema.js.map +1 -1
- package/dist/transaction.js +1 -1
- package/dist/utils.js +6 -6
- package/dist/utils.js.map +1 -1
- package/dist/wrappedEventBuilder.js +8 -8
- package/dist/wrappedEventBuilder.js.map +1 -1
- package/package.json +1 -1
- package/src/createAggregateRoot.ts +22 -2
- package/src/lock.ts +17 -3
- package/src/redis/redisLock.ts +6 -2
- package/src/tests/aggregateRoot.spec.ts +42 -0
- package/dist/chunk-2fe8jjdc.js +0 -22
- package/dist/chunk-6q8mr1sg.js +0 -13
- package/dist/chunk-6yrb30rx.js +0 -22
- package/dist/chunk-7akf01zj.js.map +0 -10
- package/dist/chunk-ak901ckt.js +0 -67
- package/dist/chunk-dgzw1nj9.js.map +0 -10
- package/dist/chunk-jd4q8fcf.js +0 -11
- package/dist/chunk-ty9bhdvx.js.map +0 -10
package/dist/surreal/index.js
CHANGED
|
@@ -1,36 +1,36 @@
|
|
|
1
|
+
import"../chunk-06anxtk6.js";
|
|
1
2
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
ConcurrencyError2
|
|
4
|
+
} from "../chunk-jw9e0fr0.js";
|
|
5
|
+
import"../chunk-nrhw3kde.js";
|
|
6
|
+
import"../chunk-hmvwn02w.js";
|
|
6
7
|
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
} from "../chunk-
|
|
8
|
+
superjson2,
|
|
9
|
+
extendTypes2
|
|
10
|
+
} from "../chunk-fpjnk143.js";
|
|
11
|
+
import"../chunk-d6jqbrq2.js";
|
|
12
|
+
import"../chunk-tkwe4r0y.js";
|
|
13
|
+
import"../chunk-fxb9fbvz.js";
|
|
14
|
+
import"../chunk-2wqpktzp.js";
|
|
15
|
+
import"../chunk-j4mwjx07.js";
|
|
16
|
+
import"../chunk-9qtjz725.js";
|
|
17
|
+
import"../chunk-zkz6ew8c.js";
|
|
10
18
|
import {
|
|
11
|
-
|
|
12
|
-
} from "../chunk-
|
|
19
|
+
createEventStore2
|
|
20
|
+
} from "../chunk-pcggjrxr.js";
|
|
21
|
+
import"../chunk-c7sytwpp.js";
|
|
13
22
|
import {
|
|
14
|
-
|
|
15
|
-
} from "../chunk-
|
|
16
|
-
import"../chunk-ty9bhdvx.js";
|
|
17
|
-
import"../chunk-z388cd25.js";
|
|
18
|
-
import"../chunk-24xjphpk.js";
|
|
19
|
-
import"../chunk-tfy01fah.js";
|
|
20
|
-
import"../chunk-zznvzvnv.js";
|
|
21
|
-
import"../chunk-8qn1nqnh.js";
|
|
22
|
-
import"../chunk-kqh3q3fj.js";
|
|
23
|
-
import"../chunk-6yrb30rx.js";
|
|
23
|
+
createAggregateRoot2
|
|
24
|
+
} from "../chunk-f95c3da4.js";
|
|
24
25
|
import {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
} from "../chunk-
|
|
28
|
-
import"../chunk-2fe8jjdc.js";
|
|
29
|
-
import"../chunk-3251p253.js";
|
|
30
|
-
import"../chunk-pc1q4se9.js";
|
|
26
|
+
isStreamId2,
|
|
27
|
+
isStreamEvents2
|
|
28
|
+
} from "../chunk-6dn6wxg7.js";
|
|
31
29
|
import {
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
TABLES2,
|
|
31
|
+
SCHEMA_STATEMENTS2,
|
|
32
|
+
initSchema2
|
|
33
|
+
} from "../chunk-mbxxvskx.js";
|
|
34
34
|
|
|
35
35
|
// src/surreal/index.ts
|
|
36
36
|
import { RecordId } from "surrealdb";
|
|
@@ -76,8 +76,8 @@ function toOutputEvent(row) {
|
|
|
76
76
|
position: Number(event.position),
|
|
77
77
|
streamVersion: Number(event.streamVersion),
|
|
78
78
|
createdAt: toDate(event.createdAt),
|
|
79
|
-
payload:
|
|
80
|
-
metadata:
|
|
79
|
+
payload: superjson2.parse(event.payload),
|
|
80
|
+
metadata: superjson2.deserialize(event.metadata)
|
|
81
81
|
};
|
|
82
82
|
}
|
|
83
83
|
function conflictBackoff(attempt) {
|
|
@@ -86,11 +86,11 @@ function conflictBackoff(attempt) {
|
|
|
86
86
|
}
|
|
87
87
|
var APPEND_QUERY = `
|
|
88
88
|
BEGIN;
|
|
89
|
-
LET $head = array::max(SELECT VALUE streamVersion FROM ${
|
|
89
|
+
LET $head = array::max(SELECT VALUE streamVersion FROM ${TABLES2.events} WHERE streamId = $streamId AND streamType = $streamType) ?? 0;
|
|
90
90
|
IF $head != $expectedVersion { THROW "${CONCURRENCY_MARKER}" + <string>$head; };
|
|
91
|
-
LET $next = (UPSERT ONLY ${
|
|
91
|
+
LET $next = (UPSERT ONLY ${TABLES2.counters}:${TABLES2.events} SET value += $count RETURN VALUE value);
|
|
92
92
|
LET $base = $next - $count;
|
|
93
|
-
INSERT INTO ${
|
|
93
|
+
INSERT INTO ${TABLES2.events} $events.map(|$event, $index| $event + { position: $base + $index + 1 });
|
|
94
94
|
COMMIT;
|
|
95
95
|
`;
|
|
96
96
|
var CHECKPOINT_UPSERT_QUERY = `
|
|
@@ -112,7 +112,7 @@ function createSurrealStorage(params) {
|
|
|
112
112
|
if (params.initSchema === false) {
|
|
113
113
|
return Promise.resolve();
|
|
114
114
|
}
|
|
115
|
-
schemaReady ??=
|
|
115
|
+
schemaReady ??= initSchema2(db());
|
|
116
116
|
return schemaReady;
|
|
117
117
|
};
|
|
118
118
|
async function runWithResponses(query, bindings) {
|
|
@@ -134,9 +134,9 @@ function createSurrealStorage(params) {
|
|
|
134
134
|
const bindings = {};
|
|
135
135
|
if (select) {
|
|
136
136
|
const selects = Array.isArray(select) ? select : [select];
|
|
137
|
-
const streamTypes = selects.map((
|
|
138
|
-
const streamIds = selects.map((
|
|
139
|
-
const eventTypes = selects.flatMap((
|
|
137
|
+
const streamTypes = selects.map((select) => select.stream);
|
|
138
|
+
const streamIds = selects.map((select) => isStreamId2(select) ? select.id : null).filter(Boolean);
|
|
139
|
+
const eventTypes = selects.flatMap((select) => isStreamEvents2(select) ? select.events : []);
|
|
140
140
|
conditions.push("streamType IN $streamTypes");
|
|
141
141
|
bindings.streamTypes = streamTypes;
|
|
142
142
|
if (streamIds.length > 0) {
|
|
@@ -153,7 +153,7 @@ function createSurrealStorage(params) {
|
|
|
153
153
|
lastPosition = range.from - 1;
|
|
154
154
|
}
|
|
155
155
|
const chunkSize = 50;
|
|
156
|
-
const query = `SELECT * FROM ${
|
|
156
|
+
const query = `SELECT * FROM ${TABLES2.events} WHERE ${conditions.join(" AND ")} ORDER BY position ASC LIMIT ${chunkSize};`;
|
|
157
157
|
while (true) {
|
|
158
158
|
const [resolvedEvents] = await db().query(query, { ...bindings, lastPosition }).collect();
|
|
159
159
|
if (resolvedEvents.length === 0) {
|
|
@@ -176,8 +176,8 @@ function createSurrealStorage(params) {
|
|
|
176
176
|
streamType: streamId.stream,
|
|
177
177
|
streamVersion: expectedVersion + 1 + index,
|
|
178
178
|
type: event.type,
|
|
179
|
-
payload:
|
|
180
|
-
metadata:
|
|
179
|
+
payload: superjson2.stringify(event.payload),
|
|
180
|
+
metadata: superjson2.serialize(event.metadata),
|
|
181
181
|
causationId: event.causationId ?? undefined,
|
|
182
182
|
actorId: event.actorId ?? undefined,
|
|
183
183
|
correlationId: event.correlationId ?? undefined,
|
|
@@ -200,12 +200,12 @@ function createSurrealStorage(params) {
|
|
|
200
200
|
const concurrency = errors.find((error) => isThrownError(error) && error.message.includes(CONCURRENCY_MARKER));
|
|
201
201
|
if (concurrency) {
|
|
202
202
|
const currentVersion = Number(new RegExp(`${CONCURRENCY_MARKER}(\\d+)`).exec(concurrency.message)[1]);
|
|
203
|
-
throw new
|
|
203
|
+
throw new ConcurrencyError2(streamId, expectedVersion, currentVersion);
|
|
204
204
|
}
|
|
205
205
|
if (errors.some(isUniqueIndexViolation)) {
|
|
206
|
-
const [version] = await db().query(`RETURN array::max(SELECT VALUE streamVersion FROM ${
|
|
206
|
+
const [version] = await db().query(`RETURN array::max(SELECT VALUE streamVersion FROM ${TABLES2.events} WHERE streamId = $streamId AND streamType = $streamType) ?? 0;`, { streamId: streamId.id, streamType: streamId.stream }).collect();
|
|
207
207
|
const currentVersion = Number(version ?? 0);
|
|
208
|
-
throw new
|
|
208
|
+
throw new ConcurrencyError2(streamId, expectedVersion, currentVersion);
|
|
209
209
|
}
|
|
210
210
|
if (errors.some(isTransactionConflict) && attempt < CONFLICT_RETRIES) {
|
|
211
211
|
await conflictBackoff(attempt);
|
|
@@ -217,11 +217,11 @@ function createSurrealStorage(params) {
|
|
|
217
217
|
checkpoint: {
|
|
218
218
|
async upsert(checkpoint, expectedVersion) {
|
|
219
219
|
await ready();
|
|
220
|
-
const rid = new RecordId(
|
|
220
|
+
const rid = new RecordId(TABLES2.checkpoints, [
|
|
221
221
|
checkpoint.type,
|
|
222
222
|
checkpoint.name
|
|
223
223
|
]);
|
|
224
|
-
const metadata =
|
|
224
|
+
const metadata = superjson2.stringify(checkpoint.metadata);
|
|
225
225
|
const changes = {
|
|
226
226
|
lastEventPosition: checkpoint.lastEventPosition,
|
|
227
227
|
metadata,
|
|
@@ -254,7 +254,7 @@ function createSurrealStorage(params) {
|
|
|
254
254
|
},
|
|
255
255
|
async get(type, name) {
|
|
256
256
|
await ready();
|
|
257
|
-
const rid = new RecordId(
|
|
257
|
+
const rid = new RecordId(TABLES2.checkpoints, [type, name]);
|
|
258
258
|
const [checkpoint] = await db().query(`SELECT * OMIT id FROM ONLY $rid;`, { rid }).collect();
|
|
259
259
|
if (!checkpoint) {
|
|
260
260
|
return null;
|
|
@@ -264,32 +264,32 @@ function createSurrealStorage(params) {
|
|
|
264
264
|
name: checkpoint.name,
|
|
265
265
|
lastEventPosition: Number(checkpoint.lastEventPosition),
|
|
266
266
|
version: Number(checkpoint.version),
|
|
267
|
-
metadata:
|
|
267
|
+
metadata: superjson2.parse(checkpoint.metadata)
|
|
268
268
|
};
|
|
269
269
|
},
|
|
270
270
|
async delete(type, name) {
|
|
271
271
|
await ready();
|
|
272
|
-
const rid = new RecordId(
|
|
272
|
+
const rid = new RecordId(TABLES2.checkpoints, [type, name]);
|
|
273
273
|
await db().query(`DELETE $rid;`, { rid }).collect();
|
|
274
274
|
}
|
|
275
275
|
},
|
|
276
276
|
projectionSnapshot: {
|
|
277
277
|
async put(snapshot) {
|
|
278
278
|
await ready();
|
|
279
|
-
await db().query(`CREATE ${
|
|
279
|
+
await db().query(`CREATE ${TABLES2.projectionSnapshots} CONTENT $content;`, {
|
|
280
280
|
content: {
|
|
281
281
|
projectionId: snapshot.projectionId,
|
|
282
282
|
projectionType: snapshot.projectionType,
|
|
283
283
|
lastEventPosition: snapshot.lastEventPosition,
|
|
284
284
|
schemaVersion: snapshot.schemaVersion,
|
|
285
|
-
state:
|
|
286
|
-
metadata:
|
|
285
|
+
state: superjson2.stringify(snapshot.state),
|
|
286
|
+
metadata: superjson2.stringify(snapshot.metadata)
|
|
287
287
|
}
|
|
288
288
|
}).collect();
|
|
289
289
|
},
|
|
290
290
|
async get(select) {
|
|
291
291
|
await ready();
|
|
292
|
-
const [[snapshot]] = await db().query(`SELECT * OMIT id FROM ${
|
|
292
|
+
const [[snapshot]] = await db().query(`SELECT * OMIT id FROM ${TABLES2.projectionSnapshots} WHERE projectionId = $id AND projectionType = $projection ORDER BY lastEventPosition DESC LIMIT 1;`, { id: select.id, projection: select.projection }).collect();
|
|
293
293
|
if (!snapshot) {
|
|
294
294
|
return null;
|
|
295
295
|
}
|
|
@@ -298,8 +298,8 @@ function createSurrealStorage(params) {
|
|
|
298
298
|
lastEventPosition: Number(snapshot.lastEventPosition),
|
|
299
299
|
schemaVersion: Number(snapshot.schemaVersion),
|
|
300
300
|
createdAt: toDate(snapshot.createdAt),
|
|
301
|
-
state:
|
|
302
|
-
metadata:
|
|
301
|
+
state: superjson2.parse(snapshot.state),
|
|
302
|
+
metadata: superjson2.parse(snapshot.metadata)
|
|
303
303
|
};
|
|
304
304
|
},
|
|
305
305
|
async delete(target, fromPosition) {
|
|
@@ -316,13 +316,13 @@ function createSurrealStorage(params) {
|
|
|
316
316
|
conditions.push("lastEventPosition > $fromPosition");
|
|
317
317
|
bindings.fromPosition = fromPosition;
|
|
318
318
|
}
|
|
319
|
-
await db().query(`DELETE ${
|
|
319
|
+
await db().query(`DELETE ${TABLES2.projectionSnapshots} WHERE ${conditions.join(" AND ")};`, bindings).collect();
|
|
320
320
|
},
|
|
321
321
|
async incrementAppliedCount(select) {
|
|
322
322
|
await ready();
|
|
323
323
|
for (let attempt = 0;; attempt++) {
|
|
324
324
|
try {
|
|
325
|
-
const [appliedEvents] = await db().query(`UPSERT ONLY ${
|
|
325
|
+
const [appliedEvents] = await db().query(`UPSERT ONLY ${TABLES2.projectionAppliedEvents}:[$projection, $id] SET appliedEvents += 1 RETURN VALUE appliedEvents;`, { projection: select.projection, id: select.id }).collect();
|
|
326
326
|
return Number(appliedEvents);
|
|
327
327
|
} catch (error) {
|
|
328
328
|
if (isTransactionConflict(error) && attempt < CONFLICT_RETRIES) {
|
|
@@ -337,21 +337,21 @@ function createSurrealStorage(params) {
|
|
|
337
337
|
aggregateRootSnapshot: {
|
|
338
338
|
async put(snapshot) {
|
|
339
339
|
await ready();
|
|
340
|
-
await db().query(`CREATE ${
|
|
340
|
+
await db().query(`CREATE ${TABLES2.aggregateRootSnapshots} CONTENT $content;`, {
|
|
341
341
|
content: {
|
|
342
342
|
streamId: snapshot.streamId,
|
|
343
343
|
streamType: snapshot.streamType,
|
|
344
344
|
streamVersion: snapshot.streamVersion,
|
|
345
345
|
lastEventPosition: snapshot.lastEventPosition,
|
|
346
346
|
schemaVersion: snapshot.schemaVersion,
|
|
347
|
-
state:
|
|
348
|
-
metadata:
|
|
347
|
+
state: superjson2.stringify(snapshot.state),
|
|
348
|
+
metadata: superjson2.stringify(snapshot.metadata)
|
|
349
349
|
}
|
|
350
350
|
}).collect();
|
|
351
351
|
},
|
|
352
352
|
async get(select) {
|
|
353
353
|
await ready();
|
|
354
|
-
const [[snapshot]] = await db().query(`SELECT * OMIT id FROM ${
|
|
354
|
+
const [[snapshot]] = await db().query(`SELECT * OMIT id FROM ${TABLES2.aggregateRootSnapshots} WHERE streamId = $id AND streamType = $stream ORDER BY streamVersion DESC LIMIT 1;`, { id: select.id, stream: select.stream }).collect();
|
|
355
355
|
if (!snapshot) {
|
|
356
356
|
return null;
|
|
357
357
|
}
|
|
@@ -361,13 +361,13 @@ function createSurrealStorage(params) {
|
|
|
361
361
|
lastEventPosition: Number(snapshot.lastEventPosition),
|
|
362
362
|
schemaVersion: Number(snapshot.schemaVersion),
|
|
363
363
|
createdAt: toDate(snapshot.createdAt),
|
|
364
|
-
state:
|
|
365
|
-
metadata:
|
|
364
|
+
state: superjson2.parse(snapshot.state),
|
|
365
|
+
metadata: superjson2.parse(snapshot.metadata)
|
|
366
366
|
};
|
|
367
367
|
},
|
|
368
368
|
async delete(target, fromStreamVersion) {
|
|
369
369
|
await ready();
|
|
370
|
-
await db().query(`DELETE ${
|
|
370
|
+
await db().query(`DELETE ${TABLES2.aggregateRootSnapshots} WHERE streamId = $id AND streamType = $stream AND streamVersion > $fromStreamVersion;`, {
|
|
371
371
|
id: target.id,
|
|
372
372
|
stream: target.stream,
|
|
373
373
|
fromStreamVersion
|
|
@@ -376,7 +376,7 @@ function createSurrealStorage(params) {
|
|
|
376
376
|
}
|
|
377
377
|
};
|
|
378
378
|
}
|
|
379
|
-
function
|
|
379
|
+
function createEventStore({
|
|
380
380
|
database,
|
|
381
381
|
aggregateRoots,
|
|
382
382
|
postProcessEvent,
|
|
@@ -384,15 +384,15 @@ function createEventStore2({
|
|
|
384
384
|
onProcessManagerRefresh,
|
|
385
385
|
onEventsAppended,
|
|
386
386
|
autoInit,
|
|
387
|
-
initSchema
|
|
387
|
+
initSchema,
|
|
388
388
|
lock
|
|
389
389
|
}) {
|
|
390
390
|
const storage = createSurrealStorage({
|
|
391
391
|
database,
|
|
392
|
-
initSchema
|
|
392
|
+
initSchema,
|
|
393
393
|
onEventsAppended
|
|
394
394
|
});
|
|
395
|
-
return
|
|
395
|
+
return createEventStore2({
|
|
396
396
|
aggregateRoots,
|
|
397
397
|
postProcessEvent,
|
|
398
398
|
onProjectionReplay,
|
|
@@ -403,13 +403,13 @@ function createEventStore2({
|
|
|
403
403
|
});
|
|
404
404
|
}
|
|
405
405
|
export {
|
|
406
|
-
|
|
407
|
-
|
|
406
|
+
SCHEMA_STATEMENTS2 as SCHEMA_STATEMENTS,
|
|
407
|
+
TABLES2 as TABLES,
|
|
408
|
+
createAggregateRoot2 as createAggregateRoot,
|
|
409
|
+
createEventStore,
|
|
408
410
|
createSurrealStorage,
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
TABLES,
|
|
412
|
-
SCHEMA_STATEMENTS
|
|
411
|
+
extendTypes2 as extendTypes,
|
|
412
|
+
initSchema2 as initSchema
|
|
413
413
|
};
|
|
414
414
|
|
|
415
|
-
//# debugId=
|
|
415
|
+
//# debugId=3B0F9FD071AFFB4C64756E2164756E21
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"sourcesContent": [
|
|
5
5
|
"import { RecordId, type Surreal } from 'surrealdb'\n\nimport type {\n AggregateRootSnapshotMethods,\n AnyAggregateRoot,\n} from '../createAggregateRoot.ts'\nimport type { CheckpointMethods } from '../createCheckpointApi.ts'\nimport type { ProjectionSnapshotMethods } from '../createProjection.ts'\nimport {\n ConcurrencyError,\n createEventStore as createBaseEventStore,\n isStreamEvents,\n isStreamId,\n} from '../index.ts'\nimport type {\n EventStore,\n EventStoreParamsWithAggregateRootSnapshots,\n EventsFromRoot,\n LoadEvents,\n OnProgress,\n} from '../createEventStore.ts'\nimport type { LockCreator } from '../lock.ts'\nimport { superjson } from '../superjson.ts'\nimport { TABLES, initSchema as runInitSchema } from './schema.ts'\nimport type {\n BaseInputEvent,\n BaseOutputEvent,\n MaybePromise,\n StreamId,\n} from '../utilityTypes.js'\n\nexport { createAggregateRoot } from '../index.ts'\nexport { extendTypes } from '../superjson.ts'\nexport { SCHEMA_STATEMENTS, TABLES, initSchema } from './schema.ts'\n\nexport type OnEventsAppended = (events: BaseOutputEvent[]) => MaybePromise<void>\n\ninterface SurrealEventStoreParams<Root extends AnyAggregateRoot> {\n database: Surreal | (() => Surreal)\n aggregateRoots: Root[]\n autoInit?: boolean\n initSchema?: boolean\n lock?: LockCreator\n postProcessEvent?: EventStoreParamsWithAggregateRootSnapshots<Root>['postProcessEvent']\n onProjectionReplay?: OnProgress\n onProcessManagerRefresh?: OnProgress\n onEventsAppended?: OnEventsAppended\n}\n\nconst CONFLICT_RETRIES = 10\nconst CONCURRENCY_MARKER = 'es_concurrency:'\nconst CHECKPOINT_CONFLICT_MARKER = 'es_checkpoint_conflict'\n\ntype QueryResponse =\n | { success: true; result: unknown }\n | { success: false; error: Error & { kind?: string } }\n\ntype ServerErrorLike = Error & {\n kind?: string\n isTransactionConflict?: boolean\n}\n\nfunction isThrownError(error: unknown): boolean {\n return (\n typeof error === 'object' &&\n error !== null &&\n (error as ServerErrorLike).kind === 'Thrown'\n )\n}\n\nfunction isAlreadyExistsError(error: unknown): boolean {\n return (\n typeof error === 'object' &&\n error !== null &&\n (error as ServerErrorLike).kind === 'AlreadyExists'\n )\n}\n\nfunction isUniqueIndexViolation(error: unknown): boolean {\n return (\n error instanceof Error && /index .* already contains/i.test(error.message)\n )\n}\n\n// Snapshot-isolation conflicts are safe to retry. SurrealDB >= 3.1 reports\n// them with a structured `TransactionConflict` detail; older servers only\n// expose the human-readable message.\nfunction isTransactionConflict(error: unknown): error is ServerErrorLike {\n if (typeof error !== 'object' || error === null) {\n return false\n }\n const serverError = error as ServerErrorLike\n if (serverError.isTransactionConflict) {\n return true\n }\n return /read or write conflict|transaction can be retried/i.test(\n serverError.message ?? '',\n )\n}\n\n// Statements after a failed one only report generic \"not executed\" errors —\n// surface the statement error that actually caused the transaction to fail.\nfunction primaryError(errors: ServerErrorLike[]): ServerErrorLike {\n return (\n errors.find((error) => !/was not executed/i.test(error.message)) ??\n errors[0]\n )\n}\n\nfunction toDate(value: unknown): Date {\n if (value instanceof Date) {\n return value\n }\n const dateTime = value as { toDate?: () => Date }\n if (typeof dateTime?.toDate === 'function') {\n return dateTime.toDate()\n }\n return new Date(String(value))\n}\n\nfunction toOutputEvent(row: any): BaseOutputEvent {\n const { id: _id, ...event } = row\n return {\n ...event,\n position: Number(event.position),\n streamVersion: Number(event.streamVersion),\n createdAt: toDate(event.createdAt),\n payload: superjson.parse(event.payload),\n metadata: superjson.deserialize(event.metadata),\n }\n}\n\n// Jittered exponential backoff so concurrent writers racing on the position\n// counter do not retry in lockstep.\nfunction conflictBackoff(attempt: number) {\n const ms = Math.min(200, 5 * 2 ** attempt) * (0.5 + Math.random())\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\n// The head version is computed with array::max instead of\n// ORDER BY ... DESC LIMIT 1: inside a transaction the index scan serves that\n// query in ascending order with the limit pushed down, returning the lowest\n// version instead of the highest.\nconst APPEND_QUERY = `\nBEGIN;\nLET $head = array::max(SELECT VALUE streamVersion FROM ${TABLES.events} WHERE streamId = $streamId AND streamType = $streamType) ?? 0;\nIF $head != $expectedVersion { THROW \"${CONCURRENCY_MARKER}\" + <string>$head; };\nLET $next = (UPSERT ONLY ${TABLES.counters}:${TABLES.events} SET value += $count RETURN VALUE value);\nLET $base = $next - $count;\nINSERT INTO ${TABLES.events} $events.map(|$event, $index| $event + { position: $base + $index + 1 });\nCOMMIT;\n`\n\nconst CHECKPOINT_UPSERT_QUERY = `\nBEGIN;\nLET $current = (SELECT VALUE version FROM ONLY $rid);\nIF $current = NONE {\n CREATE $rid CONTENT $content;\n} ELSE IF $insertOnly = false AND $current = $expectedVersion {\n UPDATE $rid MERGE $changes;\n} ELSE {\n THROW \"${CHECKPOINT_CONFLICT_MARKER}\";\n};\nCOMMIT;\n`\n\nexport function createSurrealStorage(params: {\n database: Surreal | (() => Surreal)\n initSchema?: boolean\n onEventsAppended?: OnEventsAppended\n}): {\n loadEvents: LoadEvents\n appendEvents: (\n streamId: StreamId,\n events: BaseInputEvent[],\n expectedVersion: number,\n ) => Promise<BaseOutputEvent[]>\n checkpoint: CheckpointMethods\n projectionSnapshot: ProjectionSnapshotMethods\n aggregateRootSnapshot: AggregateRootSnapshotMethods\n} {\n const db = () =>\n typeof params.database === 'function' ? params.database() : params.database\n\n let schemaReady: Promise<void> | undefined\n const ready = () => {\n if (params.initSchema === false) {\n return Promise.resolve()\n }\n schemaReady ??= runInitSchema(db())\n return schemaReady\n }\n\n // Statement failures come back as per-statement error responses, but\n // transaction conflicts reject the query promise itself — normalize both\n // into the errors array so the retry loops handle them uniformly.\n async function runWithResponses(\n query: string,\n bindings: Record<string, unknown>,\n ): Promise<{ responses: QueryResponse[]; errors: ServerErrorLike[] }> {\n try {\n const responses = (await db()\n .query(query, bindings)\n .responses()) as QueryResponse[]\n const errors = responses\n .filter((response) => !response.success)\n .map((response) => (response as { error: ServerErrorLike }).error)\n return { responses, errors }\n } catch (error) {\n if (isTransactionConflict(error)) {\n return { responses: [], errors: [error] }\n }\n throw error\n }\n }\n\n return {\n async *loadEvents(select, range) {\n await ready()\n const conditions = ['position > $lastPosition']\n const bindings: Record<string, unknown> = {}\n\n if (select) {\n const selects = Array.isArray(select) ? select : [select]\n const streamTypes = selects.map((select) => select.stream)\n const streamIds = selects\n .map((select) => (isStreamId(select) ? select.id : null))\n .filter(Boolean) as string[]\n const eventTypes = selects.flatMap((select) =>\n isStreamEvents(select) ? select.events : [],\n )\n conditions.push('streamType IN $streamTypes')\n bindings.streamTypes = streamTypes\n\n if (streamIds.length > 0) {\n conditions.push('streamId IN $streamIds')\n bindings.streamIds = streamIds\n }\n\n if (eventTypes.length > 0) {\n conditions.push('type IN $eventTypes')\n bindings.eventTypes = eventTypes\n }\n }\n let lastPosition = 0\n\n if (range?.from) {\n lastPosition = range.from - 1\n }\n\n // range.to is applied client-side: combining both bounds on the\n // uniquely indexed position field trips a SurrealDB 3.0 planner bug\n // where the exclusive lower bound is ignored.\n const chunkSize = 50\n const query = `SELECT * FROM ${TABLES.events} WHERE ${conditions.join(' AND ')} ORDER BY position ASC LIMIT ${chunkSize};`\n\n while (true) {\n const [resolvedEvents] = (await db()\n .query(query, { ...bindings, lastPosition })\n .collect()) as [any[]]\n\n if (resolvedEvents.length === 0) {\n break\n }\n\n for (const resolvedEvent of resolvedEvents) {\n const position = Number(resolvedEvent.position)\n if (range?.to && position > range.to) {\n return\n }\n yield toOutputEvent(resolvedEvent)\n lastPosition = position\n }\n }\n },\n\n async appendEvents(streamId, newEvents, expectedVersion) {\n await ready()\n const mappedEvents = newEvents.map((event, index) => ({\n streamId: streamId.id,\n streamType: streamId.stream,\n streamVersion: expectedVersion + 1 + index,\n type: event.type,\n payload: superjson.stringify(event.payload),\n metadata: superjson.serialize(event.metadata),\n causationId: event.causationId ?? undefined,\n actorId: event.actorId ?? undefined,\n correlationId: event.correlationId ?? undefined,\n schemaVersion: event.schemaVersion,\n }))\n\n for (let attempt = 0; ; attempt++) {\n const { responses, errors } = await runWithResponses(APPEND_QUERY, {\n streamId: streamId.id,\n streamType: streamId.stream,\n expectedVersion,\n count: mappedEvents.length,\n events: mappedEvents,\n })\n\n if (errors.length === 0) {\n const persistedEvents = responses\n .map((response) => (response.success ? response.result : undefined))\n .find(Array.isArray) as any[]\n\n const resolvedEvents = persistedEvents\n .map(toOutputEvent)\n .toSorted((eventA, eventB) => eventA.position - eventB.position)\n\n params.onEventsAppended?.(resolvedEvents)\n\n return resolvedEvents\n }\n\n const concurrency = errors.find(\n (error) =>\n isThrownError(error) && error.message.includes(CONCURRENCY_MARKER),\n )\n if (concurrency) {\n const currentVersion = Number(\n new RegExp(`${CONCURRENCY_MARKER}(\\\\d+)`).exec(\n concurrency.message,\n )![1],\n )\n throw new ConcurrencyError(streamId, expectedVersion, currentVersion)\n }\n\n if (errors.some(isUniqueIndexViolation)) {\n const [version] = (await db()\n .query(\n `RETURN array::max(SELECT VALUE streamVersion FROM ${TABLES.events} WHERE streamId = $streamId AND streamType = $streamType) ?? 0;`,\n { streamId: streamId.id, streamType: streamId.stream },\n )\n .collect()) as [number]\n\n const currentVersion = Number(version ?? 0)\n throw new ConcurrencyError(streamId, expectedVersion, currentVersion)\n }\n\n if (errors.some(isTransactionConflict) && attempt < CONFLICT_RETRIES) {\n await conflictBackoff(attempt)\n continue\n }\n\n throw primaryError(errors)\n }\n },\n\n checkpoint: {\n async upsert(checkpoint, expectedVersion) {\n await ready()\n const rid = new RecordId(TABLES.checkpoints, [\n checkpoint.type,\n checkpoint.name,\n ])\n const metadata = superjson.stringify(checkpoint.metadata)\n const changes = {\n lastEventPosition: checkpoint.lastEventPosition,\n metadata,\n version: checkpoint.version,\n }\n\n // Compare-and-swap: create when no checkpoint exists, otherwise only\n // apply when the stored version still matches `expectedVersion`. A\n // `null` expectation means \"insert only\" — an existing record is a\n // conflict.\n for (let attempt = 0; ; attempt++) {\n const { errors } = await runWithResponses(CHECKPOINT_UPSERT_QUERY, {\n rid,\n content: {\n type: checkpoint.type,\n name: checkpoint.name,\n ...changes,\n },\n changes,\n insertOnly: expectedVersion === null,\n expectedVersion: expectedVersion ?? 0,\n })\n\n if (errors.length === 0) {\n return true\n }\n\n if (\n errors.some(\n (error) =>\n isAlreadyExistsError(error) ||\n (isThrownError(error) &&\n error.message.includes(CHECKPOINT_CONFLICT_MARKER)),\n )\n ) {\n return false\n }\n\n if (\n errors.some(isTransactionConflict) &&\n attempt < CONFLICT_RETRIES\n ) {\n await conflictBackoff(attempt)\n continue\n }\n\n throw primaryError(errors)\n }\n },\n async get(type, name) {\n await ready()\n const rid = new RecordId(TABLES.checkpoints, [type, name])\n const [checkpoint] = (await db()\n .query(`SELECT * OMIT id FROM ONLY $rid;`, { rid })\n .collect()) as [any]\n\n if (!checkpoint) {\n return null\n }\n\n return {\n type: checkpoint.type,\n name: checkpoint.name,\n lastEventPosition: Number(checkpoint.lastEventPosition),\n version: Number(checkpoint.version),\n metadata: superjson.parse(checkpoint.metadata),\n }\n },\n async delete(type, name) {\n await ready()\n const rid = new RecordId(TABLES.checkpoints, [type, name])\n await db().query(`DELETE $rid;`, { rid }).collect()\n },\n },\n\n projectionSnapshot: {\n async put(snapshot) {\n await ready()\n await db()\n .query(`CREATE ${TABLES.projectionSnapshots} CONTENT $content;`, {\n content: {\n projectionId: snapshot.projectionId,\n projectionType: snapshot.projectionType,\n lastEventPosition: snapshot.lastEventPosition,\n schemaVersion: snapshot.schemaVersion,\n state: superjson.stringify(snapshot.state),\n metadata: superjson.stringify(snapshot.metadata),\n },\n })\n .collect()\n },\n async get(select) {\n await ready()\n const [[snapshot]] = (await db()\n .query(\n `SELECT * OMIT id FROM ${TABLES.projectionSnapshots} WHERE projectionId = $id AND projectionType = $projection ORDER BY lastEventPosition DESC LIMIT 1;`,\n { id: select.id, projection: select.projection },\n )\n .collect()) as [any[]]\n\n if (!snapshot) {\n return null\n }\n\n return {\n ...snapshot,\n lastEventPosition: Number(snapshot.lastEventPosition),\n schemaVersion: Number(snapshot.schemaVersion),\n createdAt: toDate(snapshot.createdAt),\n state: superjson.parse(snapshot.state),\n metadata: superjson.parse(snapshot.metadata),\n }\n },\n async delete(target, fromPosition) {\n await ready()\n const conditions = ['projectionType = $projection']\n const bindings: Record<string, unknown> = {\n projection: target.projection,\n }\n\n if (target.id) {\n conditions.push('projectionId = $id')\n bindings.id = target.id\n }\n\n if (fromPosition) {\n conditions.push('lastEventPosition > $fromPosition')\n bindings.fromPosition = fromPosition\n }\n\n await db()\n .query(\n `DELETE ${TABLES.projectionSnapshots} WHERE ${conditions.join(' AND ')};`,\n bindings,\n )\n .collect()\n },\n async incrementAppliedCount(select) {\n await ready()\n for (let attempt = 0; ; attempt++) {\n try {\n const [appliedEvents] = (await db()\n .query(\n `UPSERT ONLY ${TABLES.projectionAppliedEvents}:[$projection, $id] SET appliedEvents += 1 RETURN VALUE appliedEvents;`,\n { projection: select.projection, id: select.id },\n )\n .collect()) as [number]\n\n return Number(appliedEvents)\n } catch (error) {\n if (isTransactionConflict(error) && attempt < CONFLICT_RETRIES) {\n await conflictBackoff(attempt)\n continue\n }\n throw error\n }\n }\n },\n },\n\n aggregateRootSnapshot: {\n async put(snapshot) {\n await ready()\n await db()\n .query(`CREATE ${TABLES.aggregateRootSnapshots} CONTENT $content;`, {\n content: {\n streamId: snapshot.streamId,\n streamType: snapshot.streamType,\n streamVersion: snapshot.streamVersion,\n lastEventPosition: snapshot.lastEventPosition,\n schemaVersion: snapshot.schemaVersion,\n state: superjson.stringify(snapshot.state),\n metadata: superjson.stringify(snapshot.metadata),\n },\n })\n .collect()\n },\n async get(select) {\n await ready()\n const [[snapshot]] = (await db()\n .query(\n `SELECT * OMIT id FROM ${TABLES.aggregateRootSnapshots} WHERE streamId = $id AND streamType = $stream ORDER BY streamVersion DESC LIMIT 1;`,\n { id: select.id, stream: select.stream },\n )\n .collect()) as [any[]]\n\n if (!snapshot) {\n return null\n }\n\n return {\n ...snapshot,\n streamVersion: Number(snapshot.streamVersion),\n lastEventPosition: Number(snapshot.lastEventPosition),\n schemaVersion: Number(snapshot.schemaVersion),\n createdAt: toDate(snapshot.createdAt),\n state: superjson.parse(snapshot.state),\n metadata: superjson.parse(snapshot.metadata),\n }\n },\n async delete(target, fromStreamVersion) {\n await ready()\n await db()\n .query(\n `DELETE ${TABLES.aggregateRootSnapshots} WHERE streamId = $id AND streamType = $stream AND streamVersion > $fromStreamVersion;`,\n {\n id: target.id,\n stream: target.stream,\n fromStreamVersion,\n },\n )\n .collect()\n },\n },\n }\n}\n\nexport function createEventStore<const Root extends AnyAggregateRoot>({\n database,\n aggregateRoots,\n postProcessEvent,\n onProjectionReplay,\n onProcessManagerRefresh,\n onEventsAppended,\n autoInit,\n initSchema,\n lock,\n}: SurrealEventStoreParams<Root>): EventStore<\n EventsFromRoot<Root>,\n Root,\n true\n> {\n const storage = createSurrealStorage({\n database,\n initSchema,\n onEventsAppended,\n })\n\n return createBaseEventStore({\n aggregateRoots,\n postProcessEvent,\n onProjectionReplay,\n onProcessManagerRefresh,\n autoInit,\n lock,\n ...storage,\n }) as any\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAiDA,IAAM,mBAAmB;AACzB,IAAM,qBAAqB;AAC3B,IAAM,6BAA6B;AAWnC,SAAS,aAAa,CAAC,OAAyB;AAAA,EAC9C,OACE,OAAO,UAAU,YACjB,UAAU,QACT,MAA0B,SAAS;AAAA;AAIxC,SAAS,oBAAoB,CAAC,OAAyB;AAAA,EACrD,OACE,OAAO,UAAU,YACjB,UAAU,QACT,MAA0B,SAAS;AAAA;AAIxC,SAAS,sBAAsB,CAAC,OAAyB;AAAA,EACvD,OACE,iBAAiB,SAAS,6BAA6B,KAAK,MAAM,OAAO;AAAA;AAO7E,SAAS,qBAAqB,CAAC,OAA0C;AAAA,EACvE,IAAI,OAAO,UAAU,YAAY,UAAU,MAAM;AAAA,IAC/C,OAAO;AAAA,EACT;AAAA,EACA,MAAM,cAAc;AAAA,EACpB,IAAI,YAAY,uBAAuB;AAAA,IACrC,OAAO;AAAA,EACT;AAAA,EACA,OAAO,qDAAqD,KAC1D,YAAY,WAAW,EACzB;AAAA;AAKF,SAAS,YAAY,CAAC,QAA4C;AAAA,EAChE,OACE,OAAO,KAAK,CAAC,UAAU,CAAC,oBAAoB,KAAK,MAAM,OAAO,CAAC,KAC/D,OAAO;AAAA;AAIX,SAAS,MAAM,CAAC,OAAsB;AAAA,EACpC,IAAI,iBAAiB,MAAM;AAAA,IACzB,OAAO;AAAA,EACT;AAAA,EACA,MAAM,WAAW;AAAA,EACjB,IAAI,OAAO,UAAU,WAAW,YAAY;AAAA,IAC1C,OAAO,SAAS,OAAO;AAAA,EACzB;AAAA,EACA,OAAO,IAAI,KAAK,OAAO,KAAK,CAAC;AAAA;AAG/B,SAAS,aAAa,CAAC,KAA2B;AAAA,EAChD,QAAQ,IAAI,QAAQ,UAAU;AAAA,EAC9B,OAAO;AAAA,OACF;AAAA,IACH,UAAU,OAAO,MAAM,QAAQ;AAAA,IAC/B,eAAe,OAAO,MAAM,aAAa;AAAA,IACzC,WAAW,OAAO,MAAM,SAAS;AAAA,IACjC,SAAS,
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "3B0F9FD071AFFB4C64756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
package/dist/surreal/schema.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
} from "../chunk-
|
|
2
|
+
TABLES2,
|
|
3
|
+
SCHEMA_STATEMENTS2,
|
|
4
|
+
initSchema2
|
|
5
|
+
} from "../chunk-mbxxvskx.js";
|
|
6
6
|
export {
|
|
7
|
-
|
|
8
|
-
TABLES,
|
|
9
|
-
|
|
7
|
+
SCHEMA_STATEMENTS2 as SCHEMA_STATEMENTS,
|
|
8
|
+
TABLES2 as TABLES,
|
|
9
|
+
initSchema2 as initSchema
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
-
//# debugId=
|
|
12
|
+
//# debugId=DAED674256F2E70964756E2164756E21
|
package/dist/transaction.js
CHANGED
package/dist/utils.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
} from "./chunk-
|
|
2
|
+
normalizeArray2,
|
|
3
|
+
awaitAll2
|
|
4
|
+
} from "./chunk-c7sytwpp.js";
|
|
5
5
|
export {
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
awaitAll2 as awaitAll,
|
|
7
|
+
normalizeArray2 as normalizeArray
|
|
8
8
|
};
|
|
9
9
|
|
|
10
|
-
//# debugId=
|
|
10
|
+
//# debugId=27F4432A2CD67A7364756E2164756E21
|
package/dist/utils.js.map
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
} from "./chunk-
|
|
2
|
+
unwrapEvent2,
|
|
3
|
+
handleEventError2,
|
|
4
|
+
wrappedEventBuilder2
|
|
5
|
+
} from "./chunk-zkz6ew8c.js";
|
|
6
6
|
export {
|
|
7
|
-
|
|
8
|
-
unwrapEvent,
|
|
9
|
-
|
|
7
|
+
handleEventError2 as handleEventError,
|
|
8
|
+
unwrapEvent2 as unwrapEvent,
|
|
9
|
+
wrappedEventBuilder2 as wrappedEventBuilder
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
-
//# debugId=
|
|
12
|
+
//# debugId=13D61F145C1E7AE864756E2164756E21
|
package/package.json
CHANGED
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
InfiniteLoopError,
|
|
18
18
|
ValidationError,
|
|
19
19
|
} from './errors.ts'
|
|
20
|
-
import type
|
|
20
|
+
import { DEFAULT_LOCK_TTL, type LockCreator } from './lock.ts'
|
|
21
21
|
import { isRefreshing } from './refresh.ts'
|
|
22
22
|
import createSnapshotGenerator, {
|
|
23
23
|
type CompleteSnapshotGenerator,
|
|
@@ -530,6 +530,7 @@ export function createAggregateRoot<Name extends string>(type: Name) {
|
|
|
530
530
|
let downstreamSettledPromise = () => Promise.resolve()
|
|
531
531
|
let releaseLock!: () => Promise<void>
|
|
532
532
|
let extendLock!: EventHandlerOptions['extendLock']
|
|
533
|
+
let lockTtl: number | undefined
|
|
533
534
|
|
|
534
535
|
const warnReleaseLock = () => {
|
|
535
536
|
if (releasedAfterChain) {
|
|
@@ -582,8 +583,25 @@ export function createAggregateRoot<Name extends string>(type: Name) {
|
|
|
582
583
|
let commandChain = createLock([type, streamId]).then((lock) => {
|
|
583
584
|
releaseLock = lock.release
|
|
584
585
|
extendLock = lock.extend
|
|
586
|
+
lockTtl = lock.ttl
|
|
585
587
|
return [] as Error | BaseInputEvent[]
|
|
586
588
|
})
|
|
589
|
+
|
|
590
|
+
// A replay is the library's own work and takes as long as the stream is
|
|
591
|
+
// long, so unlike a slow command it must not cost the caller the lock.
|
|
592
|
+
// Extended on a timer while it runs, and never past it: a lock nobody
|
|
593
|
+
// releases still expires.
|
|
594
|
+
const keepLockAlive = async <T>(work: () => Promise<T>) => {
|
|
595
|
+
const timer = setInterval(
|
|
596
|
+
() => void extendLock().catch(() => false),
|
|
597
|
+
(lockTtl ?? DEFAULT_LOCK_TTL) / 4,
|
|
598
|
+
)
|
|
599
|
+
try {
|
|
600
|
+
return await work()
|
|
601
|
+
} finally {
|
|
602
|
+
clearInterval(timer)
|
|
603
|
+
}
|
|
604
|
+
}
|
|
587
605
|
let commandChainTouched = false
|
|
588
606
|
let releasedAfterChain = false
|
|
589
607
|
let transactionDelay: TransactionDelay | undefined
|
|
@@ -769,7 +787,9 @@ export function createAggregateRoot<Name extends string>(type: Name) {
|
|
|
769
787
|
// ensure commands are executed after load is finished
|
|
770
788
|
commandChain = commandChain
|
|
771
789
|
.then(() =>
|
|
772
|
-
|
|
790
|
+
keepLockAlive(() =>
|
|
791
|
+
loadUntil(state, snapshotApi, streamId, undefined, filter),
|
|
792
|
+
),
|
|
773
793
|
)
|
|
774
794
|
.then((loadedVersion) => {
|
|
775
795
|
version = loadedVersion
|
package/src/lock.ts
CHANGED
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
import { Mutex } from 'async-mutex'
|
|
2
2
|
|
|
3
|
-
export
|
|
3
|
+
export const DEFAULT_LOCK_TTL = 5000
|
|
4
|
+
|
|
5
|
+
export type Lock = {
|
|
6
|
+
/** Moves the expiry to `ttl` from now (default: half the lock's TTL). */
|
|
7
|
+
extend(ttl?: number): Promise<boolean>
|
|
8
|
+
release(): Promise<void>
|
|
9
|
+
/**
|
|
10
|
+
* The TTL the lock was taken with. The aggregate root keeps a replay's lock
|
|
11
|
+
* alive at a quarter of it, and assumes {@link DEFAULT_LOCK_TTL} without it.
|
|
12
|
+
*/
|
|
13
|
+
ttl?: number
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export type LockCreator = (key: string | string[]) => Promise<Lock>
|
|
17
|
+
|
|
18
|
+
export default function lock(defaultTtl = DEFAULT_LOCK_TTL): LockCreator {
|
|
4
19
|
const locks = new Map<string, Mutex>()
|
|
5
20
|
return async (key: string | string[]) => {
|
|
6
21
|
const k = Array.isArray(key) ? key.join(':') : key
|
|
@@ -30,6 +45,7 @@ export default function lock(defaultTtl = 5000) {
|
|
|
30
45
|
startTimer(defaultTtl)
|
|
31
46
|
|
|
32
47
|
return {
|
|
48
|
+
ttl: defaultTtl,
|
|
33
49
|
async extend(ttl?: number) {
|
|
34
50
|
if (isReleased) {
|
|
35
51
|
return false
|
|
@@ -54,5 +70,3 @@ export default function lock(defaultTtl = 5000) {
|
|
|
54
70
|
}
|
|
55
71
|
}
|
|
56
72
|
}
|
|
57
|
-
|
|
58
|
-
export type LockCreator = ReturnType<typeof lock>
|
package/src/redis/redisLock.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Redis } from 'ioredis'
|
|
2
2
|
|
|
3
|
-
import type
|
|
3
|
+
import { DEFAULT_LOCK_TTL, type LockCreator } from '../lock.ts'
|
|
4
4
|
|
|
5
5
|
const extendScript = `
|
|
6
6
|
if redis.call("get", KEYS[1]) == ARGV[1] then
|
|
@@ -18,7 +18,10 @@ const deleteScript = `
|
|
|
18
18
|
end
|
|
19
19
|
`
|
|
20
20
|
|
|
21
|
-
export function redisLock(
|
|
21
|
+
export function redisLock(
|
|
22
|
+
client: Redis,
|
|
23
|
+
defaultTtl = DEFAULT_LOCK_TTL,
|
|
24
|
+
): LockCreator {
|
|
22
25
|
return async (rawKey) => {
|
|
23
26
|
const key = Array.isArray(rawKey) ? rawKey.join(':') : rawKey
|
|
24
27
|
const token = crypto.randomUUID()
|
|
@@ -33,6 +36,7 @@ export function redisLock(client: Redis, defaultTtl = 5000): LockCreator {
|
|
|
33
36
|
|
|
34
37
|
let isReleased = false
|
|
35
38
|
return {
|
|
39
|
+
ttl: defaultTtl,
|
|
36
40
|
async extend(ttl) {
|
|
37
41
|
const extended = await client.eval(
|
|
38
42
|
extendScript,
|