@ocoda/event-sourcing-mariadb 3.0.0 → 3.0.2
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/CHANGELOG.md +32 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +303 -273
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
# @ocoda/event-sourcing-mariadb
|
|
2
2
|
|
|
3
|
+
## 3.0.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#544](https://github.com/ocoda/event-sourcing/pull/544) [`94b5f48`](https://github.com/ocoda/event-sourcing/commit/94b5f48415e54e3408f21c35858b431311c04462) Thanks [@drieshooghe](https://github.com/drieshooghe)! - `getLastSnapshots([])` and `getManyLastSnapshotEnvelopes([])` of the MariaDB snapshot store, and so `SnapshotRepository.loadMany([])`, return an empty map instead of failing with an SQL syntax error.
|
|
8
|
+
|
|
9
|
+
- Updated dependencies [[`94b5f48`](https://github.com/ocoda/event-sourcing/commit/94b5f48415e54e3408f21c35858b431311c04462)]:
|
|
10
|
+
- @ocoda/event-sourcing@3.0.2
|
|
11
|
+
|
|
12
|
+
## 3.0.1
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- [#526](https://github.com/ocoda/event-sourcing/pull/526) [`b93acfa`](https://github.com/ocoda/event-sourcing/commit/b93acfaea457a6ee1e7cb2b345bd9f5ca8cb695d) Thanks [@drieshooghe](https://github.com/drieshooghe)! - Harden the MariaDB and MongoDB event and snapshot stores.
|
|
17
|
+
|
|
18
|
+
MariaDB:
|
|
19
|
+
|
|
20
|
+
- Reads no longer hide failures. A missing table, a dropped connection or an unregistered event used to end the stream silently and return a truncated history. The original error is now thrown to the consumer. Applications that relied on reading a not-yet-created pool returning nothing must create it with `ensureCollection()` first.
|
|
21
|
+
- Stopping a read early (`break` or an error in the consumer) now discards the rest of the result set and releases the connection. Before, this could leave the connection stuck and eventually exhaust the pool.
|
|
22
|
+
- A concurrent append that loses the race on the primary key now throws `EventStoreVersionConflictException` / `SnapshotStoreVersionConflictException` instead of `EventStorePersistenceException` / `SnapshotStorePersistenceException`.
|
|
23
|
+
- Table names are quoted with the connector's `escapeId`, so pool names with special characters are handled safely.
|
|
24
|
+
|
|
25
|
+
MongoDB:
|
|
26
|
+
|
|
27
|
+
- Cursors are now closed when a read ends early or fails, instead of staying open on the server until they time out.
|
|
28
|
+
- Appends no longer look up the collection on every write. Collections that are known to exist (created through `ensureCollection()` or found once) are remembered per store instance. Unknown pools are still rejected with the same exception and are checked against the server on every attempt. If you drop a collection while a store instance is running, call `ensureCollection()` again before appending to it: otherwise MongoDB re-creates it on the next write without its unique indexes.
|
|
29
|
+
- A concurrent append that loses the race on the `(streamId, version)` unique index now throws `EventStoreVersionConflictException` / `SnapshotStoreVersionConflictException` instead of `EventStorePersistenceException` / `SnapshotStorePersistenceException`. Events of the losing append that were already inserted are removed again.
|
|
30
|
+
- The batches yielded by the read methods are no longer emptied after the consumer resumes, so consumers can safely keep a reference to a batch.
|
|
31
|
+
|
|
32
|
+
- Updated dependencies [[`c2f0b47`](https://github.com/ocoda/event-sourcing/commit/c2f0b479ad295d0c92b1cf3c522bac23424c8c81)]:
|
|
33
|
+
- @ocoda/event-sourcing@3.0.1
|
|
34
|
+
|
|
3
35
|
## 3.0.0
|
|
4
36
|
|
|
5
37
|
### Patch Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -26,6 +26,10 @@ declare class MariaDBEventStore extends EventStore<MariaDBEventStoreConfig> {
|
|
|
26
26
|
getEnvelope({ streamId }: EventStream, version: number, pool?: IEventPool): Promise<EventEnvelope>;
|
|
27
27
|
getEnvelopes({ streamId }: EventStream, filter?: IEventFilter): AsyncGenerator<EventEnvelope[]>;
|
|
28
28
|
getAllEnvelopes(filter: IAllEventsFilter): AsyncGenerator<EventEnvelope[]>;
|
|
29
|
+
/**
|
|
30
|
+
* Best effort lookup of the latest version of a stream, used to report a conflict.
|
|
31
|
+
*/
|
|
32
|
+
private getLatestVersion;
|
|
29
33
|
}
|
|
30
34
|
|
|
31
35
|
interface MariaDBEventStoreConfig extends EventStoreConfig, PoolConfig {
|
|
@@ -60,6 +64,10 @@ declare class MariaDBSnapshotStore extends SnapshotStore<MariaDBSnapshotStoreCon
|
|
|
60
64
|
getLastEnvelopesForAggregate<A extends AggregateRoot>(aggregate: Type<A>, filter?: ILatestSnapshotFilter): AsyncGenerator<SnapshotEnvelope<A>[]>;
|
|
61
65
|
getManyLastSnapshotEnvelopes<A extends AggregateRoot>(streams: SnapshotStream[], pool?: ISnapshotPool): Promise<Map<SnapshotStream, SnapshotEnvelope<A>>>;
|
|
62
66
|
private getLastStreamEntities;
|
|
67
|
+
/**
|
|
68
|
+
* Best effort lookup of the latest snapshot version of a stream, used to report a conflict.
|
|
69
|
+
*/
|
|
70
|
+
private getLatestVersion;
|
|
63
71
|
}
|
|
64
72
|
|
|
65
73
|
interface MariaDBSnapshotStoreConfig extends SnapshotStoreConfig, PoolConfig {
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
3
3
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
4
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
5
|
var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
|
|
6
|
+
var __typeError = (msg) => {
|
|
7
|
+
throw TypeError(msg);
|
|
8
|
+
};
|
|
6
9
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
7
10
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
8
11
|
var __export = (target, all) => {
|
|
@@ -54,6 +57,34 @@ var __asyncGenerator = (__this, __arguments, generator) => {
|
|
|
54
57
|
}, method = (k) => it[k] = (x) => new Promise((yes, no) => resume(k, x, yes, no)), it = {};
|
|
55
58
|
return generator = generator.apply(__this, __arguments), it[__knownSymbol("asyncIterator")] = () => it, method("next"), method("throw"), method("return"), it;
|
|
56
59
|
};
|
|
60
|
+
var __yieldStar = (value) => {
|
|
61
|
+
var obj = value[__knownSymbol("asyncIterator")], isAwait = false, method, it = {};
|
|
62
|
+
if (obj == null) {
|
|
63
|
+
obj = value[__knownSymbol("iterator")]();
|
|
64
|
+
method = (k) => it[k] = (x) => obj[k](x);
|
|
65
|
+
} else {
|
|
66
|
+
obj = obj.call(value);
|
|
67
|
+
method = (k) => it[k] = (v) => {
|
|
68
|
+
if (isAwait) {
|
|
69
|
+
isAwait = false;
|
|
70
|
+
if (k === "throw") throw v;
|
|
71
|
+
return v;
|
|
72
|
+
}
|
|
73
|
+
isAwait = true;
|
|
74
|
+
return {
|
|
75
|
+
done: false,
|
|
76
|
+
value: new __await(new Promise((resolve) => {
|
|
77
|
+
var x = obj[k](v);
|
|
78
|
+
if (!(x instanceof Object)) __typeError("Object expected");
|
|
79
|
+
resolve(x);
|
|
80
|
+
}), 1)
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
return it[__knownSymbol("iterator")] = () => it, method("next"), "throw" in obj ? method("throw") : it.throw = (x) => {
|
|
85
|
+
throw x;
|
|
86
|
+
}, "return" in obj && method("return"), it;
|
|
87
|
+
};
|
|
57
88
|
var __forAwait = (obj, it, method) => (it = obj[__knownSymbol("asyncIterator")]) ? it.call(obj) : (obj = obj[__knownSymbol("iterator")](), it = {}, method = (key, fn) => (fn = obj[key]) && (it[key] = (arg) => new Promise((yes, no, done) => (arg = fn.call(obj, arg), done = arg.done, Promise.resolve(arg.value).then((value) => yes({ value, done }), no)))), method("next"), method("return"), it);
|
|
58
89
|
|
|
59
90
|
// lib/index.ts
|
|
@@ -67,6 +98,34 @@ module.exports = __toCommonJS(index_exports);
|
|
|
67
98
|
// lib/mariadb.event-store.ts
|
|
68
99
|
var import_event_sourcing = require("@ocoda/event-sourcing");
|
|
69
100
|
var import_mariadb = require("mariadb");
|
|
101
|
+
|
|
102
|
+
// lib/mariadb.utils.ts
|
|
103
|
+
var ER_DUP_ENTRY = 1062;
|
|
104
|
+
var isDuplicateEntryError = /* @__PURE__ */ __name((error) => {
|
|
105
|
+
const { errno, code } = error != null ? error : {};
|
|
106
|
+
return errno === ER_DUP_ENTRY || code === "ER_DUP_ENTRY";
|
|
107
|
+
}, "isDuplicateEntryError");
|
|
108
|
+
function streamRows(pool, sql, params) {
|
|
109
|
+
return __asyncGenerator(this, null, function* () {
|
|
110
|
+
var _a;
|
|
111
|
+
const connection = yield new __await(pool.getConnection());
|
|
112
|
+
let stream;
|
|
113
|
+
try {
|
|
114
|
+
stream = connection.queryStream(sql, params);
|
|
115
|
+
stream.on("error", () => void 0);
|
|
116
|
+
yield* __yieldStar(stream);
|
|
117
|
+
} finally {
|
|
118
|
+
if (stream) {
|
|
119
|
+
(_a = stream.close) == null ? void 0 : _a.call(stream);
|
|
120
|
+
stream.destroy();
|
|
121
|
+
}
|
|
122
|
+
yield new __await(connection.release());
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
__name(streamRows, "streamRows");
|
|
127
|
+
|
|
128
|
+
// lib/mariadb.event-store.ts
|
|
70
129
|
var _MariaDBEventStore = class _MariaDBEventStore extends import_event_sourcing.EventStore {
|
|
71
130
|
constructor() {
|
|
72
131
|
super(...arguments);
|
|
@@ -88,7 +147,7 @@ var _MariaDBEventStore = class _MariaDBEventStore extends import_event_sourcing.
|
|
|
88
147
|
return __async(this, null, function* () {
|
|
89
148
|
const collection = import_event_sourcing.EventCollection.get(pool);
|
|
90
149
|
try {
|
|
91
|
-
yield this.pool.query(`CREATE TABLE IF NOT EXISTS
|
|
150
|
+
yield this.pool.query(`CREATE TABLE IF NOT EXISTS ${this.pool.escapeId(collection)} (
|
|
92
151
|
stream_id VARCHAR(120) NOT NULL,
|
|
93
152
|
version INT NOT NULL,
|
|
94
153
|
event VARCHAR(80) NOT NULL,
|
|
@@ -110,45 +169,35 @@ var _MariaDBEventStore = class _MariaDBEventStore extends import_event_sourcing.
|
|
|
110
169
|
}
|
|
111
170
|
listCollections(filter) {
|
|
112
171
|
return __asyncGenerator(this, null, function* () {
|
|
113
|
-
const connection = this.pool.getConnection();
|
|
114
172
|
const batch = (filter == null ? void 0 : filter.batch) || import_event_sourcing.DEFAULT_BATCH_SIZE;
|
|
115
173
|
const query = "SELECT TABLE_NAME FROM information_schema.tables WHERE BINARY table_name LIKE '%events'";
|
|
116
|
-
|
|
117
|
-
const stream = client.queryStream(query);
|
|
174
|
+
let batchedCollections = [];
|
|
118
175
|
try {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
batchedCollections
|
|
124
|
-
|
|
125
|
-
yield batchedCollections;
|
|
126
|
-
batchedCollections = [];
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
} catch (temp) {
|
|
130
|
-
error = [temp];
|
|
131
|
-
} finally {
|
|
132
|
-
try {
|
|
133
|
-
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
134
|
-
} finally {
|
|
135
|
-
if (error)
|
|
136
|
-
throw error[0];
|
|
176
|
+
for (var iter = __forAwait(streamRows(this.pool, query)), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
|
|
177
|
+
const { TABLE_NAME } = temp.value;
|
|
178
|
+
batchedCollections.push(TABLE_NAME);
|
|
179
|
+
if (batchedCollections.length === batch) {
|
|
180
|
+
yield batchedCollections;
|
|
181
|
+
batchedCollections = [];
|
|
137
182
|
}
|
|
138
183
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
}
|
|
142
|
-
} catch (e) {
|
|
143
|
-
stream.destroy();
|
|
184
|
+
} catch (temp) {
|
|
185
|
+
error = [temp];
|
|
144
186
|
} finally {
|
|
145
|
-
|
|
187
|
+
try {
|
|
188
|
+
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
189
|
+
} finally {
|
|
190
|
+
if (error)
|
|
191
|
+
throw error[0];
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
if (batchedCollections.length > 0) {
|
|
195
|
+
yield batchedCollections;
|
|
146
196
|
}
|
|
147
197
|
});
|
|
148
198
|
}
|
|
149
199
|
getEvents(_0, _1) {
|
|
150
200
|
return __asyncGenerator(this, arguments, function* ({ streamId }, filter) {
|
|
151
|
-
const connection = this.pool.getConnection();
|
|
152
201
|
const collection = import_event_sourcing.EventCollection.get(filter == null ? void 0 : filter.pool);
|
|
153
202
|
const fromVersion = filter == null ? void 0 : filter.fromVersion;
|
|
154
203
|
const direction = (filter == null ? void 0 : filter.direction) || import_event_sourcing.StreamReadingDirection.FORWARD;
|
|
@@ -156,7 +205,7 @@ var _MariaDBEventStore = class _MariaDBEventStore extends import_event_sourcing.
|
|
|
156
205
|
const batch = (filter == null ? void 0 : filter.batch) || import_event_sourcing.DEFAULT_BATCH_SIZE;
|
|
157
206
|
const query = `
|
|
158
207
|
SELECT event, payload
|
|
159
|
-
FROM
|
|
208
|
+
FROM ${this.pool.escapeId(collection)}
|
|
160
209
|
WHERE stream_id = ?
|
|
161
210
|
${fromVersion ? "AND version >= ?" : ""}
|
|
162
211
|
ORDER BY version ${direction === import_event_sourcing.StreamReadingDirection.FORWARD ? "ASC" : "DESC"}
|
|
@@ -170,43 +219,35 @@ var _MariaDBEventStore = class _MariaDBEventStore extends import_event_sourcing.
|
|
|
170
219
|
streamId,
|
|
171
220
|
limit
|
|
172
221
|
];
|
|
173
|
-
|
|
174
|
-
const stream = client.queryStream(query, params);
|
|
222
|
+
let batchedEvents = [];
|
|
175
223
|
try {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
batchedEvents
|
|
181
|
-
|
|
182
|
-
yield batchedEvents;
|
|
183
|
-
batchedEvents = [];
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
} catch (temp) {
|
|
187
|
-
error = [temp];
|
|
188
|
-
} finally {
|
|
189
|
-
try {
|
|
190
|
-
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
191
|
-
} finally {
|
|
192
|
-
if (error)
|
|
193
|
-
throw error[0];
|
|
224
|
+
for (var iter = __forAwait(streamRows(this.pool, query, params)), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
|
|
225
|
+
const { event, payload } = temp.value;
|
|
226
|
+
batchedEvents.push(this.eventMap.deserializeEvent(event, payload));
|
|
227
|
+
if (batchedEvents.length === batch) {
|
|
228
|
+
yield batchedEvents;
|
|
229
|
+
batchedEvents = [];
|
|
194
230
|
}
|
|
195
231
|
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
}
|
|
199
|
-
} catch (e) {
|
|
200
|
-
stream.destroy();
|
|
232
|
+
} catch (temp) {
|
|
233
|
+
error = [temp];
|
|
201
234
|
} finally {
|
|
202
|
-
|
|
235
|
+
try {
|
|
236
|
+
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
237
|
+
} finally {
|
|
238
|
+
if (error)
|
|
239
|
+
throw error[0];
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
if (batchedEvents.length > 0) {
|
|
243
|
+
yield batchedEvents;
|
|
203
244
|
}
|
|
204
245
|
});
|
|
205
246
|
}
|
|
206
247
|
getEvent(_0, _1, _2) {
|
|
207
248
|
return __async(this, arguments, function* ({ streamId }, version, pool) {
|
|
208
249
|
const collection = import_event_sourcing.EventCollection.get(pool);
|
|
209
|
-
const [entity] = yield this.pool.query(`SELECT event, payload FROM
|
|
250
|
+
const [entity] = yield this.pool.query(`SELECT event, payload FROM ${this.pool.escapeId(collection)} WHERE stream_id = ? AND version = ?`, [
|
|
210
251
|
streamId,
|
|
211
252
|
version
|
|
212
253
|
]);
|
|
@@ -220,11 +261,13 @@ var _MariaDBEventStore = class _MariaDBEventStore extends import_event_sourcing.
|
|
|
220
261
|
return __async(this, null, function* () {
|
|
221
262
|
const connection = yield this.pool.getConnection();
|
|
222
263
|
const collection = import_event_sourcing.EventCollection.get(pool);
|
|
264
|
+
let currentVersion = 0;
|
|
223
265
|
try {
|
|
224
|
-
const
|
|
266
|
+
const table = connection.escapeId(collection);
|
|
267
|
+
const [currentVersionResult] = yield connection.query(`SELECT MAX(version) as version FROM ${table} WHERE stream_id = ?`, [
|
|
225
268
|
stream.streamId
|
|
226
269
|
]);
|
|
227
|
-
|
|
270
|
+
currentVersion = (currentVersionResult == null ? void 0 : currentVersionResult.version) || 0;
|
|
228
271
|
if (aggregateVersion <= currentVersion) {
|
|
229
272
|
throw new import_event_sourcing.EventStoreVersionConflictException(stream, aggregateVersion, currentVersion);
|
|
230
273
|
}
|
|
@@ -246,7 +289,7 @@ var _MariaDBEventStore = class _MariaDBEventStore extends import_event_sourcing.
|
|
|
246
289
|
envelopes.push(envelope);
|
|
247
290
|
}
|
|
248
291
|
yield connection.beginTransaction();
|
|
249
|
-
yield connection.batch(`INSERT INTO
|
|
292
|
+
yield connection.batch(`INSERT INTO ${table} VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, envelopes.map(({ event, payload, metadata }) => {
|
|
250
293
|
var _a, _b;
|
|
251
294
|
return [
|
|
252
295
|
stream.streamId,
|
|
@@ -264,15 +307,17 @@ var _MariaDBEventStore = class _MariaDBEventStore extends import_event_sourcing.
|
|
|
264
307
|
yield connection.commit();
|
|
265
308
|
return envelopes;
|
|
266
309
|
} catch (error) {
|
|
267
|
-
yield connection.rollback();
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
310
|
+
yield connection.rollback().catch(() => void 0);
|
|
311
|
+
if (error instanceof import_event_sourcing.EventStoreVersionConflictException) {
|
|
312
|
+
throw error;
|
|
313
|
+
}
|
|
314
|
+
if (isDuplicateEntryError(error)) {
|
|
315
|
+
const latestVersion = yield this.getLatestVersion(collection, stream, connection, currentVersion);
|
|
316
|
+
throw new import_event_sourcing.EventStoreVersionConflictException(stream, aggregateVersion, latestVersion, error);
|
|
273
317
|
}
|
|
318
|
+
throw new import_event_sourcing.EventStorePersistenceException(collection, error);
|
|
274
319
|
} finally {
|
|
275
|
-
connection.release();
|
|
320
|
+
yield connection.release();
|
|
276
321
|
}
|
|
277
322
|
});
|
|
278
323
|
}
|
|
@@ -280,7 +325,7 @@ var _MariaDBEventStore = class _MariaDBEventStore extends import_event_sourcing.
|
|
|
280
325
|
return __async(this, arguments, function* ({ streamId }, version, pool) {
|
|
281
326
|
var _a, _b;
|
|
282
327
|
const collection = import_event_sourcing.EventCollection.get(pool);
|
|
283
|
-
const [entity] = yield this.pool.query(`SELECT event, payload, event_id, aggregate_id, version, occurred_on, correlation_id, causation_id FROM
|
|
328
|
+
const [entity] = yield this.pool.query(`SELECT event, payload, event_id, aggregate_id, version, occurred_on, correlation_id, causation_id FROM ${this.pool.escapeId(collection)} WHERE stream_id = ? AND version = ?`, [
|
|
284
329
|
streamId,
|
|
285
330
|
version
|
|
286
331
|
]);
|
|
@@ -299,7 +344,6 @@ var _MariaDBEventStore = class _MariaDBEventStore extends import_event_sourcing.
|
|
|
299
344
|
}
|
|
300
345
|
getEnvelopes(_0, _1) {
|
|
301
346
|
return __asyncGenerator(this, arguments, function* ({ streamId }, filter) {
|
|
302
|
-
const connection = this.pool.getConnection();
|
|
303
347
|
const collection = import_event_sourcing.EventCollection.get(filter == null ? void 0 : filter.pool);
|
|
304
348
|
const fromVersion = filter == null ? void 0 : filter.fromVersion;
|
|
305
349
|
const direction = (filter == null ? void 0 : filter.direction) || import_event_sourcing.StreamReadingDirection.FORWARD;
|
|
@@ -307,7 +351,7 @@ var _MariaDBEventStore = class _MariaDBEventStore extends import_event_sourcing.
|
|
|
307
351
|
const batch = (filter == null ? void 0 : filter.batch) || import_event_sourcing.DEFAULT_BATCH_SIZE;
|
|
308
352
|
const query = `
|
|
309
353
|
SELECT event, payload, event_id, aggregate_id, version, occurred_on, correlation_id, causation_id
|
|
310
|
-
FROM
|
|
354
|
+
FROM ${this.pool.escapeId(collection)}
|
|
311
355
|
WHERE stream_id = ?
|
|
312
356
|
${fromVersion ? "AND version >= ?" : ""}
|
|
313
357
|
ORDER BY version ${direction === import_event_sourcing.StreamReadingDirection.FORWARD ? "ASC" : "DESC"}
|
|
@@ -321,98 +365,96 @@ var _MariaDBEventStore = class _MariaDBEventStore extends import_event_sourcing.
|
|
|
321
365
|
streamId,
|
|
322
366
|
limit
|
|
323
367
|
];
|
|
324
|
-
|
|
325
|
-
const stream = client.queryStream(query, params);
|
|
368
|
+
let batchedEvents = [];
|
|
326
369
|
try {
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
yield batchedEvents;
|
|
341
|
-
batchedEvents = [];
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
} catch (temp) {
|
|
345
|
-
error = [temp];
|
|
346
|
-
} finally {
|
|
347
|
-
try {
|
|
348
|
-
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
349
|
-
} finally {
|
|
350
|
-
if (error)
|
|
351
|
-
throw error[0];
|
|
370
|
+
for (var iter = __forAwait(streamRows(this.pool, query, params)), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
|
|
371
|
+
const { event, payload, event_id, aggregate_id, version, occurred_on, correlation_id, causation_id } = temp.value;
|
|
372
|
+
batchedEvents.push(import_event_sourcing.EventEnvelope.from(event, payload, {
|
|
373
|
+
eventId: import_event_sourcing.EventId.from(event_id),
|
|
374
|
+
aggregateId: aggregate_id,
|
|
375
|
+
version,
|
|
376
|
+
occurredOn: occurred_on,
|
|
377
|
+
correlationId: correlation_id != null ? correlation_id : void 0,
|
|
378
|
+
causationId: causation_id != null ? causation_id : void 0
|
|
379
|
+
}));
|
|
380
|
+
if (batchedEvents.length === batch) {
|
|
381
|
+
yield batchedEvents;
|
|
382
|
+
batchedEvents = [];
|
|
352
383
|
}
|
|
353
384
|
}
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
}
|
|
357
|
-
} catch (e) {
|
|
358
|
-
stream.destroy();
|
|
385
|
+
} catch (temp) {
|
|
386
|
+
error = [temp];
|
|
359
387
|
} finally {
|
|
360
|
-
|
|
388
|
+
try {
|
|
389
|
+
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
390
|
+
} finally {
|
|
391
|
+
if (error)
|
|
392
|
+
throw error[0];
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
if (batchedEvents.length > 0) {
|
|
396
|
+
yield batchedEvents;
|
|
361
397
|
}
|
|
362
398
|
});
|
|
363
399
|
}
|
|
364
400
|
getAllEnvelopes(filter) {
|
|
365
401
|
return __asyncGenerator(this, null, function* () {
|
|
366
|
-
const connection = this.pool.getConnection();
|
|
367
402
|
const collection = import_event_sourcing.EventCollection.get(filter == null ? void 0 : filter.pool);
|
|
368
403
|
const yearMonths = this.getYearMonthRange(filter.since, filter.until);
|
|
369
404
|
const batch = (filter == null ? void 0 : filter.batch) || import_event_sourcing.DEFAULT_BATCH_SIZE;
|
|
370
405
|
const query = `
|
|
371
406
|
SELECT event, payload, event_id, aggregate_id, version, occurred_on, correlation_id, causation_id
|
|
372
|
-
FROM
|
|
407
|
+
FROM ${this.pool.escapeId(collection)}
|
|
373
408
|
WHERE event_date IN (?)
|
|
374
409
|
ORDER BY event_date ASC, event_id ASC
|
|
375
410
|
`;
|
|
376
411
|
const params = [
|
|
377
412
|
yearMonths
|
|
378
413
|
];
|
|
379
|
-
|
|
380
|
-
const stream = client.queryStream(query, params);
|
|
414
|
+
let batchedEvents = [];
|
|
381
415
|
try {
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
yield batchedEvents;
|
|
396
|
-
batchedEvents = [];
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
} catch (temp) {
|
|
400
|
-
error = [temp];
|
|
401
|
-
} finally {
|
|
402
|
-
try {
|
|
403
|
-
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
404
|
-
} finally {
|
|
405
|
-
if (error)
|
|
406
|
-
throw error[0];
|
|
416
|
+
for (var iter = __forAwait(streamRows(this.pool, query, params)), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
|
|
417
|
+
const { event, payload, event_id, aggregate_id, version, occurred_on, correlation_id, causation_id } = temp.value;
|
|
418
|
+
batchedEvents.push(import_event_sourcing.EventEnvelope.from(event, payload, {
|
|
419
|
+
eventId: import_event_sourcing.EventId.from(event_id),
|
|
420
|
+
aggregateId: aggregate_id,
|
|
421
|
+
version,
|
|
422
|
+
occurredOn: occurred_on,
|
|
423
|
+
correlationId: correlation_id != null ? correlation_id : void 0,
|
|
424
|
+
causationId: causation_id != null ? causation_id : void 0
|
|
425
|
+
}));
|
|
426
|
+
if (batchedEvents.length === batch) {
|
|
427
|
+
yield batchedEvents;
|
|
428
|
+
batchedEvents = [];
|
|
407
429
|
}
|
|
408
430
|
}
|
|
409
|
-
|
|
410
|
-
|
|
431
|
+
} catch (temp) {
|
|
432
|
+
error = [temp];
|
|
433
|
+
} finally {
|
|
434
|
+
try {
|
|
435
|
+
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
436
|
+
} finally {
|
|
437
|
+
if (error)
|
|
438
|
+
throw error[0];
|
|
411
439
|
}
|
|
440
|
+
}
|
|
441
|
+
if (batchedEvents.length > 0) {
|
|
442
|
+
yield batchedEvents;
|
|
443
|
+
}
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* Best effort lookup of the latest version of a stream, used to report a conflict.
|
|
448
|
+
*/
|
|
449
|
+
getLatestVersion(_0, _1, _2, _3) {
|
|
450
|
+
return __async(this, arguments, function* (collection, { streamId }, connection, fallback) {
|
|
451
|
+
try {
|
|
452
|
+
const [result] = yield connection.query(`SELECT MAX(version) as version FROM ${connection.escapeId(collection)} WHERE stream_id = ?`, [
|
|
453
|
+
streamId
|
|
454
|
+
]);
|
|
455
|
+
return (result == null ? void 0 : result.version) || fallback;
|
|
412
456
|
} catch (e) {
|
|
413
|
-
|
|
414
|
-
} finally {
|
|
415
|
-
yield new __await(client.release());
|
|
457
|
+
return fallback;
|
|
416
458
|
}
|
|
417
459
|
});
|
|
418
460
|
}
|
|
@@ -422,7 +464,7 @@ var MariaDBEventStore = _MariaDBEventStore;
|
|
|
422
464
|
|
|
423
465
|
// lib/mariadb.snapshot-store.ts
|
|
424
466
|
var import_event_sourcing2 = require("@ocoda/event-sourcing");
|
|
425
|
-
var
|
|
467
|
+
var import_mariadb3 = require("mariadb");
|
|
426
468
|
var _MariaDBSnapshotStore = class _MariaDBSnapshotStore extends import_event_sourcing2.SnapshotStore {
|
|
427
469
|
constructor() {
|
|
428
470
|
super(...arguments);
|
|
@@ -431,7 +473,7 @@ var _MariaDBSnapshotStore = class _MariaDBSnapshotStore extends import_event_sou
|
|
|
431
473
|
connect() {
|
|
432
474
|
return __async(this, null, function* () {
|
|
433
475
|
this.logger.log("Starting store");
|
|
434
|
-
this.pool = (0,
|
|
476
|
+
this.pool = (0, import_mariadb3.createPool)(this.options);
|
|
435
477
|
});
|
|
436
478
|
}
|
|
437
479
|
disconnect() {
|
|
@@ -444,7 +486,7 @@ var _MariaDBSnapshotStore = class _MariaDBSnapshotStore extends import_event_sou
|
|
|
444
486
|
return __async(this, null, function* () {
|
|
445
487
|
const collection = import_event_sourcing2.SnapshotCollection.get(pool);
|
|
446
488
|
try {
|
|
447
|
-
yield this.pool.query(`CREATE TABLE IF NOT EXISTS
|
|
489
|
+
yield this.pool.query(`CREATE TABLE IF NOT EXISTS ${this.pool.escapeId(collection)} (
|
|
448
490
|
stream_id VARCHAR(90) NOT NULL,
|
|
449
491
|
version INT NOT NULL,
|
|
450
492
|
payload JSON NOT NULL,
|
|
@@ -464,45 +506,35 @@ var _MariaDBSnapshotStore = class _MariaDBSnapshotStore extends import_event_sou
|
|
|
464
506
|
}
|
|
465
507
|
listCollections(filter) {
|
|
466
508
|
return __asyncGenerator(this, null, function* () {
|
|
467
|
-
const connection = this.pool.getConnection();
|
|
468
509
|
const batch = (filter == null ? void 0 : filter.batch) || import_event_sourcing2.DEFAULT_BATCH_SIZE;
|
|
469
510
|
const query = "SELECT TABLE_NAME FROM information_schema.tables WHERE BINARY table_name LIKE '%snapshots'";
|
|
470
|
-
|
|
471
|
-
const stream = client.queryStream(query);
|
|
511
|
+
let batchedCollections = [];
|
|
472
512
|
try {
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
batchedCollections
|
|
478
|
-
|
|
479
|
-
yield batchedCollections;
|
|
480
|
-
batchedCollections = [];
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
} catch (temp) {
|
|
484
|
-
error = [temp];
|
|
485
|
-
} finally {
|
|
486
|
-
try {
|
|
487
|
-
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
488
|
-
} finally {
|
|
489
|
-
if (error)
|
|
490
|
-
throw error[0];
|
|
513
|
+
for (var iter = __forAwait(streamRows(this.pool, query)), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
|
|
514
|
+
const { TABLE_NAME } = temp.value;
|
|
515
|
+
batchedCollections.push(TABLE_NAME);
|
|
516
|
+
if (batchedCollections.length === batch) {
|
|
517
|
+
yield batchedCollections;
|
|
518
|
+
batchedCollections = [];
|
|
491
519
|
}
|
|
492
520
|
}
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
}
|
|
496
|
-
} catch (e) {
|
|
497
|
-
stream.destroy();
|
|
521
|
+
} catch (temp) {
|
|
522
|
+
error = [temp];
|
|
498
523
|
} finally {
|
|
499
|
-
|
|
524
|
+
try {
|
|
525
|
+
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
526
|
+
} finally {
|
|
527
|
+
if (error)
|
|
528
|
+
throw error[0];
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
if (batchedCollections.length > 0) {
|
|
532
|
+
yield batchedCollections;
|
|
500
533
|
}
|
|
501
534
|
});
|
|
502
535
|
}
|
|
503
536
|
getSnapshots(_0, _1) {
|
|
504
537
|
return __asyncGenerator(this, arguments, function* ({ streamId }, filter) {
|
|
505
|
-
const connection = this.pool.getConnection();
|
|
506
538
|
const collection = import_event_sourcing2.SnapshotCollection.get(filter == null ? void 0 : filter.pool);
|
|
507
539
|
const fromVersion = filter == null ? void 0 : filter.fromVersion;
|
|
508
540
|
const direction = (filter == null ? void 0 : filter.direction) || import_event_sourcing2.StreamReadingDirection.FORWARD;
|
|
@@ -510,7 +542,7 @@ var _MariaDBSnapshotStore = class _MariaDBSnapshotStore extends import_event_sou
|
|
|
510
542
|
const batch = (filter == null ? void 0 : filter.batch) || import_event_sourcing2.DEFAULT_BATCH_SIZE;
|
|
511
543
|
const query = `
|
|
512
544
|
SELECT payload
|
|
513
|
-
FROM
|
|
545
|
+
FROM ${this.pool.escapeId(collection)}
|
|
514
546
|
WHERE stream_id = ?
|
|
515
547
|
${fromVersion ? "AND version >= ?" : ""}
|
|
516
548
|
ORDER BY version ${direction === import_event_sourcing2.StreamReadingDirection.FORWARD ? "ASC" : "DESC"}
|
|
@@ -524,43 +556,35 @@ var _MariaDBSnapshotStore = class _MariaDBSnapshotStore extends import_event_sou
|
|
|
524
556
|
streamId,
|
|
525
557
|
limit
|
|
526
558
|
];
|
|
527
|
-
|
|
528
|
-
const stream = client.queryStream(query, params);
|
|
559
|
+
let batchedEvents = [];
|
|
529
560
|
try {
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
batchedEvents
|
|
535
|
-
|
|
536
|
-
yield batchedEvents;
|
|
537
|
-
batchedEvents = [];
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
} catch (temp) {
|
|
541
|
-
error = [temp];
|
|
542
|
-
} finally {
|
|
543
|
-
try {
|
|
544
|
-
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
545
|
-
} finally {
|
|
546
|
-
if (error)
|
|
547
|
-
throw error[0];
|
|
561
|
+
for (var iter = __forAwait(streamRows(this.pool, query, params)), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
|
|
562
|
+
const { payload } = temp.value;
|
|
563
|
+
batchedEvents.push(payload);
|
|
564
|
+
if (batchedEvents.length === batch) {
|
|
565
|
+
yield batchedEvents;
|
|
566
|
+
batchedEvents = [];
|
|
548
567
|
}
|
|
549
568
|
}
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
}
|
|
553
|
-
} catch (e) {
|
|
554
|
-
stream.destroy();
|
|
569
|
+
} catch (temp) {
|
|
570
|
+
error = [temp];
|
|
555
571
|
} finally {
|
|
556
|
-
|
|
572
|
+
try {
|
|
573
|
+
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
574
|
+
} finally {
|
|
575
|
+
if (error)
|
|
576
|
+
throw error[0];
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
if (batchedEvents.length > 0) {
|
|
580
|
+
yield batchedEvents;
|
|
557
581
|
}
|
|
558
582
|
});
|
|
559
583
|
}
|
|
560
584
|
getSnapshot(_0, _1, _2) {
|
|
561
585
|
return __async(this, arguments, function* ({ streamId }, version, pool) {
|
|
562
586
|
const collection = import_event_sourcing2.SnapshotCollection.get(pool);
|
|
563
|
-
const [entity] = yield this.pool.query(`SELECT payload FROM
|
|
587
|
+
const [entity] = yield this.pool.query(`SELECT payload FROM ${this.pool.escapeId(collection)} WHERE stream_id = ? AND version = ?`, [
|
|
564
588
|
streamId,
|
|
565
589
|
version
|
|
566
590
|
]);
|
|
@@ -572,9 +596,12 @@ var _MariaDBSnapshotStore = class _MariaDBSnapshotStore extends import_event_sou
|
|
|
572
596
|
}
|
|
573
597
|
appendSnapshot(stream, aggregateVersion, snapshot, pool) {
|
|
574
598
|
return __async(this, null, function* () {
|
|
599
|
+
var _a;
|
|
575
600
|
const connection = yield this.pool.getConnection();
|
|
576
601
|
const collection = import_event_sourcing2.SnapshotCollection.get(pool);
|
|
602
|
+
let latestVersion = 0;
|
|
577
603
|
try {
|
|
604
|
+
const table = connection.escapeId(collection);
|
|
578
605
|
const envelope = import_event_sourcing2.SnapshotEnvelope.create(snapshot, {
|
|
579
606
|
aggregateId: stream.aggregateId,
|
|
580
607
|
version: aggregateVersion
|
|
@@ -585,17 +612,18 @@ var _MariaDBSnapshotStore = class _MariaDBSnapshotStore extends import_event_sou
|
|
|
585
612
|
"stream_id",
|
|
586
613
|
"version"
|
|
587
614
|
], connection);
|
|
615
|
+
latestVersion = (_a = lastStreamEntity == null ? void 0 : lastStreamEntity.version) != null ? _a : 0;
|
|
588
616
|
if (aggregateVersion <= (lastStreamEntity == null ? void 0 : lastStreamEntity.version)) {
|
|
589
617
|
throw new import_event_sourcing2.SnapshotStoreVersionConflictException(stream, aggregateVersion, lastStreamEntity.version);
|
|
590
618
|
}
|
|
591
619
|
yield connection.beginTransaction();
|
|
592
620
|
if (lastStreamEntity) {
|
|
593
|
-
yield connection.query(`UPDATE
|
|
621
|
+
yield connection.query(`UPDATE ${table} SET latest = null WHERE stream_id = ? AND version = ?`, [
|
|
594
622
|
lastStreamEntity.stream_id,
|
|
595
623
|
lastStreamEntity.version
|
|
596
624
|
]);
|
|
597
625
|
}
|
|
598
|
-
yield connection.query(`INSERT INTO
|
|
626
|
+
yield connection.query(`INSERT INTO ${table} VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
599
627
|
stream.streamId,
|
|
600
628
|
envelope.metadata.version,
|
|
601
629
|
JSON.stringify(envelope.payload),
|
|
@@ -608,15 +636,17 @@ var _MariaDBSnapshotStore = class _MariaDBSnapshotStore extends import_event_sou
|
|
|
608
636
|
yield connection.commit();
|
|
609
637
|
return envelope;
|
|
610
638
|
} catch (error) {
|
|
611
|
-
yield connection.rollback();
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
throw error;
|
|
615
|
-
default:
|
|
616
|
-
throw new import_event_sourcing2.SnapshotStorePersistenceException(collection, error);
|
|
639
|
+
yield connection.rollback().catch(() => void 0);
|
|
640
|
+
if (error instanceof import_event_sourcing2.SnapshotStoreVersionConflictException) {
|
|
641
|
+
throw error;
|
|
617
642
|
}
|
|
643
|
+
if (isDuplicateEntryError(error)) {
|
|
644
|
+
latestVersion = yield this.getLatestVersion(collection, stream, connection, latestVersion);
|
|
645
|
+
throw new import_event_sourcing2.SnapshotStoreVersionConflictException(stream, aggregateVersion, latestVersion, error);
|
|
646
|
+
}
|
|
647
|
+
throw new import_event_sourcing2.SnapshotStorePersistenceException(collection, error);
|
|
618
648
|
} finally {
|
|
619
|
-
connection.release();
|
|
649
|
+
yield connection.release();
|
|
620
650
|
}
|
|
621
651
|
});
|
|
622
652
|
}
|
|
@@ -673,7 +703,6 @@ var _MariaDBSnapshotStore = class _MariaDBSnapshotStore extends import_event_sou
|
|
|
673
703
|
}
|
|
674
704
|
getEnvelopes(_0, _1) {
|
|
675
705
|
return __asyncGenerator(this, arguments, function* ({ streamId }, filter) {
|
|
676
|
-
const connection = this.pool.getConnection();
|
|
677
706
|
const collection = import_event_sourcing2.SnapshotCollection.get(filter == null ? void 0 : filter.pool);
|
|
678
707
|
const fromVersion = filter == null ? void 0 : filter.fromVersion;
|
|
679
708
|
const direction = (filter == null ? void 0 : filter.direction) || import_event_sourcing2.StreamReadingDirection.FORWARD;
|
|
@@ -681,7 +710,7 @@ var _MariaDBSnapshotStore = class _MariaDBSnapshotStore extends import_event_sou
|
|
|
681
710
|
const batch = (filter == null ? void 0 : filter.batch) || import_event_sourcing2.DEFAULT_BATCH_SIZE;
|
|
682
711
|
const query = `
|
|
683
712
|
SELECT payload, aggregate_id, registered_on, snapshot_id, version
|
|
684
|
-
FROM
|
|
713
|
+
FROM ${this.pool.escapeId(collection)}
|
|
685
714
|
WHERE stream_id = ?
|
|
686
715
|
${fromVersion ? "AND version >= ?" : ""}
|
|
687
716
|
ORDER BY version ${direction === import_event_sourcing2.StreamReadingDirection.FORWARD ? "ASC" : "DESC"}
|
|
@@ -695,48 +724,40 @@ var _MariaDBSnapshotStore = class _MariaDBSnapshotStore extends import_event_sou
|
|
|
695
724
|
streamId,
|
|
696
725
|
limit
|
|
697
726
|
];
|
|
698
|
-
|
|
699
|
-
const stream = client.queryStream(query, params);
|
|
727
|
+
let batchedSnapshots = [];
|
|
700
728
|
try {
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
yield batchedSnapshots;
|
|
713
|
-
batchedSnapshots = [];
|
|
714
|
-
}
|
|
715
|
-
}
|
|
716
|
-
} catch (temp) {
|
|
717
|
-
error = [temp];
|
|
718
|
-
} finally {
|
|
719
|
-
try {
|
|
720
|
-
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
721
|
-
} finally {
|
|
722
|
-
if (error)
|
|
723
|
-
throw error[0];
|
|
729
|
+
for (var iter = __forAwait(streamRows(this.pool, query, params)), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
|
|
730
|
+
const { payload, aggregate_id, registered_on, snapshot_id, version } = temp.value;
|
|
731
|
+
batchedSnapshots.push(import_event_sourcing2.SnapshotEnvelope.from(payload, {
|
|
732
|
+
aggregateId: aggregate_id,
|
|
733
|
+
registeredOn: registered_on,
|
|
734
|
+
snapshotId: snapshot_id,
|
|
735
|
+
version
|
|
736
|
+
}));
|
|
737
|
+
if (batchedSnapshots.length === batch) {
|
|
738
|
+
yield batchedSnapshots;
|
|
739
|
+
batchedSnapshots = [];
|
|
724
740
|
}
|
|
725
741
|
}
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
}
|
|
729
|
-
} catch (e) {
|
|
730
|
-
stream.destroy();
|
|
742
|
+
} catch (temp) {
|
|
743
|
+
error = [temp];
|
|
731
744
|
} finally {
|
|
732
|
-
|
|
745
|
+
try {
|
|
746
|
+
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
747
|
+
} finally {
|
|
748
|
+
if (error)
|
|
749
|
+
throw error[0];
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
if (batchedSnapshots.length > 0) {
|
|
753
|
+
yield batchedSnapshots;
|
|
733
754
|
}
|
|
734
755
|
});
|
|
735
756
|
}
|
|
736
757
|
getEnvelope(_0, _1, _2) {
|
|
737
758
|
return __async(this, arguments, function* ({ streamId }, version, pool) {
|
|
738
759
|
const collection = import_event_sourcing2.SnapshotCollection.get(pool);
|
|
739
|
-
const [entity] = yield this.pool.query(`SELECT payload, aggregate_id, registered_on, snapshot_id, version FROM
|
|
760
|
+
const [entity] = yield this.pool.query(`SELECT payload, aggregate_id, registered_on, snapshot_id, version FROM ${this.pool.escapeId(collection)} WHERE stream_id = ? AND version = ?`, [
|
|
740
761
|
streamId,
|
|
741
762
|
version
|
|
742
763
|
]);
|
|
@@ -753,7 +774,6 @@ var _MariaDBSnapshotStore = class _MariaDBSnapshotStore extends import_event_sou
|
|
|
753
774
|
}
|
|
754
775
|
getLastEnvelopesForAggregate(aggregate, filter) {
|
|
755
776
|
return __asyncGenerator(this, null, function* () {
|
|
756
|
-
const connection = this.pool.getConnection();
|
|
757
777
|
const collection = import_event_sourcing2.SnapshotCollection.get(filter == null ? void 0 : filter.pool);
|
|
758
778
|
const { streamName } = (0, import_event_sourcing2.getAggregateMetadata)(aggregate);
|
|
759
779
|
const aggregateId = filter == null ? void 0 : filter.aggregateId;
|
|
@@ -761,7 +781,7 @@ var _MariaDBSnapshotStore = class _MariaDBSnapshotStore extends import_event_sou
|
|
|
761
781
|
const batch = (filter == null ? void 0 : filter.batch) || import_event_sourcing2.DEFAULT_BATCH_SIZE;
|
|
762
782
|
const query = `
|
|
763
783
|
SELECT payload, aggregate_id, registered_on, snapshot_id, version
|
|
764
|
-
FROM
|
|
784
|
+
FROM ${this.pool.escapeId(collection)}
|
|
765
785
|
WHERE aggregate_name = ?
|
|
766
786
|
AND ${aggregateId ? "latest >= ?" : "latest LIKE 'latest%'"}
|
|
767
787
|
LIMIT ?
|
|
@@ -774,41 +794,33 @@ var _MariaDBSnapshotStore = class _MariaDBSnapshotStore extends import_event_sou
|
|
|
774
794
|
streamName,
|
|
775
795
|
limit
|
|
776
796
|
];
|
|
777
|
-
|
|
778
|
-
const stream = client.queryStream(query, params);
|
|
797
|
+
let batchedSnapshots = [];
|
|
779
798
|
try {
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
yield batchedSnapshots;
|
|
792
|
-
batchedSnapshots = [];
|
|
793
|
-
}
|
|
794
|
-
}
|
|
795
|
-
} catch (temp) {
|
|
796
|
-
error = [temp];
|
|
797
|
-
} finally {
|
|
798
|
-
try {
|
|
799
|
-
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
800
|
-
} finally {
|
|
801
|
-
if (error)
|
|
802
|
-
throw error[0];
|
|
799
|
+
for (var iter = __forAwait(streamRows(this.pool, query, params)), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
|
|
800
|
+
const { payload, aggregate_id, registered_on, snapshot_id, version } = temp.value;
|
|
801
|
+
batchedSnapshots.push(import_event_sourcing2.SnapshotEnvelope.from(payload, {
|
|
802
|
+
aggregateId: aggregate_id,
|
|
803
|
+
registeredOn: registered_on,
|
|
804
|
+
snapshotId: snapshot_id,
|
|
805
|
+
version
|
|
806
|
+
}));
|
|
807
|
+
if (batchedSnapshots.length === batch) {
|
|
808
|
+
yield batchedSnapshots;
|
|
809
|
+
batchedSnapshots = [];
|
|
803
810
|
}
|
|
804
811
|
}
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
}
|
|
808
|
-
} catch (e) {
|
|
809
|
-
stream.destroy();
|
|
812
|
+
} catch (temp) {
|
|
813
|
+
error = [temp];
|
|
810
814
|
} finally {
|
|
811
|
-
|
|
815
|
+
try {
|
|
816
|
+
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
817
|
+
} finally {
|
|
818
|
+
if (error)
|
|
819
|
+
throw error[0];
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
if (batchedSnapshots.length > 0) {
|
|
823
|
+
yield batchedSnapshots;
|
|
812
824
|
}
|
|
813
825
|
});
|
|
814
826
|
}
|
|
@@ -839,15 +851,33 @@ var _MariaDBSnapshotStore = class _MariaDBSnapshotStore extends import_event_sou
|
|
|
839
851
|
}
|
|
840
852
|
getLastStreamEntities(collection, streams, fields, connection) {
|
|
841
853
|
return __async(this, null, function* () {
|
|
854
|
+
if (streams.length === 0) {
|
|
855
|
+
return [];
|
|
856
|
+
}
|
|
842
857
|
const latestIds = streams.map(({ streamId }) => `latest#${streamId}`);
|
|
843
858
|
return (connection || this.pool).query(`SELECT ${fields.join(", ")}
|
|
844
|
-
FROM
|
|
859
|
+
FROM ${this.pool.escapeId(collection)}
|
|
845
860
|
WHERE latest IN (?)
|
|
846
861
|
`, [
|
|
847
862
|
latestIds
|
|
848
863
|
]);
|
|
849
864
|
});
|
|
850
865
|
}
|
|
866
|
+
/**
|
|
867
|
+
* Best effort lookup of the latest snapshot version of a stream, used to report a conflict.
|
|
868
|
+
*/
|
|
869
|
+
getLatestVersion(_0, _1, _2, _3) {
|
|
870
|
+
return __async(this, arguments, function* (collection, { streamId }, connection, fallback) {
|
|
871
|
+
try {
|
|
872
|
+
const [result] = yield connection.query(`SELECT MAX(version) as version FROM ${connection.escapeId(collection)} WHERE stream_id = ?`, [
|
|
873
|
+
streamId
|
|
874
|
+
]);
|
|
875
|
+
return (result == null ? void 0 : result.version) || fallback;
|
|
876
|
+
} catch (e) {
|
|
877
|
+
return fallback;
|
|
878
|
+
}
|
|
879
|
+
});
|
|
880
|
+
}
|
|
851
881
|
};
|
|
852
882
|
__name(_MariaDBSnapshotStore, "MariaDBSnapshotStore");
|
|
853
883
|
var MariaDBSnapshotStore = _MariaDBSnapshotStore;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ocoda/event-sourcing-mariadb",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.2",
|
|
4
4
|
"description": "NestJS Event Sourcing Library (@mariadb)",
|
|
5
5
|
"author": "Dries Hooghe <dries@drieshooghe.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"@nestjs/core": "^11.0.0",
|
|
20
20
|
"reflect-metadata": "^0.2.0",
|
|
21
21
|
"rxjs": "^7.2.0",
|
|
22
|
-
"@ocoda/event-sourcing": "3.0.
|
|
22
|
+
"@ocoda/event-sourcing": "3.0.2"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"@biomejs/biome": "1.9.4",
|