@event-driven-io/emmett-sqlite 0.43.0-apha.2 → 0.43.0-beta.10
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/cloudflare.cjs +21 -0
- package/dist/cloudflare.cjs.map +1 -0
- package/dist/cloudflare.d.cts +16 -0
- package/dist/cloudflare.d.ts +16 -0
- package/dist/cloudflare.js +21 -0
- package/dist/cloudflare.js.map +1 -0
- package/dist/index.cjs +1747 -686
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +105 -177
- package/dist/index.d.ts +105 -177
- package/dist/index.js +1772 -711
- package/dist/index.js.map +1 -1
- package/dist/sqlite3.cjs +18 -0
- package/dist/sqlite3.cjs.map +1 -0
- package/dist/sqlite3.d.cts +15 -0
- package/dist/sqlite3.d.ts +15 -0
- package/dist/sqlite3.js +18 -0
- package/dist/sqlite3.js.map +1 -0
- package/dist/sqliteProjection-BrbKryzB.d.cts +150 -0
- package/dist/sqliteProjection-BrbKryzB.d.ts +150 -0
- package/package.json +5 -5
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,132 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } async function _asyncNullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return await rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class;//
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } async function _asyncNullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return await rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class;// src/eventStore/projections/pongo/pongoProjections.ts
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
var _pongo = require('@event-driven-io/pongo');
|
|
5
|
+
var pongoProjection = ({
|
|
6
|
+
name,
|
|
7
|
+
kind,
|
|
8
|
+
version,
|
|
9
|
+
truncate,
|
|
10
|
+
handle,
|
|
11
|
+
canHandle,
|
|
12
|
+
eventsOptions
|
|
13
|
+
}) => sqliteProjection({
|
|
14
|
+
name,
|
|
15
|
+
version,
|
|
16
|
+
kind: _nullishCoalesce(kind, () => ( "emt:projections:postgresql:pongo:generic")),
|
|
17
|
+
canHandle,
|
|
18
|
+
eventsOptions,
|
|
19
|
+
handle: async (events, context) => {
|
|
20
|
+
const { connection } = context;
|
|
21
|
+
const driver = await pongoDriverRegistry.tryResolve(
|
|
22
|
+
context.driverType
|
|
23
|
+
);
|
|
24
|
+
const pongo = _pongo.pongoClient.call(void 0, {
|
|
25
|
+
driver,
|
|
26
|
+
connectionOptions: { connection }
|
|
27
|
+
});
|
|
28
|
+
try {
|
|
29
|
+
await handle(events, {
|
|
30
|
+
...context,
|
|
31
|
+
pongo
|
|
32
|
+
});
|
|
33
|
+
} finally {
|
|
34
|
+
await pongo.close();
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
truncate: truncate ? async (context) => {
|
|
38
|
+
const { connection } = context;
|
|
39
|
+
const driver = await pongoDriverRegistry.tryResolve(
|
|
40
|
+
context.driverType
|
|
41
|
+
);
|
|
42
|
+
const pongo = _pongo.pongoClient.call(void 0, {
|
|
43
|
+
driver,
|
|
44
|
+
connectionOptions: { connection }
|
|
45
|
+
});
|
|
46
|
+
try {
|
|
47
|
+
await truncate({
|
|
48
|
+
...context,
|
|
49
|
+
pongo
|
|
50
|
+
});
|
|
51
|
+
} finally {
|
|
52
|
+
await pongo.close();
|
|
53
|
+
}
|
|
54
|
+
} : void 0
|
|
55
|
+
});
|
|
56
|
+
var pongoMultiStreamProjection = (options) => {
|
|
57
|
+
const { collectionName, getDocumentId, canHandle } = options;
|
|
58
|
+
const collectionNameWithVersion = options.version && options.version > 0 ? `${collectionName}_v${options.version}` : collectionName;
|
|
59
|
+
return pongoProjection({
|
|
60
|
+
name: collectionNameWithVersion,
|
|
61
|
+
version: options.version,
|
|
62
|
+
kind: _nullishCoalesce(options.kind, () => ( "emt:projections:postgresql:pongo:multi_stream")),
|
|
63
|
+
eventsOptions: options.eventsOptions,
|
|
64
|
+
handle: async (events, { pongo }) => {
|
|
65
|
+
const collection = pongo.db().collection(
|
|
66
|
+
collectionNameWithVersion,
|
|
67
|
+
options.collectionOptions
|
|
68
|
+
);
|
|
69
|
+
for (const event of events) {
|
|
70
|
+
await collection.handle(getDocumentId(event), async (document) => {
|
|
71
|
+
return "initialState" in options ? await options.evolve(
|
|
72
|
+
_nullishCoalesce(document, () => ( options.initialState())),
|
|
73
|
+
event
|
|
74
|
+
) : await options.evolve(
|
|
75
|
+
document,
|
|
76
|
+
event
|
|
77
|
+
);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
canHandle,
|
|
82
|
+
truncate: async (context) => {
|
|
83
|
+
const { connection } = context;
|
|
84
|
+
const driver = await pongoDriverRegistry.tryResolve(
|
|
85
|
+
context.driverType
|
|
86
|
+
);
|
|
87
|
+
const pongo = _pongo.pongoClient.call(void 0, {
|
|
88
|
+
driver,
|
|
89
|
+
connectionOptions: { connection }
|
|
90
|
+
});
|
|
91
|
+
try {
|
|
92
|
+
await pongo.db().collection(
|
|
93
|
+
collectionNameWithVersion,
|
|
94
|
+
options.collectionOptions
|
|
95
|
+
).deleteMany();
|
|
96
|
+
} finally {
|
|
97
|
+
await pongo.close();
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
init: async (context) => {
|
|
101
|
+
const { connection } = context;
|
|
102
|
+
const driver = await pongoDriverRegistry.tryResolve(
|
|
103
|
+
context.driverType
|
|
104
|
+
);
|
|
105
|
+
const pongo = _pongo.pongoClient.call(void 0, {
|
|
106
|
+
connectionOptions: { connection },
|
|
107
|
+
driver
|
|
108
|
+
});
|
|
109
|
+
try {
|
|
110
|
+
await pongo.db().collection(
|
|
111
|
+
collectionNameWithVersion,
|
|
112
|
+
options.collectionOptions
|
|
113
|
+
).schema.migrate();
|
|
114
|
+
} finally {
|
|
115
|
+
await pongo.close();
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
};
|
|
120
|
+
var pongoSingleStreamProjection = (options) => {
|
|
121
|
+
return pongoMultiStreamProjection({
|
|
122
|
+
...options,
|
|
123
|
+
kind: "emt:projections:postgresql:pongo:single_stream",
|
|
124
|
+
getDocumentId: _nullishCoalesce(options.getDocumentId, () => ( ((event) => event.metadata.streamName)))
|
|
125
|
+
});
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
// ../emmett/dist/chunk-AZDDB5SF.js
|
|
2
129
|
var isNumber = (val) => typeof val === "number" && val === val;
|
|
3
|
-
var isBigint = (val) => typeof val === "bigint" && val === val;
|
|
4
130
|
var isString = (val) => typeof val === "string";
|
|
5
131
|
var isErrorConstructor = (expect) => {
|
|
6
132
|
return typeof expect === "function" && expect.prototype && // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
@@ -39,7 +165,7 @@ var ConcurrencyError = class _ConcurrencyError extends EmmettError {
|
|
|
39
165
|
constructor(current, expected, message) {
|
|
40
166
|
super({
|
|
41
167
|
errorCode: EmmettError.Codes.ConcurrencyError,
|
|
42
|
-
message: _nullishCoalesce(message, () => ( `Expected version ${expected.toString()} does not match current ${_optionalChain([current, 'optionalAccess',
|
|
168
|
+
message: _nullishCoalesce(message, () => ( `Expected version ${expected.toString()} does not match current ${_optionalChain([current, 'optionalAccess', _ => _.toString, 'call', _2 => _2()])}`))
|
|
43
169
|
});
|
|
44
170
|
this.current = current;
|
|
45
171
|
this.expected = expected;
|
|
@@ -50,12 +176,24 @@ var ConcurrencyError = class _ConcurrencyError extends EmmettError {
|
|
|
50
176
|
// ../emmett/dist/index.js
|
|
51
177
|
var _uuid = require('uuid');
|
|
52
178
|
|
|
179
|
+
|
|
53
180
|
var _asyncretry = require('async-retry'); var _asyncretry2 = _interopRequireDefault(_asyncretry);
|
|
54
181
|
|
|
55
182
|
|
|
183
|
+
|
|
56
184
|
var emmettPrefix = "emt";
|
|
57
185
|
var defaultTag = `${emmettPrefix}:default`;
|
|
58
186
|
var unknownTag = `${emmettPrefix}:unknown`;
|
|
187
|
+
var canCreateEventStoreSession = (eventStore) => "withSession" in eventStore;
|
|
188
|
+
var nulloSessionFactory = (eventStore) => ({
|
|
189
|
+
withSession: (callback) => {
|
|
190
|
+
const nulloSession = {
|
|
191
|
+
eventStore,
|
|
192
|
+
close: () => Promise.resolve()
|
|
193
|
+
};
|
|
194
|
+
return callback(nulloSession);
|
|
195
|
+
}
|
|
196
|
+
});
|
|
59
197
|
var STREAM_EXISTS = "STREAM_EXISTS";
|
|
60
198
|
var STREAM_DOES_NOT_EXIST = "STREAM_DOES_NOT_EXIST";
|
|
61
199
|
var NO_CONCURRENCY_CHECK = "NO_CONCURRENCY_CHECK";
|
|
@@ -72,12 +210,12 @@ var assertExpectedVersionMatchesCurrent = (current, expected, defaultVersion) =>
|
|
|
72
210
|
};
|
|
73
211
|
var ExpectedVersionConflictError = class _ExpectedVersionConflictError extends ConcurrencyError {
|
|
74
212
|
constructor(current, expected) {
|
|
75
|
-
super(_optionalChain([current, 'optionalAccess',
|
|
213
|
+
super(_optionalChain([current, 'optionalAccess', _3 => _3.toString, 'call', _4 => _4()]), _optionalChain([expected, 'optionalAccess', _5 => _5.toString, 'call', _6 => _6()]));
|
|
76
214
|
Object.setPrototypeOf(this, _ExpectedVersionConflictError.prototype);
|
|
77
215
|
}
|
|
78
216
|
};
|
|
79
|
-
var isExpectedVersionConflictError = (
|
|
80
|
-
|
|
217
|
+
var isExpectedVersionConflictError = (error) => error instanceof ExpectedVersionConflictError || EmmettError.isInstanceOf(
|
|
218
|
+
error,
|
|
81
219
|
ExpectedVersionConflictError.Codes.ConcurrencyError
|
|
82
220
|
);
|
|
83
221
|
var isPrimitive = (value) => {
|
|
@@ -281,28 +419,336 @@ var deepEquals = (left, right) => {
|
|
|
281
419
|
var isEquatable = (left) => {
|
|
282
420
|
return left !== null && left !== void 0 && typeof left === "object" && "equals" in left && typeof left["equals"] === "function";
|
|
283
421
|
};
|
|
284
|
-
var
|
|
285
|
-
|
|
286
|
-
|
|
422
|
+
var toNormalizedString = (value) => value.toString().padStart(19, "0");
|
|
423
|
+
var bigInt = {
|
|
424
|
+
toNormalizedString
|
|
425
|
+
};
|
|
426
|
+
var bigIntReplacer = (_key, value) => {
|
|
427
|
+
return typeof value === "bigint" ? value.toString() : value;
|
|
428
|
+
};
|
|
429
|
+
var dateReplacer = (_key, value) => {
|
|
430
|
+
return value instanceof Date ? value.toISOString() : value;
|
|
431
|
+
};
|
|
432
|
+
var isFirstLetterNumeric = (str) => {
|
|
433
|
+
const c = str.charCodeAt(0);
|
|
434
|
+
return c >= 48 && c <= 57;
|
|
435
|
+
};
|
|
436
|
+
var isFirstLetterNumericOrMinus = (str) => {
|
|
437
|
+
const c = str.charCodeAt(0);
|
|
438
|
+
return c >= 48 && c <= 57 || c === 45;
|
|
439
|
+
};
|
|
440
|
+
var bigIntReviver = (_key, value, context) => {
|
|
441
|
+
if (typeof value === "number" && Number.isInteger(value) && !Number.isSafeInteger(value)) {
|
|
442
|
+
try {
|
|
443
|
+
return BigInt(_nullishCoalesce(_optionalChain([context, 'optionalAccess', _7 => _7.source]), () => ( value.toString())));
|
|
444
|
+
} catch (e2) {
|
|
445
|
+
return value;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
if (typeof value === "string" && value.length > 15) {
|
|
449
|
+
if (isFirstLetterNumericOrMinus(value)) {
|
|
450
|
+
const num = Number(value);
|
|
451
|
+
if (Number.isFinite(num) && !Number.isSafeInteger(num)) {
|
|
452
|
+
try {
|
|
453
|
+
return BigInt(value);
|
|
454
|
+
} catch (e3) {
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
return value;
|
|
460
|
+
};
|
|
461
|
+
var dateReviver = (_key, value) => {
|
|
462
|
+
if (typeof value === "string" && value.length === 24 && isFirstLetterNumeric(value) && value[10] === "T" && value[23] === "Z") {
|
|
463
|
+
const date = new Date(value);
|
|
464
|
+
if (!isNaN(date.getTime())) {
|
|
465
|
+
return date;
|
|
466
|
+
}
|
|
287
467
|
}
|
|
468
|
+
return value;
|
|
288
469
|
};
|
|
289
|
-
var
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
470
|
+
var composeJSONReplacers = (...replacers) => {
|
|
471
|
+
const filteredReplacers = replacers.filter((r) => r !== void 0);
|
|
472
|
+
if (filteredReplacers.length === 0) return void 0;
|
|
473
|
+
return (key, value) => (
|
|
474
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
475
|
+
filteredReplacers.reduce(
|
|
294
476
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
295
|
-
(
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
477
|
+
(accValue, replacer) => replacer(key, accValue),
|
|
478
|
+
value
|
|
479
|
+
)
|
|
480
|
+
);
|
|
481
|
+
};
|
|
482
|
+
var composeJSONRevivers = (...revivers) => {
|
|
483
|
+
const filteredRevivers = revivers.filter((r) => r !== void 0);
|
|
484
|
+
if (filteredRevivers.length === 0) return void 0;
|
|
485
|
+
return (key, value, context) => (
|
|
486
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
487
|
+
filteredRevivers.reduce(
|
|
488
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
489
|
+
(accValue, reviver) => reviver(key, accValue, context),
|
|
490
|
+
value
|
|
491
|
+
)
|
|
492
|
+
);
|
|
493
|
+
};
|
|
494
|
+
var JSONReplacer = (opts) => composeJSONReplacers(
|
|
495
|
+
_optionalChain([opts, 'optionalAccess', _8 => _8.replacer]),
|
|
496
|
+
_optionalChain([opts, 'optionalAccess', _9 => _9.failOnBigIntSerialization]) !== true ? JSONReplacers.bigInt : void 0,
|
|
497
|
+
_optionalChain([opts, 'optionalAccess', _10 => _10.useDefaultDateSerialization]) !== true ? JSONReplacers.date : void 0
|
|
498
|
+
);
|
|
499
|
+
var JSONReviver = (opts) => composeJSONRevivers(
|
|
500
|
+
_optionalChain([opts, 'optionalAccess', _11 => _11.reviver]),
|
|
501
|
+
_optionalChain([opts, 'optionalAccess', _12 => _12.parseBigInts]) === true ? JSONRevivers.bigInt : void 0,
|
|
502
|
+
_optionalChain([opts, 'optionalAccess', _13 => _13.parseDates]) === true ? JSONRevivers.date : void 0
|
|
503
|
+
);
|
|
504
|
+
var JSONReplacers = {
|
|
505
|
+
bigInt: bigIntReplacer,
|
|
506
|
+
date: dateReplacer
|
|
507
|
+
};
|
|
508
|
+
var JSONRevivers = {
|
|
509
|
+
bigInt: bigIntReviver,
|
|
510
|
+
date: dateReviver
|
|
511
|
+
};
|
|
512
|
+
var jsonSerializer = (options) => {
|
|
513
|
+
const defaultReplacer = JSONReplacer(options);
|
|
514
|
+
const defaultReviver = JSONReviver(options);
|
|
515
|
+
return {
|
|
516
|
+
serialize: (object, serializerOptions) => JSON.stringify(
|
|
517
|
+
object,
|
|
518
|
+
serializerOptions ? JSONReplacer(serializerOptions) : defaultReplacer
|
|
519
|
+
),
|
|
520
|
+
deserialize: (payload, deserializerOptions) => JSON.parse(
|
|
521
|
+
payload,
|
|
522
|
+
deserializerOptions ? JSONReviver(deserializerOptions) : defaultReviver
|
|
523
|
+
)
|
|
524
|
+
};
|
|
525
|
+
};
|
|
526
|
+
var JSONSerializer = Object.assign(jsonSerializer(), {
|
|
527
|
+
from: (options) => _nullishCoalesce(_optionalChain([options, 'optionalAccess', _14 => _14.serialization, 'optionalAccess', _15 => _15.serializer]), () => ( (_optionalChain([options, 'optionalAccess', _16 => _16.serialization, 'optionalAccess', _17 => _17.options]) ? jsonSerializer(_optionalChain([options, 'optionalAccess', _18 => _18.serialization, 'optionalAccess', _19 => _19.options])) : JSONSerializer)))
|
|
528
|
+
});
|
|
529
|
+
var NoRetries = { retries: 0 };
|
|
530
|
+
var asyncRetry = async (fn, opts) => {
|
|
531
|
+
if (opts === void 0 || opts.retries === 0) return fn();
|
|
532
|
+
return _asyncretry2.default.call(void 0,
|
|
533
|
+
async (bail) => {
|
|
534
|
+
try {
|
|
535
|
+
const result = await fn();
|
|
536
|
+
if (_optionalChain([opts, 'optionalAccess', _20 => _20.shouldRetryResult]) && opts.shouldRetryResult(result)) {
|
|
537
|
+
throw new EmmettError(
|
|
538
|
+
`Retrying because of result: ${JSONSerializer.serialize(result)}`
|
|
539
|
+
);
|
|
540
|
+
}
|
|
541
|
+
return result;
|
|
542
|
+
} catch (error) {
|
|
543
|
+
if (_optionalChain([opts, 'optionalAccess', _21 => _21.shouldRetryError]) && !opts.shouldRetryError(error)) {
|
|
544
|
+
bail(error);
|
|
545
|
+
return void 0;
|
|
546
|
+
}
|
|
547
|
+
throw error;
|
|
548
|
+
}
|
|
549
|
+
},
|
|
550
|
+
_nullishCoalesce(opts, () => ( { retries: 0 }))
|
|
551
|
+
);
|
|
552
|
+
};
|
|
553
|
+
var onShutdown = (handler) => {
|
|
554
|
+
const signals = ["SIGTERM", "SIGINT"];
|
|
555
|
+
if (typeof process !== "undefined" && typeof process.on === "function") {
|
|
556
|
+
for (const signal of signals) {
|
|
557
|
+
process.on(signal, handler);
|
|
558
|
+
}
|
|
559
|
+
return () => {
|
|
560
|
+
for (const signal of signals) {
|
|
561
|
+
process.off(signal, handler);
|
|
562
|
+
}
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
const deno = globalThis.Deno;
|
|
566
|
+
if (deno && typeof deno.addSignalListener === "function") {
|
|
567
|
+
for (const signal of signals) {
|
|
568
|
+
deno.addSignalListener(signal, handler);
|
|
569
|
+
}
|
|
570
|
+
return () => {
|
|
571
|
+
for (const signal of signals) {
|
|
572
|
+
deno.removeSignalListener(signal, handler);
|
|
573
|
+
}
|
|
574
|
+
};
|
|
303
575
|
}
|
|
576
|
+
return () => {
|
|
577
|
+
};
|
|
304
578
|
};
|
|
305
579
|
var textEncoder = new TextEncoder();
|
|
580
|
+
var getCheckpoint = (message2) => {
|
|
581
|
+
return message2.metadata.checkpoint;
|
|
582
|
+
};
|
|
583
|
+
var wasMessageHandled = (message2, checkpoint) => {
|
|
584
|
+
const messageCheckpoint = getCheckpoint(message2);
|
|
585
|
+
return messageCheckpoint !== null && messageCheckpoint !== void 0 && checkpoint !== null && checkpoint !== void 0 && messageCheckpoint <= checkpoint;
|
|
586
|
+
};
|
|
587
|
+
var MessageProcessorType = {
|
|
588
|
+
PROJECTOR: "projector",
|
|
589
|
+
REACTOR: "reactor"
|
|
590
|
+
};
|
|
591
|
+
var defaultProcessingMessageProcessingScope = (handler, partialContext) => handler(partialContext);
|
|
592
|
+
var bigIntProcessorCheckpoint = (value) => bigInt.toNormalizedString(value);
|
|
593
|
+
var parseBigIntProcessorCheckpoint = (value) => BigInt(value);
|
|
594
|
+
var defaultProcessorVersion = 1;
|
|
595
|
+
var defaultProcessorPartition = defaultTag;
|
|
596
|
+
var getProcessorInstanceId = (processorId) => `${processorId}:${_uuid.v7.call(void 0, )}`;
|
|
597
|
+
var getProjectorId = (options) => `emt:processor:projector:${options.projectionName}`;
|
|
598
|
+
var reactor = (options) => {
|
|
599
|
+
const {
|
|
600
|
+
checkpoints,
|
|
601
|
+
processorId,
|
|
602
|
+
processorInstanceId: instanceId = getProcessorInstanceId(processorId),
|
|
603
|
+
type = MessageProcessorType.REACTOR,
|
|
604
|
+
version = defaultProcessorVersion,
|
|
605
|
+
partition = defaultProcessorPartition,
|
|
606
|
+
hooks = {},
|
|
607
|
+
processingScope = defaultProcessingMessageProcessingScope,
|
|
608
|
+
startFrom,
|
|
609
|
+
canHandle,
|
|
610
|
+
stopAfter
|
|
611
|
+
} = options;
|
|
612
|
+
const eachMessage = "eachMessage" in options && options.eachMessage ? options.eachMessage : () => Promise.resolve();
|
|
613
|
+
let isInitiated = false;
|
|
614
|
+
let isActive = false;
|
|
615
|
+
let lastCheckpoint = null;
|
|
616
|
+
let closeSignal = null;
|
|
617
|
+
const init = async (initOptions) => {
|
|
618
|
+
if (isInitiated) return;
|
|
619
|
+
if (hooks.onInit === void 0) {
|
|
620
|
+
isInitiated = true;
|
|
621
|
+
return;
|
|
622
|
+
}
|
|
623
|
+
return await processingScope(async (context) => {
|
|
624
|
+
await hooks.onInit(context);
|
|
625
|
+
isInitiated = true;
|
|
626
|
+
}, initOptions);
|
|
627
|
+
};
|
|
628
|
+
const close = async (closeOptions) => {
|
|
629
|
+
isActive = false;
|
|
630
|
+
if (closeSignal) {
|
|
631
|
+
closeSignal();
|
|
632
|
+
closeSignal = null;
|
|
633
|
+
}
|
|
634
|
+
if (hooks.onClose) {
|
|
635
|
+
await processingScope(hooks.onClose, closeOptions);
|
|
636
|
+
}
|
|
637
|
+
};
|
|
638
|
+
return {
|
|
639
|
+
// TODO: Consider whether not make it optional or add URN prefix
|
|
640
|
+
id: processorId,
|
|
641
|
+
instanceId,
|
|
642
|
+
type,
|
|
643
|
+
canHandle,
|
|
644
|
+
init,
|
|
645
|
+
start: async (startOptions) => {
|
|
646
|
+
if (isActive) return;
|
|
647
|
+
await init(startOptions);
|
|
648
|
+
isActive = true;
|
|
649
|
+
closeSignal = onShutdown(() => close(startOptions));
|
|
650
|
+
if (lastCheckpoint !== null)
|
|
651
|
+
return {
|
|
652
|
+
lastCheckpoint
|
|
653
|
+
};
|
|
654
|
+
return await processingScope(async (context) => {
|
|
655
|
+
if (hooks.onStart) {
|
|
656
|
+
await hooks.onStart(context);
|
|
657
|
+
}
|
|
658
|
+
if (startFrom && startFrom !== "CURRENT") return startFrom;
|
|
659
|
+
if (checkpoints) {
|
|
660
|
+
const readResult = await _optionalChain([checkpoints, 'optionalAccess', _22 => _22.read, 'call', _23 => _23(
|
|
661
|
+
{
|
|
662
|
+
processorId,
|
|
663
|
+
partition
|
|
664
|
+
},
|
|
665
|
+
{ ...startOptions, ...context }
|
|
666
|
+
)]);
|
|
667
|
+
lastCheckpoint = readResult.lastCheckpoint;
|
|
668
|
+
}
|
|
669
|
+
if (lastCheckpoint === null) return "BEGINNING";
|
|
670
|
+
return {
|
|
671
|
+
lastCheckpoint
|
|
672
|
+
};
|
|
673
|
+
}, startOptions);
|
|
674
|
+
},
|
|
675
|
+
close,
|
|
676
|
+
get isActive() {
|
|
677
|
+
return isActive;
|
|
678
|
+
},
|
|
679
|
+
handle: async (messages, partialContext) => {
|
|
680
|
+
if (!isActive) return Promise.resolve();
|
|
681
|
+
return await processingScope(async (context) => {
|
|
682
|
+
let result = void 0;
|
|
683
|
+
for (const message2 of messages) {
|
|
684
|
+
if (wasMessageHandled(message2, lastCheckpoint)) continue;
|
|
685
|
+
const upcasted = upcastRecordedMessage(
|
|
686
|
+
// TODO: Make it smarter
|
|
687
|
+
message2,
|
|
688
|
+
_optionalChain([options, 'access', _24 => _24.messageOptions, 'optionalAccess', _25 => _25.schema, 'optionalAccess', _26 => _26.versioning])
|
|
689
|
+
);
|
|
690
|
+
if (canHandle !== void 0 && !canHandle.includes(upcasted.type))
|
|
691
|
+
continue;
|
|
692
|
+
const messageProcessingResult = await eachMessage(upcasted, context);
|
|
693
|
+
if (checkpoints) {
|
|
694
|
+
const storeCheckpointResult = await checkpoints.store(
|
|
695
|
+
{
|
|
696
|
+
processorId,
|
|
697
|
+
version,
|
|
698
|
+
message: upcasted,
|
|
699
|
+
lastCheckpoint,
|
|
700
|
+
partition
|
|
701
|
+
},
|
|
702
|
+
context
|
|
703
|
+
);
|
|
704
|
+
if (storeCheckpointResult.success) {
|
|
705
|
+
lastCheckpoint = storeCheckpointResult.newCheckpoint;
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
if (messageProcessingResult && messageProcessingResult.type === "STOP") {
|
|
709
|
+
isActive = false;
|
|
710
|
+
result = messageProcessingResult;
|
|
711
|
+
break;
|
|
712
|
+
}
|
|
713
|
+
if (stopAfter && stopAfter(upcasted)) {
|
|
714
|
+
isActive = false;
|
|
715
|
+
result = { type: "STOP", reason: "Stop condition reached" };
|
|
716
|
+
break;
|
|
717
|
+
}
|
|
718
|
+
if (messageProcessingResult && messageProcessingResult.type === "SKIP")
|
|
719
|
+
continue;
|
|
720
|
+
}
|
|
721
|
+
return result;
|
|
722
|
+
}, partialContext);
|
|
723
|
+
}
|
|
724
|
+
};
|
|
725
|
+
};
|
|
726
|
+
var projector = (options) => {
|
|
727
|
+
const {
|
|
728
|
+
projection: projection2,
|
|
729
|
+
processorId = getProjectorId({
|
|
730
|
+
projectionName: _nullishCoalesce(projection2.name, () => ( "unknown"))
|
|
731
|
+
}),
|
|
732
|
+
...rest
|
|
733
|
+
} = options;
|
|
734
|
+
return reactor({
|
|
735
|
+
...rest,
|
|
736
|
+
type: MessageProcessorType.PROJECTOR,
|
|
737
|
+
canHandle: projection2.canHandle,
|
|
738
|
+
processorId,
|
|
739
|
+
messageOptions: options.projection.eventsOptions,
|
|
740
|
+
hooks: {
|
|
741
|
+
onInit: _optionalChain([options, 'access', _27 => _27.hooks, 'optionalAccess', _28 => _28.onInit]),
|
|
742
|
+
onStart: options.truncateOnStart && options.projection.truncate || _optionalChain([options, 'access', _29 => _29.hooks, 'optionalAccess', _30 => _30.onStart]) ? async (context) => {
|
|
743
|
+
if (options.truncateOnStart && options.projection.truncate)
|
|
744
|
+
await options.projection.truncate(context);
|
|
745
|
+
if (_optionalChain([options, 'access', _31 => _31.hooks, 'optionalAccess', _32 => _32.onStart])) await _optionalChain([options, 'access', _33 => _33.hooks, 'optionalAccess', _34 => _34.onStart, 'call', _35 => _35(context)]);
|
|
746
|
+
} : void 0,
|
|
747
|
+
onClose: _optionalChain([options, 'access', _36 => _36.hooks, 'optionalAccess', _37 => _37.onClose])
|
|
748
|
+
},
|
|
749
|
+
eachMessage: async (event2, context) => projection2.handle([event2], context)
|
|
750
|
+
});
|
|
751
|
+
};
|
|
306
752
|
var AssertionError = class extends Error {
|
|
307
753
|
constructor(message2) {
|
|
308
754
|
super(message2);
|
|
@@ -314,7 +760,7 @@ var isSubset = (superObj, subObj) => {
|
|
|
314
760
|
assertOk(sup);
|
|
315
761
|
assertOk(sub);
|
|
316
762
|
return Object.keys(sub).every((ele) => {
|
|
317
|
-
if (typeof sub[ele] == "object") {
|
|
763
|
+
if (sub[ele] !== null && typeof sub[ele] == "object") {
|
|
318
764
|
return isSubset(sup[ele], sub[ele]);
|
|
319
765
|
}
|
|
320
766
|
return sub[ele] === sup[ele];
|
|
@@ -323,6 +769,15 @@ var isSubset = (superObj, subObj) => {
|
|
|
323
769
|
var assertFails = (message2) => {
|
|
324
770
|
throw new AssertionError(_nullishCoalesce(message2, () => ( "That should not ever happened, right?")));
|
|
325
771
|
};
|
|
772
|
+
var assertDeepEqual = (actual, expected, message2) => {
|
|
773
|
+
if (!deepEquals(actual, expected))
|
|
774
|
+
throw new AssertionError(
|
|
775
|
+
_nullishCoalesce(message2, () => ( `subObj:
|
|
776
|
+
${JSONSerializer.serialize(expected)}
|
|
777
|
+
is not equal to
|
|
778
|
+
${JSONSerializer.serialize(actual)}`))
|
|
779
|
+
);
|
|
780
|
+
};
|
|
326
781
|
function assertTrue(condition, message2) {
|
|
327
782
|
if (condition !== true)
|
|
328
783
|
throw new AssertionError(_nullishCoalesce(message2, () => ( `Condition is false`)));
|
|
@@ -334,22 +789,29 @@ function assertEqual(expected, actual, message2) {
|
|
|
334
789
|
if (expected !== actual)
|
|
335
790
|
throw new AssertionError(
|
|
336
791
|
`${_nullishCoalesce(message2, () => ( "Objects are not equal"))}:
|
|
337
|
-
Expected: ${
|
|
338
|
-
Actual: ${
|
|
792
|
+
Expected: ${JSONSerializer.serialize(expected)}
|
|
793
|
+
Actual: ${JSONSerializer.serialize(actual)}`
|
|
339
794
|
);
|
|
340
795
|
}
|
|
341
796
|
function assertNotEqual(obj, other, message2) {
|
|
342
797
|
if (obj === other)
|
|
343
798
|
throw new AssertionError(
|
|
344
|
-
_nullishCoalesce(message2, () => ( `Objects are equal: ${
|
|
799
|
+
_nullishCoalesce(message2, () => ( `Objects are equal: ${JSONSerializer.serialize(obj)}`))
|
|
345
800
|
);
|
|
346
801
|
}
|
|
802
|
+
function assertIsNotNull(result) {
|
|
803
|
+
assertNotEqual(result, null);
|
|
804
|
+
assertOk(result);
|
|
805
|
+
}
|
|
806
|
+
function assertIsNull(result) {
|
|
807
|
+
assertEqual(result, null);
|
|
808
|
+
}
|
|
347
809
|
var assertThatArray = (array) => {
|
|
348
810
|
return {
|
|
349
811
|
isEmpty: () => assertEqual(
|
|
350
812
|
array.length,
|
|
351
813
|
0,
|
|
352
|
-
`Array is not empty ${
|
|
814
|
+
`Array is not empty ${JSONSerializer.serialize(array)}`
|
|
353
815
|
),
|
|
354
816
|
isNotEmpty: () => assertNotEqual(array.length, 0, `Array is empty`),
|
|
355
817
|
hasSize: (length) => assertEqual(array.length, length),
|
|
@@ -406,7 +868,7 @@ var assertThatArray = (array) => {
|
|
|
406
868
|
};
|
|
407
869
|
};
|
|
408
870
|
var downcastRecordedMessage = (recordedMessage, options) => {
|
|
409
|
-
if (!_optionalChain([options, 'optionalAccess',
|
|
871
|
+
if (!_optionalChain([options, 'optionalAccess', _38 => _38.downcast]))
|
|
410
872
|
return recordedMessage;
|
|
411
873
|
const downcasted = options.downcast(
|
|
412
874
|
recordedMessage
|
|
@@ -424,14 +886,14 @@ var downcastRecordedMessage = (recordedMessage, options) => {
|
|
|
424
886
|
};
|
|
425
887
|
};
|
|
426
888
|
var downcastRecordedMessages = (recordedMessages, options) => {
|
|
427
|
-
if (!_optionalChain([options, 'optionalAccess',
|
|
889
|
+
if (!_optionalChain([options, 'optionalAccess', _39 => _39.downcast]))
|
|
428
890
|
return recordedMessages;
|
|
429
891
|
return recordedMessages.map(
|
|
430
892
|
(recordedMessage) => downcastRecordedMessage(recordedMessage, options)
|
|
431
893
|
);
|
|
432
894
|
};
|
|
433
895
|
var upcastRecordedMessage = (recordedMessage, options) => {
|
|
434
|
-
if (!_optionalChain([options, 'optionalAccess',
|
|
896
|
+
if (!_optionalChain([options, 'optionalAccess', _40 => _40.upcast]))
|
|
435
897
|
return recordedMessage;
|
|
436
898
|
const upcasted = options.upcast(
|
|
437
899
|
recordedMessage
|
|
@@ -448,56 +910,467 @@ var upcastRecordedMessage = (recordedMessage, options) => {
|
|
|
448
910
|
} : {}
|
|
449
911
|
};
|
|
450
912
|
};
|
|
451
|
-
var getCheckpoint = (message2) => {
|
|
452
|
-
return "checkpoint" in message2.metadata ? (
|
|
453
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
454
|
-
message2.metadata.checkpoint
|
|
455
|
-
) : "globalPosition" in message2.metadata && // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
456
|
-
isBigint(message2.metadata.globalPosition) ? (
|
|
457
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
458
|
-
message2.metadata.globalPosition
|
|
459
|
-
) : "streamPosition" in message2.metadata && // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
460
|
-
isBigint(message2.metadata.streamPosition) ? (
|
|
461
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
462
|
-
message2.metadata.streamPosition
|
|
463
|
-
) : null;
|
|
464
|
-
};
|
|
465
913
|
var projection = (definition) => definition;
|
|
914
|
+
var WorkflowHandlerStreamVersionConflictRetryOptions = {
|
|
915
|
+
retries: 3,
|
|
916
|
+
minTimeout: 100,
|
|
917
|
+
factor: 1.5,
|
|
918
|
+
shouldRetryError: isExpectedVersionConflictError
|
|
919
|
+
};
|
|
920
|
+
var fromWorkflowHandlerRetryOptions = (retryOptions) => {
|
|
921
|
+
if (retryOptions === void 0) return NoRetries;
|
|
922
|
+
if ("onVersionConflict" in retryOptions) {
|
|
923
|
+
if (typeof retryOptions.onVersionConflict === "boolean")
|
|
924
|
+
return WorkflowHandlerStreamVersionConflictRetryOptions;
|
|
925
|
+
else if (typeof retryOptions.onVersionConflict === "number")
|
|
926
|
+
return {
|
|
927
|
+
...WorkflowHandlerStreamVersionConflictRetryOptions,
|
|
928
|
+
retries: retryOptions.onVersionConflict
|
|
929
|
+
};
|
|
930
|
+
else return retryOptions.onVersionConflict;
|
|
931
|
+
}
|
|
932
|
+
return retryOptions;
|
|
933
|
+
};
|
|
934
|
+
var emptyHandlerResult = (nextExpectedStreamVersion = 0n) => ({
|
|
935
|
+
newMessages: [],
|
|
936
|
+
createdNewStream: false,
|
|
937
|
+
nextExpectedStreamVersion
|
|
938
|
+
});
|
|
939
|
+
var createInputMetadata = (originalMessageId, action) => ({
|
|
940
|
+
originalMessageId,
|
|
941
|
+
input: true,
|
|
942
|
+
action
|
|
943
|
+
});
|
|
944
|
+
var tagOutputMessage = (msg, action) => {
|
|
945
|
+
const existingMetadata = "metadata" in msg && msg.metadata ? msg.metadata : {};
|
|
946
|
+
return {
|
|
947
|
+
...msg,
|
|
948
|
+
metadata: {
|
|
949
|
+
...existingMetadata,
|
|
950
|
+
action
|
|
951
|
+
}
|
|
952
|
+
};
|
|
953
|
+
};
|
|
954
|
+
var createWrappedInitialState = (initialState) => {
|
|
955
|
+
return () => ({
|
|
956
|
+
userState: initialState(),
|
|
957
|
+
processedInputIds: /* @__PURE__ */ new Set()
|
|
958
|
+
});
|
|
959
|
+
};
|
|
960
|
+
var createWrappedEvolve = (evolve, workflowName, separateInputInboxFromProcessing) => {
|
|
961
|
+
return (state, event2) => {
|
|
962
|
+
const metadata = event2.metadata;
|
|
963
|
+
let processedInputIds = state.processedInputIds;
|
|
964
|
+
if (_optionalChain([metadata, 'optionalAccess', _41 => _41.input]) === true && typeof _optionalChain([metadata, 'optionalAccess', _42 => _42.originalMessageId]) === "string") {
|
|
965
|
+
processedInputIds = new Set(state.processedInputIds);
|
|
966
|
+
processedInputIds.add(metadata.originalMessageId);
|
|
967
|
+
}
|
|
968
|
+
if (separateInputInboxFromProcessing && _optionalChain([metadata, 'optionalAccess', _43 => _43.input]) === true) {
|
|
969
|
+
return {
|
|
970
|
+
userState: state.userState,
|
|
971
|
+
processedInputIds
|
|
972
|
+
};
|
|
973
|
+
}
|
|
974
|
+
const eventType = event2.type;
|
|
975
|
+
const eventForEvolve = eventType.startsWith(`${workflowName}:`) ? {
|
|
976
|
+
...event2,
|
|
977
|
+
type: eventType.replace(`${workflowName}:`, "")
|
|
978
|
+
} : event2;
|
|
979
|
+
return {
|
|
980
|
+
userState: evolve(state.userState, eventForEvolve),
|
|
981
|
+
processedInputIds
|
|
982
|
+
};
|
|
983
|
+
};
|
|
984
|
+
};
|
|
985
|
+
var workflowStreamName = ({
|
|
986
|
+
workflowName,
|
|
987
|
+
workflowId
|
|
988
|
+
}) => `emt:workflow:${workflowName}:${workflowId}`;
|
|
989
|
+
var WorkflowHandler = (options) => async (store, message2, handleOptions) => asyncRetry(
|
|
990
|
+
async () => {
|
|
991
|
+
const result = await withSession2(store, async ({ eventStore }) => {
|
|
992
|
+
const {
|
|
993
|
+
workflow: { evolve, initialState, decide, name: workflowName },
|
|
994
|
+
getWorkflowId: getWorkflowId2
|
|
995
|
+
} = options;
|
|
996
|
+
const inputMessageId = (
|
|
997
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
998
|
+
_nullishCoalesce(("metadata" in message2 && _optionalChain([message2, 'access', _44 => _44.metadata, 'optionalAccess', _45 => _45.messageId]) ? (
|
|
999
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
1000
|
+
message2.metadata.messageId
|
|
1001
|
+
) : void 0), () => ( _uuid.v7.call(void 0, )))
|
|
1002
|
+
);
|
|
1003
|
+
const messageWithMetadata = {
|
|
1004
|
+
...message2,
|
|
1005
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
1006
|
+
metadata: {
|
|
1007
|
+
messageId: inputMessageId,
|
|
1008
|
+
...message2.metadata
|
|
1009
|
+
}
|
|
1010
|
+
};
|
|
1011
|
+
const workflowId = getWorkflowId2(messageWithMetadata);
|
|
1012
|
+
if (!workflowId) {
|
|
1013
|
+
return emptyHandlerResult();
|
|
1014
|
+
}
|
|
1015
|
+
const streamName = options.mapWorkflowId ? options.mapWorkflowId(workflowId) : workflowStreamName({ workflowName, workflowId });
|
|
1016
|
+
const messageType = messageWithMetadata.type;
|
|
1017
|
+
const hasWorkflowPrefix = messageType.startsWith(`${workflowName}:`);
|
|
1018
|
+
if (options.separateInputInboxFromProcessing && !hasWorkflowPrefix) {
|
|
1019
|
+
const inputMetadata2 = createInputMetadata(
|
|
1020
|
+
inputMessageId,
|
|
1021
|
+
"InitiatedBy"
|
|
1022
|
+
);
|
|
1023
|
+
const inputToStore2 = {
|
|
1024
|
+
type: `${workflowName}:${messageWithMetadata.type}`,
|
|
1025
|
+
data: messageWithMetadata.data,
|
|
1026
|
+
kind: messageWithMetadata.kind,
|
|
1027
|
+
metadata: inputMetadata2
|
|
1028
|
+
};
|
|
1029
|
+
const appendResult2 = await eventStore.appendToStream(
|
|
1030
|
+
streamName,
|
|
1031
|
+
[inputToStore2],
|
|
1032
|
+
{
|
|
1033
|
+
...handleOptions,
|
|
1034
|
+
expectedStreamVersion: _nullishCoalesce(_optionalChain([handleOptions, 'optionalAccess', _46 => _46.expectedStreamVersion]), () => ( NO_CONCURRENCY_CHECK))
|
|
1035
|
+
}
|
|
1036
|
+
);
|
|
1037
|
+
return {
|
|
1038
|
+
...appendResult2,
|
|
1039
|
+
newMessages: []
|
|
1040
|
+
};
|
|
1041
|
+
}
|
|
1042
|
+
const wrappedInitialState = createWrappedInitialState(initialState);
|
|
1043
|
+
const wrappedEvolve = createWrappedEvolve(
|
|
1044
|
+
evolve,
|
|
1045
|
+
workflowName,
|
|
1046
|
+
_nullishCoalesce(options.separateInputInboxFromProcessing, () => ( false))
|
|
1047
|
+
);
|
|
1048
|
+
const aggregationResult = await eventStore.aggregateStream(streamName, {
|
|
1049
|
+
evolve: wrappedEvolve,
|
|
1050
|
+
initialState: wrappedInitialState,
|
|
1051
|
+
read: {
|
|
1052
|
+
...handleOptions,
|
|
1053
|
+
// expected stream version is passed to fail fast
|
|
1054
|
+
// if stream is in the wrong state
|
|
1055
|
+
expectedStreamVersion: _nullishCoalesce(_optionalChain([handleOptions, 'optionalAccess', _47 => _47.expectedStreamVersion]), () => ( NO_CONCURRENCY_CHECK))
|
|
1056
|
+
}
|
|
1057
|
+
});
|
|
1058
|
+
const { currentStreamVersion } = aggregationResult;
|
|
1059
|
+
const { userState: state, processedInputIds } = aggregationResult.state;
|
|
1060
|
+
if (processedInputIds.has(inputMessageId)) {
|
|
1061
|
+
return emptyHandlerResult(currentStreamVersion);
|
|
1062
|
+
}
|
|
1063
|
+
const messageForDecide = hasWorkflowPrefix ? {
|
|
1064
|
+
...messageWithMetadata,
|
|
1065
|
+
type: messageType.replace(`${workflowName}:`, "")
|
|
1066
|
+
} : messageWithMetadata;
|
|
1067
|
+
const result2 = decide(messageForDecide, state);
|
|
1068
|
+
const inputMetadata = createInputMetadata(
|
|
1069
|
+
inputMessageId,
|
|
1070
|
+
aggregationResult.streamExists ? "Received" : "InitiatedBy"
|
|
1071
|
+
);
|
|
1072
|
+
const inputToStore = {
|
|
1073
|
+
type: `${workflowName}:${messageWithMetadata.type}`,
|
|
1074
|
+
data: messageWithMetadata.data,
|
|
1075
|
+
kind: messageWithMetadata.kind,
|
|
1076
|
+
metadata: inputMetadata
|
|
1077
|
+
};
|
|
1078
|
+
const outputMessages = (Array.isArray(result2) ? result2 : [result2]).filter((msg) => msg !== void 0 && msg !== null);
|
|
1079
|
+
const outputCommandTypes = _nullishCoalesce(_optionalChain([options, 'access', _48 => _48.outputs, 'optionalAccess', _49 => _49.commands]), () => ( []));
|
|
1080
|
+
const taggedOutputMessages = outputMessages.map((msg) => {
|
|
1081
|
+
const action = outputCommandTypes.includes(
|
|
1082
|
+
msg.type
|
|
1083
|
+
) ? "Sent" : "Published";
|
|
1084
|
+
return tagOutputMessage(msg, action);
|
|
1085
|
+
});
|
|
1086
|
+
const messagesToAppend = options.separateInputInboxFromProcessing && hasWorkflowPrefix ? [...taggedOutputMessages] : [inputToStore, ...taggedOutputMessages];
|
|
1087
|
+
if (messagesToAppend.length === 0) {
|
|
1088
|
+
return emptyHandlerResult(currentStreamVersion);
|
|
1089
|
+
}
|
|
1090
|
+
const expectedStreamVersion = _nullishCoalesce(_optionalChain([handleOptions, 'optionalAccess', _50 => _50.expectedStreamVersion]), () => ( (aggregationResult.streamExists ? currentStreamVersion : STREAM_DOES_NOT_EXIST)));
|
|
1091
|
+
const appendResult = await eventStore.appendToStream(
|
|
1092
|
+
streamName,
|
|
1093
|
+
// TODO: Fix this cast
|
|
1094
|
+
messagesToAppend,
|
|
1095
|
+
{
|
|
1096
|
+
...handleOptions,
|
|
1097
|
+
expectedStreamVersion
|
|
1098
|
+
}
|
|
1099
|
+
);
|
|
1100
|
+
return {
|
|
1101
|
+
...appendResult,
|
|
1102
|
+
newMessages: outputMessages
|
|
1103
|
+
};
|
|
1104
|
+
});
|
|
1105
|
+
return result;
|
|
1106
|
+
},
|
|
1107
|
+
fromWorkflowHandlerRetryOptions(
|
|
1108
|
+
handleOptions && "retry" in handleOptions ? handleOptions.retry : options.retry
|
|
1109
|
+
)
|
|
1110
|
+
);
|
|
1111
|
+
var withSession2 = (eventStore, callback) => {
|
|
1112
|
+
const sessionFactory = canCreateEventStoreSession(eventStore) ? eventStore : nulloSessionFactory(eventStore);
|
|
1113
|
+
return sessionFactory.withSession(callback);
|
|
1114
|
+
};
|
|
1115
|
+
var getWorkflowId = (options) => `emt:processor:workflow:${options.workflowName}`;
|
|
1116
|
+
var workflowProcessor = (options) => {
|
|
1117
|
+
const { workflow, ...rest } = options;
|
|
1118
|
+
const inputs = [...options.inputs.commands, ...options.inputs.events];
|
|
1119
|
+
let canHandle = inputs;
|
|
1120
|
+
if (options.separateInputInboxFromProcessing)
|
|
1121
|
+
canHandle = [
|
|
1122
|
+
...canHandle,
|
|
1123
|
+
...options.inputs.commands.map((t) => `${workflow.name}:${t}`),
|
|
1124
|
+
...options.inputs.events.map((t) => `${workflow.name}:${t}`)
|
|
1125
|
+
];
|
|
1126
|
+
if (options.outputHandler)
|
|
1127
|
+
canHandle = [...canHandle, ...options.outputHandler.canHandle];
|
|
1128
|
+
const handle = WorkflowHandler(options);
|
|
1129
|
+
return reactor({
|
|
1130
|
+
...rest,
|
|
1131
|
+
processorId: _nullishCoalesce(options.processorId, () => ( getWorkflowId({ workflowName: workflow.name }))),
|
|
1132
|
+
canHandle,
|
|
1133
|
+
type: MessageProcessorType.PROJECTOR,
|
|
1134
|
+
eachMessage: async (message2, context) => {
|
|
1135
|
+
const messageType = message2.type;
|
|
1136
|
+
const metadata = message2.metadata;
|
|
1137
|
+
const isInput = _optionalChain([metadata, 'optionalAccess', _51 => _51.input]) === true;
|
|
1138
|
+
if (isInput || inputs.includes(messageType)) {
|
|
1139
|
+
const result = await handle(
|
|
1140
|
+
context.connection.messageStore,
|
|
1141
|
+
message2,
|
|
1142
|
+
context
|
|
1143
|
+
);
|
|
1144
|
+
if (options.stopAfter && result.newMessages.length > 0) {
|
|
1145
|
+
for (const outputMessage of result.newMessages) {
|
|
1146
|
+
if (options.stopAfter(
|
|
1147
|
+
outputMessage
|
|
1148
|
+
)) {
|
|
1149
|
+
return { type: "STOP", reason: "Stop condition reached" };
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
return;
|
|
1154
|
+
}
|
|
1155
|
+
if (_optionalChain([options, 'access', _52 => _52.outputHandler, 'optionalAccess', _53 => _53.canHandle, 'access', _54 => _54.includes, 'call', _55 => _55(messageType)]) === true) {
|
|
1156
|
+
const handledOutputMessages = await options.outputHandler.handle(
|
|
1157
|
+
message2,
|
|
1158
|
+
context
|
|
1159
|
+
);
|
|
1160
|
+
if (handledOutputMessages instanceof EmmettError) {
|
|
1161
|
+
return {
|
|
1162
|
+
type: "STOP",
|
|
1163
|
+
reason: "Routing error",
|
|
1164
|
+
error: handledOutputMessages
|
|
1165
|
+
};
|
|
1166
|
+
}
|
|
1167
|
+
const messagesToAppend = Array.isArray(handledOutputMessages) ? handledOutputMessages : handledOutputMessages ? [handledOutputMessages] : [];
|
|
1168
|
+
if (messagesToAppend.length === 0) {
|
|
1169
|
+
return;
|
|
1170
|
+
}
|
|
1171
|
+
const workflowId = options.getWorkflowId(
|
|
1172
|
+
message2
|
|
1173
|
+
);
|
|
1174
|
+
if (!workflowId) return;
|
|
1175
|
+
const streamName = options.mapWorkflowId ? options.mapWorkflowId(workflowId) : workflowStreamName({
|
|
1176
|
+
workflowName: workflow.name,
|
|
1177
|
+
workflowId
|
|
1178
|
+
});
|
|
1179
|
+
await context.connection.messageStore.appendToStream(
|
|
1180
|
+
streamName,
|
|
1181
|
+
messagesToAppend
|
|
1182
|
+
);
|
|
1183
|
+
return;
|
|
1184
|
+
}
|
|
1185
|
+
return;
|
|
1186
|
+
}
|
|
1187
|
+
});
|
|
1188
|
+
};
|
|
1189
|
+
|
|
1190
|
+
// src/eventStore/projections/pongo/pongoProjectionSpec.ts
|
|
1191
|
+
|
|
1192
|
+
|
|
1193
|
+
|
|
1194
|
+
var withCollection = async (handle, options) => {
|
|
1195
|
+
const { connection, inDatabase, inCollection } = options;
|
|
1196
|
+
const driver = await pongoDriverRegistry.tryResolve(
|
|
1197
|
+
connection.driverType
|
|
1198
|
+
);
|
|
1199
|
+
const pongo = _pongo.pongoClient.call(void 0, {
|
|
1200
|
+
connectionOptions: { connection },
|
|
1201
|
+
driver
|
|
1202
|
+
});
|
|
1203
|
+
try {
|
|
1204
|
+
const collection = pongo.db(inDatabase).collection(inCollection);
|
|
1205
|
+
return handle(collection);
|
|
1206
|
+
} finally {
|
|
1207
|
+
await pongo.close();
|
|
1208
|
+
}
|
|
1209
|
+
};
|
|
1210
|
+
var withoutIdAndVersion = (doc) => {
|
|
1211
|
+
const { _id, _version, ...without } = doc;
|
|
1212
|
+
return without;
|
|
1213
|
+
};
|
|
1214
|
+
var assertDocumentsEqual = (actual, expected) => {
|
|
1215
|
+
if ("_id" in expected)
|
|
1216
|
+
assertEqual(
|
|
1217
|
+
expected._id,
|
|
1218
|
+
actual._id,
|
|
1219
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
1220
|
+
`Document ids are not matching! Expected: ${expected._id}, Actual: ${actual._id}`
|
|
1221
|
+
);
|
|
1222
|
+
return assertDeepEqual(
|
|
1223
|
+
withoutIdAndVersion(actual),
|
|
1224
|
+
withoutIdAndVersion(expected)
|
|
1225
|
+
);
|
|
1226
|
+
};
|
|
1227
|
+
var documentExists = (document, options) => (assertOptions) => withCollection(
|
|
1228
|
+
async (collection) => {
|
|
1229
|
+
const result = await collection.findOne(
|
|
1230
|
+
"withId" in options ? { _id: options.withId } : options.matchingFilter
|
|
1231
|
+
);
|
|
1232
|
+
assertIsNotNull(result);
|
|
1233
|
+
assertDocumentsEqual(result, document);
|
|
1234
|
+
},
|
|
1235
|
+
{ ...options, ...assertOptions }
|
|
1236
|
+
);
|
|
1237
|
+
var documentsAreTheSame = (documents, options) => (assertOptions) => withCollection(
|
|
1238
|
+
async (collection) => {
|
|
1239
|
+
const result = await collection.find(
|
|
1240
|
+
"withId" in options ? { _id: options.withId } : options.matchingFilter
|
|
1241
|
+
);
|
|
1242
|
+
assertEqual(
|
|
1243
|
+
documents.length,
|
|
1244
|
+
result.length,
|
|
1245
|
+
"Different Documents Count than expected"
|
|
1246
|
+
);
|
|
1247
|
+
for (let i = 0; i < documents.length; i++) {
|
|
1248
|
+
assertThatArray(result).contains(documents[i]);
|
|
1249
|
+
}
|
|
1250
|
+
},
|
|
1251
|
+
{ ...options, ...assertOptions }
|
|
1252
|
+
);
|
|
1253
|
+
var documentsMatchingHaveCount = (expectedCount, options) => (assertOptions) => withCollection(
|
|
1254
|
+
async (collection) => {
|
|
1255
|
+
const result = await collection.find(
|
|
1256
|
+
"withId" in options ? { _id: options.withId } : options.matchingFilter
|
|
1257
|
+
);
|
|
1258
|
+
assertEqual(
|
|
1259
|
+
expectedCount,
|
|
1260
|
+
result.length,
|
|
1261
|
+
"Different Documents Count than expected"
|
|
1262
|
+
);
|
|
1263
|
+
},
|
|
1264
|
+
{ ...options, ...assertOptions }
|
|
1265
|
+
);
|
|
1266
|
+
var documentMatchingExists = (options) => (assertOptions) => withCollection(
|
|
1267
|
+
async (collection) => {
|
|
1268
|
+
const result = await collection.find(
|
|
1269
|
+
"withId" in options ? { _id: options.withId } : options.matchingFilter
|
|
1270
|
+
);
|
|
1271
|
+
assertThatArray(result).isNotEmpty();
|
|
1272
|
+
},
|
|
1273
|
+
{ ...options, ...assertOptions }
|
|
1274
|
+
);
|
|
1275
|
+
var documentDoesNotExist = (options) => (assertOptions) => withCollection(
|
|
1276
|
+
async (collection) => {
|
|
1277
|
+
const result = await collection.findOne(
|
|
1278
|
+
"withId" in options ? { _id: options.withId } : options.matchingFilter
|
|
1279
|
+
);
|
|
1280
|
+
assertIsNull(result);
|
|
1281
|
+
},
|
|
1282
|
+
{ ...options, ...assertOptions }
|
|
1283
|
+
);
|
|
1284
|
+
var expectPongoDocuments = {
|
|
1285
|
+
fromCollection: (collectionName) => {
|
|
1286
|
+
return {
|
|
1287
|
+
withId: (id) => {
|
|
1288
|
+
return {
|
|
1289
|
+
toBeEqual: (document) => documentExists(document, {
|
|
1290
|
+
withId: id,
|
|
1291
|
+
inCollection: collectionName
|
|
1292
|
+
}),
|
|
1293
|
+
toExist: () => documentMatchingExists({
|
|
1294
|
+
withId: id,
|
|
1295
|
+
inCollection: collectionName
|
|
1296
|
+
}),
|
|
1297
|
+
notToExist: () => documentDoesNotExist({
|
|
1298
|
+
withId: id,
|
|
1299
|
+
inCollection: collectionName
|
|
1300
|
+
})
|
|
1301
|
+
};
|
|
1302
|
+
},
|
|
1303
|
+
matching: (filter) => {
|
|
1304
|
+
return {
|
|
1305
|
+
toBeTheSame: (documents) => documentsAreTheSame(documents, {
|
|
1306
|
+
matchingFilter: filter,
|
|
1307
|
+
inCollection: collectionName
|
|
1308
|
+
}),
|
|
1309
|
+
toHaveCount: (expectedCount) => documentsMatchingHaveCount(expectedCount, {
|
|
1310
|
+
matchingFilter: filter,
|
|
1311
|
+
inCollection: collectionName
|
|
1312
|
+
}),
|
|
1313
|
+
toExist: () => documentMatchingExists({
|
|
1314
|
+
matchingFilter: filter,
|
|
1315
|
+
inCollection: collectionName
|
|
1316
|
+
}),
|
|
1317
|
+
notToExist: () => documentDoesNotExist({
|
|
1318
|
+
matchingFilter: filter,
|
|
1319
|
+
inCollection: collectionName
|
|
1320
|
+
})
|
|
1321
|
+
};
|
|
1322
|
+
}
|
|
1323
|
+
};
|
|
1324
|
+
}
|
|
1325
|
+
};
|
|
466
1326
|
|
|
467
1327
|
// src/eventStore/projections/sqliteProjection.ts
|
|
468
1328
|
var handleProjections = async (options) => {
|
|
469
|
-
const {
|
|
1329
|
+
const {
|
|
1330
|
+
projections: allProjections,
|
|
1331
|
+
events,
|
|
1332
|
+
connection,
|
|
1333
|
+
execute,
|
|
1334
|
+
driverType
|
|
1335
|
+
} = options;
|
|
470
1336
|
const eventTypes = events.map((e) => e.type);
|
|
471
1337
|
for (const projection2 of allProjections) {
|
|
472
1338
|
if (!projection2.canHandle.some((type) => eventTypes.includes(type))) {
|
|
473
1339
|
continue;
|
|
474
1340
|
}
|
|
475
1341
|
await projection2.handle(events, {
|
|
476
|
-
connection
|
|
1342
|
+
connection,
|
|
1343
|
+
execute,
|
|
1344
|
+
driverType
|
|
477
1345
|
});
|
|
478
1346
|
}
|
|
479
1347
|
};
|
|
480
1348
|
var sqliteProjection = (definition) => projection(definition);
|
|
481
1349
|
var sqliteRawBatchSQLProjection = (options) => sqliteProjection({
|
|
1350
|
+
name: options.name,
|
|
1351
|
+
kind: _nullishCoalesce(options.kind, () => ( "emt:projections:sqlite:raw_sql:batch")),
|
|
1352
|
+
version: options.version,
|
|
482
1353
|
canHandle: options.canHandle,
|
|
1354
|
+
eventsOptions: options.eventsOptions,
|
|
483
1355
|
handle: async (events, context) => {
|
|
484
1356
|
const sqls = await options.evolve(events, context);
|
|
485
|
-
|
|
1357
|
+
await context.execute.batchCommand(sqls);
|
|
486
1358
|
},
|
|
487
1359
|
init: async (initOptions) => {
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
1360
|
+
const initSQL = options.init ? await options.init(initOptions) : void 0;
|
|
1361
|
+
if (initSQL) {
|
|
1362
|
+
if (Array.isArray(initSQL)) {
|
|
1363
|
+
await initOptions.context.execute.batchCommand(initSQL);
|
|
1364
|
+
} else {
|
|
1365
|
+
await initOptions.context.execute.command(initSQL);
|
|
1366
|
+
}
|
|
495
1367
|
}
|
|
496
1368
|
}
|
|
497
1369
|
});
|
|
498
1370
|
var sqliteRawSQLProjection = (options) => {
|
|
499
|
-
const { evolve, ...rest } = options;
|
|
1371
|
+
const { evolve, kind, ...rest } = options;
|
|
500
1372
|
return sqliteRawBatchSQLProjection({
|
|
1373
|
+
kind: _nullishCoalesce(kind, () => ( "emt:projections:sqlite:raw:_sql:single")),
|
|
501
1374
|
...rest,
|
|
502
1375
|
evolve: async (events, context) => {
|
|
503
1376
|
const sqls = [];
|
|
@@ -515,19 +1388,153 @@ var sqliteRawSQLProjection = (options) => {
|
|
|
515
1388
|
};
|
|
516
1389
|
|
|
517
1390
|
// src/eventStore/projections/sqliteProjectionSpec.ts
|
|
1391
|
+
var _dumbo = require('@event-driven-io/dumbo');
|
|
518
1392
|
|
|
1393
|
+
var SQLiteProjectionSpec = {
|
|
1394
|
+
for: (options) => {
|
|
1395
|
+
{
|
|
1396
|
+
const driverType = options.driver.driverType;
|
|
1397
|
+
const pool = _nullishCoalesce(options.pool, () => ( _dumbo.dumbo.call(void 0, {
|
|
1398
|
+
serialization: options.serialization,
|
|
1399
|
+
transactionOptions: {
|
|
1400
|
+
allowNestedTransactions: true,
|
|
1401
|
+
mode: "session_based"
|
|
1402
|
+
},
|
|
1403
|
+
...options.driver.mapToDumboOptions(options)
|
|
1404
|
+
})));
|
|
1405
|
+
const projection2 = options.projection;
|
|
1406
|
+
let wasInitialized = false;
|
|
1407
|
+
return (givenEvents) => {
|
|
1408
|
+
return {
|
|
1409
|
+
when: (events, options2) => {
|
|
1410
|
+
const allEvents = [];
|
|
1411
|
+
const run = async (connection) => {
|
|
1412
|
+
let globalPosition = 0n;
|
|
1413
|
+
const numberOfTimes = _nullishCoalesce(_optionalChain([options2, 'optionalAccess', _56 => _56.numberOfTimes]), () => ( 1));
|
|
1414
|
+
for (const event of [
|
|
1415
|
+
...givenEvents,
|
|
1416
|
+
...Array.from({ length: numberOfTimes }).flatMap(() => events)
|
|
1417
|
+
]) {
|
|
1418
|
+
const metadata = {
|
|
1419
|
+
checkpoint: bigIntProcessorCheckpoint(++globalPosition),
|
|
1420
|
+
globalPosition,
|
|
1421
|
+
streamPosition: globalPosition,
|
|
1422
|
+
streamName: `test-${_uuid.v4.call(void 0, )}`,
|
|
1423
|
+
messageId: _uuid.v4.call(void 0, )
|
|
1424
|
+
};
|
|
1425
|
+
allEvents.push({
|
|
1426
|
+
...event,
|
|
1427
|
+
kind: "Event",
|
|
1428
|
+
metadata: {
|
|
1429
|
+
...metadata,
|
|
1430
|
+
..."metadata" in event ? _nullishCoalesce(event.metadata, () => ( {})) : {}
|
|
1431
|
+
}
|
|
1432
|
+
});
|
|
1433
|
+
}
|
|
1434
|
+
if (!wasInitialized && projection2.init) {
|
|
1435
|
+
await projection2.init({
|
|
1436
|
+
registrationType: "async",
|
|
1437
|
+
status: "active",
|
|
1438
|
+
context: {
|
|
1439
|
+
execute: connection.execute,
|
|
1440
|
+
connection,
|
|
1441
|
+
driverType
|
|
1442
|
+
},
|
|
1443
|
+
version: _nullishCoalesce(projection2.version, () => ( 1))
|
|
1444
|
+
});
|
|
1445
|
+
wasInitialized = true;
|
|
1446
|
+
}
|
|
1447
|
+
await connection.withTransaction(
|
|
1448
|
+
() => handleProjections({
|
|
1449
|
+
events: allEvents,
|
|
1450
|
+
projections: [projection2],
|
|
1451
|
+
execute: connection.execute,
|
|
1452
|
+
connection,
|
|
1453
|
+
driverType
|
|
1454
|
+
})
|
|
1455
|
+
);
|
|
1456
|
+
};
|
|
1457
|
+
return {
|
|
1458
|
+
then: (assert, message) => pool.withConnection(async (connection) => {
|
|
1459
|
+
await run(connection);
|
|
1460
|
+
const succeeded = await assert({
|
|
1461
|
+
connection
|
|
1462
|
+
});
|
|
1463
|
+
if (succeeded !== void 0 && succeeded === false)
|
|
1464
|
+
assertFails(
|
|
1465
|
+
_nullishCoalesce(message, () => ( "Projection specification didn't match the criteria"))
|
|
1466
|
+
);
|
|
1467
|
+
}),
|
|
1468
|
+
thenThrows: (...args) => pool.withConnection(async (connection) => {
|
|
1469
|
+
try {
|
|
1470
|
+
await run(connection);
|
|
1471
|
+
throw new AssertionError(
|
|
1472
|
+
"Handler did not fail as expected"
|
|
1473
|
+
);
|
|
1474
|
+
} catch (error) {
|
|
1475
|
+
if (error instanceof AssertionError) throw error;
|
|
1476
|
+
if (args.length === 0) return;
|
|
1477
|
+
if (!isErrorConstructor(args[0])) {
|
|
1478
|
+
assertTrue(
|
|
1479
|
+
args[0](error),
|
|
1480
|
+
`Error didn't match the error condition: ${_optionalChain([error, 'optionalAccess', _57 => _57.toString, 'call', _58 => _58()])}`
|
|
1481
|
+
);
|
|
1482
|
+
return;
|
|
1483
|
+
}
|
|
1484
|
+
assertTrue(
|
|
1485
|
+
error instanceof args[0],
|
|
1486
|
+
`Caught error is not an instance of the expected type: ${_optionalChain([error, 'optionalAccess', _59 => _59.toString, 'call', _60 => _60()])}`
|
|
1487
|
+
);
|
|
1488
|
+
if (args[1]) {
|
|
1489
|
+
assertTrue(
|
|
1490
|
+
args[1](error),
|
|
1491
|
+
`Error didn't match the error condition: ${_optionalChain([error, 'optionalAccess', _61 => _61.toString, 'call', _62 => _62()])}`
|
|
1492
|
+
);
|
|
1493
|
+
}
|
|
1494
|
+
}
|
|
1495
|
+
})
|
|
1496
|
+
};
|
|
1497
|
+
}
|
|
1498
|
+
};
|
|
1499
|
+
};
|
|
1500
|
+
}
|
|
1501
|
+
}
|
|
1502
|
+
};
|
|
1503
|
+
var eventInStream = (streamName, event) => {
|
|
1504
|
+
return {
|
|
1505
|
+
...event,
|
|
1506
|
+
metadata: {
|
|
1507
|
+
..._nullishCoalesce(event.metadata, () => ( {})),
|
|
1508
|
+
streamName: _nullishCoalesce(_optionalChain([event, 'access', _63 => _63.metadata, 'optionalAccess', _64 => _64.streamName]), () => ( streamName))
|
|
1509
|
+
}
|
|
1510
|
+
};
|
|
1511
|
+
};
|
|
1512
|
+
var eventsInStream = (streamName, events) => {
|
|
1513
|
+
return events.map((e) => eventInStream(streamName, e));
|
|
1514
|
+
};
|
|
1515
|
+
var newEventsInStream = eventsInStream;
|
|
1516
|
+
var assertSQLQueryResultMatches = (sql, rows) => async ({
|
|
1517
|
+
connection
|
|
1518
|
+
}) => {
|
|
1519
|
+
const result = await connection.execute.query(sql);
|
|
1520
|
+
assertThatArray(rows).containsExactlyInAnyOrder(result.rows);
|
|
1521
|
+
};
|
|
1522
|
+
var expectSQL = {
|
|
1523
|
+
query: (sql) => ({
|
|
1524
|
+
resultRows: {
|
|
1525
|
+
toBeTheSame: (rows) => assertSQLQueryResultMatches(sql, rows)
|
|
1526
|
+
}
|
|
1527
|
+
})
|
|
1528
|
+
};
|
|
519
1529
|
|
|
520
|
-
|
|
521
|
-
require('@event-driven-io/dumbo/sqlite');
|
|
1530
|
+
// src/eventStore/schema/appendToStream.ts
|
|
522
1531
|
|
|
523
1532
|
|
|
524
|
-
// src/eventStore/SQLiteEventStore.ts
|
|
525
1533
|
|
|
526
1534
|
|
|
527
1535
|
|
|
528
1536
|
|
|
529
1537
|
|
|
530
|
-
// src/eventStore/schema/readLastMessageGlobalPosition.ts
|
|
531
1538
|
|
|
532
1539
|
|
|
533
1540
|
// src/eventStore/schema/typing.ts
|
|
@@ -565,158 +1572,12 @@ var projectionsTable = {
|
|
|
565
1572
|
name: `${emmettPrefix2}_projections`
|
|
566
1573
|
};
|
|
567
1574
|
|
|
568
|
-
// src/eventStore/schema/readLastMessageGlobalPosition.ts
|
|
569
|
-
var { identifier } = _dumbo.SQL;
|
|
570
|
-
var readLastMessageGlobalPosition = async (execute, options) => {
|
|
571
|
-
const result = await _dumbo.singleOrNull.call(void 0,
|
|
572
|
-
execute.query(
|
|
573
|
-
_dumbo.SQL`
|
|
574
|
-
SELECT global_position
|
|
575
|
-
FROM ${identifier(messagesTable.name)}
|
|
576
|
-
WHERE partition = ${_nullishCoalesce(_optionalChain([options, 'optionalAccess', _17 => _17.partition]), () => ( defaultTag2))} AND is_archived = FALSE
|
|
577
|
-
ORDER BY global_position
|
|
578
|
-
LIMIT 1`
|
|
579
|
-
)
|
|
580
|
-
);
|
|
581
|
-
return {
|
|
582
|
-
currentGlobalPosition: result !== null ? BigInt(result.global_position) : null
|
|
583
|
-
};
|
|
584
|
-
};
|
|
585
|
-
|
|
586
|
-
// src/eventStore/schema/readMessagesBatch.ts
|
|
587
|
-
|
|
588
|
-
var { identifier: identifier2 } = _dumbo.SQL;
|
|
589
|
-
var readMessagesBatch = async (execute, options) => {
|
|
590
|
-
const from = "from" in options ? options.from : "after" in options ? options.after + 1n : 0n;
|
|
591
|
-
const batchSize = options && "batchSize" in options ? options.batchSize : options.to - options.from;
|
|
592
|
-
const fromCondition = from !== -0n ? _dumbo.SQL`AND global_position >= ${from}` : "";
|
|
593
|
-
const toCondition = "to" in options ? _dumbo.SQL`AND global_position <= ${options.to}` : _dumbo.SQL.EMPTY;
|
|
594
|
-
const limitCondition = "batchSize" in options ? _dumbo.SQL`LIMIT ${options.batchSize}` : _dumbo.SQL.EMPTY;
|
|
595
|
-
const events = (await execute.query(
|
|
596
|
-
_dumbo.SQL`SELECT stream_id, stream_position, global_position, message_data, message_metadata, message_schema_version, message_type, message_id
|
|
597
|
-
FROM ${identifier2(messagesTable.name)}
|
|
598
|
-
WHERE partition = ${_nullishCoalesce(_optionalChain([options, 'optionalAccess', _18 => _18.partition]), () => ( defaultTag2))} AND is_archived = FALSE ${fromCondition} ${toCondition}
|
|
599
|
-
ORDER BY global_position
|
|
600
|
-
${limitCondition}`
|
|
601
|
-
)).rows.map((row) => {
|
|
602
|
-
const rawEvent = {
|
|
603
|
-
type: row.message_type,
|
|
604
|
-
data: JSONParser.parse(row.message_data),
|
|
605
|
-
metadata: JSONParser.parse(row.message_metadata)
|
|
606
|
-
};
|
|
607
|
-
const metadata = {
|
|
608
|
-
..."metadata" in rawEvent ? _nullishCoalesce(rawEvent.metadata, () => ( {})) : {},
|
|
609
|
-
messageId: row.message_id,
|
|
610
|
-
streamName: row.stream_id,
|
|
611
|
-
streamPosition: BigInt(row.stream_position),
|
|
612
|
-
globalPosition: BigInt(row.global_position)
|
|
613
|
-
};
|
|
614
|
-
return {
|
|
615
|
-
...rawEvent,
|
|
616
|
-
kind: "Event",
|
|
617
|
-
metadata
|
|
618
|
-
};
|
|
619
|
-
});
|
|
620
|
-
return events.length > 0 ? {
|
|
621
|
-
currentGlobalPosition: events[events.length - 1].metadata.globalPosition,
|
|
622
|
-
messages: events,
|
|
623
|
-
areEventsLeft: events.length === batchSize
|
|
624
|
-
} : {
|
|
625
|
-
currentGlobalPosition: "from" in options ? options.from : "after" in options ? options.after : 0n,
|
|
626
|
-
messages: [],
|
|
627
|
-
areEventsLeft: false
|
|
628
|
-
};
|
|
629
|
-
};
|
|
630
|
-
|
|
631
|
-
// src/eventStore/consumers/messageBatchProcessing/index.ts
|
|
632
|
-
var DefaultSQLiteEventStoreProcessorBatchSize = 100;
|
|
633
|
-
var DefaultSQLiteEventStoreProcessorPullingFrequencyInMs = 50;
|
|
634
|
-
var sqliteEventStoreMessageBatchPuller = ({
|
|
635
|
-
pool,
|
|
636
|
-
batchSize,
|
|
637
|
-
eachBatch,
|
|
638
|
-
pullingFrequencyInMs
|
|
639
|
-
}) => {
|
|
640
|
-
let isRunning = false;
|
|
641
|
-
let start;
|
|
642
|
-
const pullMessages = async (options) => {
|
|
643
|
-
const after = options.startFrom === "BEGINNING" ? 0n : options.startFrom === "END" ? await _asyncNullishCoalesce((await pool.withConnection(
|
|
644
|
-
async ({ execute }) => readLastMessageGlobalPosition(execute)
|
|
645
|
-
)).currentGlobalPosition, async () => ( 0n)) : options.startFrom.globalPosition;
|
|
646
|
-
const readMessagesOptions = {
|
|
647
|
-
after,
|
|
648
|
-
batchSize
|
|
649
|
-
};
|
|
650
|
-
let waitTime = 100;
|
|
651
|
-
do {
|
|
652
|
-
const { messages, currentGlobalPosition, areEventsLeft } = await pool.withConnection(
|
|
653
|
-
({ execute }) => readMessagesBatch(execute, readMessagesOptions)
|
|
654
|
-
);
|
|
655
|
-
if (messages.length > 0) {
|
|
656
|
-
const result = await eachBatch({ messages });
|
|
657
|
-
if (result && result.type === "STOP") {
|
|
658
|
-
isRunning = false;
|
|
659
|
-
break;
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
readMessagesOptions.after = currentGlobalPosition;
|
|
663
|
-
await new Promise((resolve) => setTimeout(resolve, waitTime));
|
|
664
|
-
if (!areEventsLeft) {
|
|
665
|
-
waitTime = Math.min(waitTime * 2, 1e3);
|
|
666
|
-
} else {
|
|
667
|
-
waitTime = pullingFrequencyInMs;
|
|
668
|
-
}
|
|
669
|
-
} while (isRunning);
|
|
670
|
-
};
|
|
671
|
-
return {
|
|
672
|
-
get isRunning() {
|
|
673
|
-
return isRunning;
|
|
674
|
-
},
|
|
675
|
-
start: (options) => {
|
|
676
|
-
if (isRunning) return start;
|
|
677
|
-
start = (async () => {
|
|
678
|
-
isRunning = true;
|
|
679
|
-
return pullMessages(options);
|
|
680
|
-
})();
|
|
681
|
-
return start;
|
|
682
|
-
},
|
|
683
|
-
stop: async () => {
|
|
684
|
-
if (!isRunning) return;
|
|
685
|
-
isRunning = false;
|
|
686
|
-
await start;
|
|
687
|
-
}
|
|
688
|
-
};
|
|
689
|
-
};
|
|
690
|
-
var zipSQLiteEventStoreMessageBatchPullerStartFrom = (options) => {
|
|
691
|
-
if (options.length === 0 || options.some((o) => o === void 0 || o === "BEGINNING"))
|
|
692
|
-
return "BEGINNING";
|
|
693
|
-
if (options.every((o) => o === "END")) return "END";
|
|
694
|
-
return options.filter((o) => o !== void 0 && o !== "BEGINNING" && o !== "END").sort((a, b) => a > b ? 1 : -1)[0];
|
|
695
|
-
};
|
|
696
|
-
|
|
697
|
-
// src/eventStore/consumers/sqliteEventStoreConsumer.ts
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
// src/eventStore/consumers/sqliteProcessor.ts
|
|
703
|
-
|
|
704
|
-
|
|
705
1575
|
// src/eventStore/schema/appendToStream.ts
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
var { identifier: identifier3, merge } = _dumbo.SQL;
|
|
1576
|
+
var { identifier, merge } = _dumbo.SQL;
|
|
716
1577
|
var appendToStream = async (connection, streamName, streamType, messages, options) => {
|
|
717
1578
|
if (messages.length === 0) return { success: false };
|
|
718
1579
|
const expectedStreamVersion = toExpectedVersion(
|
|
719
|
-
_optionalChain([options, 'optionalAccess',
|
|
1580
|
+
_optionalChain([options, 'optionalAccess', _65 => _65.expectedStreamVersion])
|
|
720
1581
|
);
|
|
721
1582
|
const messagesToAppend = messages.map(
|
|
722
1583
|
(m, i) => ({
|
|
@@ -739,13 +1600,13 @@ var appendToStream = async (connection, streamName, streamType, messages, option
|
|
|
739
1600
|
streamType,
|
|
740
1601
|
downcastRecordedMessages(
|
|
741
1602
|
messagesToAppend,
|
|
742
|
-
_optionalChain([options, 'optionalAccess',
|
|
1603
|
+
_optionalChain([options, 'optionalAccess', _66 => _66.schema, 'optionalAccess', _67 => _67.versioning])
|
|
743
1604
|
),
|
|
744
1605
|
{
|
|
745
1606
|
expectedStreamVersion
|
|
746
1607
|
}
|
|
747
1608
|
);
|
|
748
|
-
if (_optionalChain([options, 'optionalAccess',
|
|
1609
|
+
if (_optionalChain([options, 'optionalAccess', _68 => _68.onBeforeCommit]))
|
|
749
1610
|
await options.onBeforeCommit(messagesToAppend, { connection });
|
|
750
1611
|
return { success: true, result };
|
|
751
1612
|
}
|
|
@@ -769,7 +1630,7 @@ var toExpectedVersion = (expected) => {
|
|
|
769
1630
|
return expected;
|
|
770
1631
|
};
|
|
771
1632
|
var appendToStreamRaw = async (execute, streamId, streamType, messages, options) => {
|
|
772
|
-
let expectedStreamVersion = _nullishCoalesce(_optionalChain([options, 'optionalAccess',
|
|
1633
|
+
let expectedStreamVersion = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _69 => _69.expectedStreamVersion]), () => ( null));
|
|
773
1634
|
const currentStreamVersion = await getLastStreamPosition(
|
|
774
1635
|
execute,
|
|
775
1636
|
streamId,
|
|
@@ -782,22 +1643,22 @@ var appendToStreamRaw = async (execute, streamId, streamType, messages, options)
|
|
|
782
1643
|
expectedStreamVersion
|
|
783
1644
|
);
|
|
784
1645
|
}
|
|
785
|
-
const streamSQL = expectedStreamVersion === 0n ? _dumbo.SQL`INSERT INTO ${
|
|
1646
|
+
const streamSQL = expectedStreamVersion === 0n ? _dumbo.SQL`INSERT INTO ${identifier(streamsTable.name)}
|
|
786
1647
|
(stream_id, stream_position, partition, stream_type, stream_metadata, is_archived)
|
|
787
1648
|
VALUES (
|
|
788
1649
|
${streamId},
|
|
789
1650
|
${messages.length},
|
|
790
|
-
${_nullishCoalesce(_optionalChain([options, 'optionalAccess',
|
|
1651
|
+
${_nullishCoalesce(_optionalChain([options, 'optionalAccess', _70 => _70.partition]), () => ( streamsTable.columns.partition))},
|
|
791
1652
|
${streamType},
|
|
792
1653
|
'[]',
|
|
793
1654
|
false
|
|
794
1655
|
)
|
|
795
1656
|
RETURNING stream_position;
|
|
796
|
-
` : _dumbo.SQL`UPDATE ${
|
|
1657
|
+
` : _dumbo.SQL`UPDATE ${identifier(streamsTable.name)}
|
|
797
1658
|
SET stream_position = stream_position + ${messages.length}
|
|
798
1659
|
WHERE stream_id = ${streamId}
|
|
799
1660
|
AND stream_position = ${expectedStreamVersion}
|
|
800
|
-
AND partition = ${_nullishCoalesce(_optionalChain([options, 'optionalAccess',
|
|
1661
|
+
AND partition = ${_nullishCoalesce(_optionalChain([options, 'optionalAccess', _71 => _71.partition]), () => ( streamsTable.columns.partition))}
|
|
801
1662
|
AND is_archived = false
|
|
802
1663
|
RETURNING stream_position;
|
|
803
1664
|
`;
|
|
@@ -805,12 +1666,12 @@ var appendToStreamRaw = async (execute, streamId, streamType, messages, options)
|
|
|
805
1666
|
messages,
|
|
806
1667
|
expectedStreamVersion,
|
|
807
1668
|
streamId,
|
|
808
|
-
_nullishCoalesce(_optionalChain([options, 'optionalAccess',
|
|
1669
|
+
_nullishCoalesce(_optionalChain([options, 'optionalAccess', _72 => _72.partition, 'optionalAccess', _73 => _73.toString, 'call', _74 => _74()]), () => ( defaultTag2))
|
|
809
1670
|
);
|
|
810
1671
|
const results = await execute.batchCommand([streamSQL, insertSQL], { assertChanges: true });
|
|
811
1672
|
const [streamResult, messagesResult] = results;
|
|
812
|
-
const streamPosition = _optionalChain([streamResult, 'optionalAccess',
|
|
813
|
-
const globalPosition = _optionalChain([messagesResult, 'optionalAccess',
|
|
1673
|
+
const streamPosition = _optionalChain([streamResult, 'optionalAccess', _75 => _75.rows, 'access', _76 => _76[0], 'optionalAccess', _77 => _77.stream_position]);
|
|
1674
|
+
const globalPosition = _optionalChain([messagesResult, 'optionalAccess', _78 => _78.rows, 'access', _79 => _79.at, 'call', _80 => _80(-1), 'optionalAccess', _81 => _81.global_position]);
|
|
814
1675
|
if (!streamPosition)
|
|
815
1676
|
throw new ExpectedVersionConflictError(0n, _nullishCoalesce(expectedStreamVersion, () => ( 0n)));
|
|
816
1677
|
if (!globalPosition) throw new Error("Could not find global position");
|
|
@@ -823,10 +1684,10 @@ var appendToStreamRaw = async (execute, streamId, streamType, messages, options)
|
|
|
823
1684
|
async function getLastStreamPosition(execute, streamId, expectedStreamVersion) {
|
|
824
1685
|
const result = await _dumbo.singleOrNull.call(void 0,
|
|
825
1686
|
execute.query(
|
|
826
|
-
_dumbo.SQL`SELECT CAST(stream_position AS VARCHAR) AS stream_position FROM ${
|
|
1687
|
+
_dumbo.SQL`SELECT CAST(stream_position AS VARCHAR) AS stream_position FROM ${identifier(streamsTable.name)} WHERE stream_id = ${streamId}`
|
|
827
1688
|
)
|
|
828
1689
|
);
|
|
829
|
-
if (_optionalChain([result, 'optionalAccess',
|
|
1690
|
+
if (_optionalChain([result, 'optionalAccess', _82 => _82.stream_position]) == null) {
|
|
830
1691
|
expectedStreamVersion = 0n;
|
|
831
1692
|
} else {
|
|
832
1693
|
expectedStreamVersion = BigInt(result.stream_position);
|
|
@@ -835,14 +1696,14 @@ async function getLastStreamPosition(execute, streamId, expectedStreamVersion) {
|
|
|
835
1696
|
}
|
|
836
1697
|
var buildMessageInsertQuery = (messages, expectedStreamVersion, streamId, partition) => {
|
|
837
1698
|
const values = messages.map((message) => {
|
|
838
|
-
if (_optionalChain([message, 'access',
|
|
1699
|
+
if (_optionalChain([message, 'access', _83 => _83.metadata, 'optionalAccess', _84 => _84.streamPosition]) == null || typeof message.metadata.streamPosition !== "bigint") {
|
|
839
1700
|
throw new Error("Stream position is required");
|
|
840
1701
|
}
|
|
841
1702
|
const streamPosition = BigInt(message.metadata.streamPosition) + BigInt(expectedStreamVersion);
|
|
842
1703
|
return _dumbo.SQL`(${streamId},${_nullishCoalesce(streamPosition, () => ( 0n))},${_nullishCoalesce(partition, () => ( defaultTag2))},${message.kind === "Event" ? "E" : "C"},${message.data},${message.metadata},${_nullishCoalesce(expectedStreamVersion, () => ( 0n))},${message.type},${message.metadata.messageId},${false})`;
|
|
843
1704
|
});
|
|
844
1705
|
return _dumbo.SQL`
|
|
845
|
-
INSERT INTO ${
|
|
1706
|
+
INSERT INTO ${identifier(messagesTable.name)} (
|
|
846
1707
|
stream_id,
|
|
847
1708
|
stream_position,
|
|
848
1709
|
partition,
|
|
@@ -899,9 +1760,9 @@ var schema_0_41_0 = [
|
|
|
899
1760
|
|
|
900
1761
|
// src/eventStore/schema/migrations/0_42_0/0_42_0.migration.ts
|
|
901
1762
|
|
|
902
|
-
var { identifier:
|
|
1763
|
+
var { identifier: identifier2, plain } = _dumbo.SQL;
|
|
903
1764
|
var migration_0_42_0_SQLs = [
|
|
904
|
-
_dumbo.SQL`CREATE TABLE IF NOT EXISTS ${
|
|
1765
|
+
_dumbo.SQL`CREATE TABLE IF NOT EXISTS ${identifier2(processorsTable.name)}(
|
|
905
1766
|
processor_id TEXT NOT NULL,
|
|
906
1767
|
version INTEGER NOT NULL DEFAULT 1,
|
|
907
1768
|
partition TEXT NOT NULL DEFAULT '${plain(globalTag)}',
|
|
@@ -910,7 +1771,7 @@ var migration_0_42_0_SQLs = [
|
|
|
910
1771
|
processor_instance_id TEXT DEFAULT 'emt:unknown',
|
|
911
1772
|
PRIMARY KEY (processor_id, partition, version)
|
|
912
1773
|
)`,
|
|
913
|
-
_dumbo.SQL`CREATE TABLE IF NOT EXISTS ${
|
|
1774
|
+
_dumbo.SQL`CREATE TABLE IF NOT EXISTS ${identifier2(projectionsTable.name)}(
|
|
914
1775
|
name TEXT NOT NULL,
|
|
915
1776
|
version INTEGER NOT NULL DEFAULT 1,
|
|
916
1777
|
partition TEXT NOT NULL DEFAULT '${plain(globalTag)}',
|
|
@@ -920,7 +1781,7 @@ var migration_0_42_0_SQLs = [
|
|
|
920
1781
|
definition JSONB NOT NULL DEFAULT '{}',
|
|
921
1782
|
PRIMARY KEY (name, partition, version)
|
|
922
1783
|
)`,
|
|
923
|
-
_dumbo.SQL`INSERT INTO ${
|
|
1784
|
+
_dumbo.SQL`INSERT INTO ${identifier2(processorsTable.name)}
|
|
924
1785
|
(processor_id, version, partition, status, last_processed_checkpoint, processor_instance_id)
|
|
925
1786
|
SELECT
|
|
926
1787
|
subscription_id,
|
|
@@ -993,337 +1854,332 @@ var schema_0_42_0 = [
|
|
|
993
1854
|
)`
|
|
994
1855
|
];
|
|
995
1856
|
|
|
996
|
-
// src/eventStore/schema/
|
|
1857
|
+
// src/eventStore/schema/readLastMessageGlobalPosition.ts
|
|
997
1858
|
|
|
998
|
-
var { identifier:
|
|
999
|
-
var
|
|
1859
|
+
var { identifier: identifier3 } = _dumbo.SQL;
|
|
1860
|
+
var readLastMessageGlobalPosition = async (execute, options) => {
|
|
1000
1861
|
const result = await _dumbo.singleOrNull.call(void 0,
|
|
1001
1862
|
execute.query(
|
|
1002
|
-
_dumbo.SQL`
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1863
|
+
_dumbo.SQL`
|
|
1864
|
+
SELECT global_position
|
|
1865
|
+
FROM ${identifier3(messagesTable.name)}
|
|
1866
|
+
WHERE partition = ${_nullishCoalesce(_optionalChain([options, 'optionalAccess', _85 => _85.partition]), () => ( defaultTag2))} AND is_archived = FALSE
|
|
1867
|
+
ORDER BY global_position
|
|
1868
|
+
LIMIT 1`
|
|
1006
1869
|
)
|
|
1007
1870
|
);
|
|
1008
1871
|
return {
|
|
1009
|
-
|
|
1872
|
+
currentGlobalPosition: result !== null ? BigInt(result.global_position) : null
|
|
1010
1873
|
};
|
|
1011
1874
|
};
|
|
1012
1875
|
|
|
1013
|
-
// src/eventStore/schema/
|
|
1876
|
+
// src/eventStore/schema/readMessagesBatch.ts
|
|
1014
1877
|
|
|
1015
|
-
var { identifier:
|
|
1016
|
-
var
|
|
1017
|
-
const
|
|
1018
|
-
const
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
const
|
|
1022
|
-
const
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1878
|
+
var { identifier: identifier4 } = _dumbo.SQL;
|
|
1879
|
+
var readMessagesBatch = async (execute, options) => {
|
|
1880
|
+
const { serializer } = options;
|
|
1881
|
+
const from = "from" in options ? options.from : void 0;
|
|
1882
|
+
const after = "after" in options ? options.after : void 0;
|
|
1883
|
+
const batchSize = "batchSize" in options ? options.batchSize : options.to - options.from;
|
|
1884
|
+
const fromCondition = from !== void 0 ? _dumbo.SQL`AND global_position >= ${from}` : after !== void 0 ? _dumbo.SQL`AND global_position > ${after}` : _dumbo.SQL.EMPTY;
|
|
1885
|
+
const toCondition = "to" in options ? _dumbo.SQL`AND global_position <= ${options.to}` : _dumbo.SQL.EMPTY;
|
|
1886
|
+
const limitCondition = "batchSize" in options ? _dumbo.SQL`LIMIT ${options.batchSize}` : _dumbo.SQL.EMPTY;
|
|
1887
|
+
const messages = await _dumbo.mapRows.call(void 0,
|
|
1888
|
+
execute.query(
|
|
1889
|
+
_dumbo.SQL`SELECT stream_id, stream_position, global_position, message_data, message_metadata, message_schema_version, message_type, message_id
|
|
1890
|
+
FROM ${identifier4(messagesTable.name)}
|
|
1891
|
+
WHERE partition = ${_nullishCoalesce(_optionalChain([options, 'optionalAccess', _86 => _86.partition]), () => ( defaultTag2))} AND is_archived = FALSE ${fromCondition} ${toCondition}
|
|
1892
|
+
ORDER BY global_position
|
|
1893
|
+
${limitCondition}`
|
|
1894
|
+
),
|
|
1895
|
+
(row) => {
|
|
1896
|
+
const rawEvent = {
|
|
1897
|
+
type: row.message_type,
|
|
1898
|
+
data: serializer.deserialize(row.message_data),
|
|
1899
|
+
metadata: serializer.deserialize(row.message_metadata)
|
|
1900
|
+
};
|
|
1901
|
+
const metadata = {
|
|
1902
|
+
..."metadata" in rawEvent ? _nullishCoalesce(rawEvent.metadata, () => ( {})) : {},
|
|
1903
|
+
messageId: row.message_id,
|
|
1904
|
+
streamName: row.stream_id,
|
|
1905
|
+
streamPosition: BigInt(row.stream_position),
|
|
1906
|
+
globalPosition: BigInt(row.global_position),
|
|
1907
|
+
checkpoint: bigIntProcessorCheckpoint(BigInt(row.global_position))
|
|
1908
|
+
};
|
|
1909
|
+
return {
|
|
1910
|
+
...rawEvent,
|
|
1911
|
+
kind: "Event",
|
|
1912
|
+
metadata
|
|
1913
|
+
};
|
|
1914
|
+
}
|
|
1027
1915
|
);
|
|
1028
|
-
const messages = results.map((row) => {
|
|
1029
|
-
const rawEvent = {
|
|
1030
|
-
type: row.message_type,
|
|
1031
|
-
data: JSONParser.parse(row.message_data),
|
|
1032
|
-
metadata: JSONParser.parse(row.message_metadata)
|
|
1033
|
-
};
|
|
1034
|
-
const metadata = {
|
|
1035
|
-
..."metadata" in rawEvent ? _nullishCoalesce(rawEvent.metadata, () => ( {})) : {},
|
|
1036
|
-
messageId: row.message_id,
|
|
1037
|
-
streamName: streamId,
|
|
1038
|
-
streamPosition: BigInt(row.stream_position),
|
|
1039
|
-
globalPosition: BigInt(row.global_position)
|
|
1040
|
-
};
|
|
1041
|
-
const event = {
|
|
1042
|
-
...rawEvent,
|
|
1043
|
-
kind: "Event",
|
|
1044
|
-
metadata
|
|
1045
|
-
};
|
|
1046
|
-
return upcastRecordedMessage(event, _optionalChain([options, 'optionalAccess', _44 => _44.schema, 'optionalAccess', _45 => _45.versioning]));
|
|
1047
|
-
});
|
|
1048
1916
|
return messages.length > 0 ? {
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1917
|
+
currentGlobalPosition: messages[messages.length - 1].metadata.globalPosition,
|
|
1918
|
+
messages,
|
|
1919
|
+
areMessagesLeft: messages.length === batchSize
|
|
1052
1920
|
} : {
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1921
|
+
currentGlobalPosition: "from" in options ? options.from : "after" in options ? options.after : 0n,
|
|
1922
|
+
messages: [],
|
|
1923
|
+
areMessagesLeft: false
|
|
1056
1924
|
};
|
|
1057
1925
|
};
|
|
1058
1926
|
|
|
1059
|
-
// src/eventStore/schema/
|
|
1927
|
+
// src/eventStore/schema/readProcessorCheckpoint.ts
|
|
1060
1928
|
|
|
1929
|
+
var { identifier: identifier5 } = _dumbo.SQL;
|
|
1930
|
+
var readProcessorCheckpoint = async (execute, options) => {
|
|
1931
|
+
const result = await _dumbo.singleOrNull.call(void 0,
|
|
1932
|
+
execute.query(
|
|
1933
|
+
_dumbo.SQL`SELECT last_processed_checkpoint
|
|
1934
|
+
FROM ${identifier5(processorsTable.name)}
|
|
1935
|
+
WHERE partition = ${_nullishCoalesce(_optionalChain([options, 'optionalAccess', _87 => _87.partition]), () => ( defaultTag2))} AND processor_id = ${options.processorId}
|
|
1936
|
+
LIMIT 1`
|
|
1937
|
+
)
|
|
1938
|
+
);
|
|
1939
|
+
return {
|
|
1940
|
+
lastProcessedCheckpoint: result !== null ? result.last_processed_checkpoint : null
|
|
1941
|
+
};
|
|
1942
|
+
};
|
|
1061
1943
|
|
|
1944
|
+
// src/eventStore/schema/readStream.ts
|
|
1062
1945
|
|
|
1063
1946
|
|
|
1947
|
+
// src/eventStore/SQLiteEventStore.ts
|
|
1064
1948
|
|
|
1065
1949
|
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
return 2;
|
|
1098
|
-
}
|
|
1099
|
-
} else {
|
|
1100
|
-
try {
|
|
1101
|
-
await execute.command(
|
|
1102
|
-
_dumbo.SQL`INSERT INTO ${identifier7(processorsTable.name)} (processor_id, version, last_processed_checkpoint, partition, processor_instance_id)
|
|
1103
|
-
VALUES (${processorId}, ${version}, ${position}, ${partition}, ${processorInstanceId})`
|
|
1104
|
-
);
|
|
1105
|
-
return 1;
|
|
1106
|
-
} catch (err) {
|
|
1107
|
-
if (!_dumbo.DumboError.isInstanceOf(err, {
|
|
1108
|
-
errorType: _dumbo.UniqueConstraintError.ErrorType
|
|
1109
|
-
})) {
|
|
1110
|
-
throw err;
|
|
1950
|
+
// src/eventStore/consumers/messageBatchProcessing/index.ts
|
|
1951
|
+
var DefaultSQLiteEventStoreProcessorBatchSize = 100;
|
|
1952
|
+
var DefaultSQLiteEventStoreProcessorPullingFrequencyInMs = 50;
|
|
1953
|
+
var sqliteEventStoreMessageBatchPuller = ({
|
|
1954
|
+
executor,
|
|
1955
|
+
batchSize,
|
|
1956
|
+
eachBatch,
|
|
1957
|
+
pullingFrequencyInMs,
|
|
1958
|
+
stopWhen,
|
|
1959
|
+
signal,
|
|
1960
|
+
serialization
|
|
1961
|
+
}) => {
|
|
1962
|
+
let isRunning = false;
|
|
1963
|
+
let start;
|
|
1964
|
+
const serializer = JSONSerializer.from({ serialization });
|
|
1965
|
+
const pullMessages = async (options) => {
|
|
1966
|
+
const after = options.startFrom === "BEGINNING" ? 0n : options.startFrom === "END" ? await _asyncNullishCoalesce((await readLastMessageGlobalPosition(executor)).currentGlobalPosition, async () => ( 0n)) : parseBigIntProcessorCheckpoint(options.startFrom.lastCheckpoint);
|
|
1967
|
+
const readMessagesOptions = {
|
|
1968
|
+
after,
|
|
1969
|
+
batchSize,
|
|
1970
|
+
serializer
|
|
1971
|
+
};
|
|
1972
|
+
let waitTime = 100;
|
|
1973
|
+
while (isRunning && !_optionalChain([signal, 'optionalAccess', _88 => _88.aborted])) {
|
|
1974
|
+
const { messages, currentGlobalPosition, areMessagesLeft } = await readMessagesBatch(executor, readMessagesOptions);
|
|
1975
|
+
if (messages.length > 0) {
|
|
1976
|
+
const result = await eachBatch(messages);
|
|
1977
|
+
if (result && result.type === "STOP") {
|
|
1978
|
+
isRunning = false;
|
|
1979
|
+
break;
|
|
1980
|
+
}
|
|
1111
1981
|
}
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
)
|
|
1119
|
-
|
|
1120
|
-
if (currentPosition === position) {
|
|
1121
|
-
return 0;
|
|
1982
|
+
readMessagesOptions.after = currentGlobalPosition;
|
|
1983
|
+
await new Promise((resolve) => setTimeout(resolve, waitTime));
|
|
1984
|
+
if (_optionalChain([stopWhen, 'optionalAccess', _89 => _89.noMessagesLeft]) === true && !areMessagesLeft) {
|
|
1985
|
+
isRunning = false;
|
|
1986
|
+
break;
|
|
1987
|
+
}
|
|
1988
|
+
if (!areMessagesLeft) {
|
|
1989
|
+
waitTime = Math.min(waitTime * 2, 1e3);
|
|
1122
1990
|
} else {
|
|
1123
|
-
|
|
1991
|
+
waitTime = pullingFrequencyInMs;
|
|
1124
1992
|
}
|
|
1125
1993
|
}
|
|
1126
|
-
}
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
}
|
|
1994
|
+
};
|
|
1995
|
+
return {
|
|
1996
|
+
get isRunning() {
|
|
1997
|
+
return isRunning;
|
|
1998
|
+
},
|
|
1999
|
+
start: (options) => {
|
|
2000
|
+
if (isRunning) return start;
|
|
2001
|
+
isRunning = true;
|
|
2002
|
+
start = (async () => {
|
|
2003
|
+
return pullMessages(options);
|
|
2004
|
+
})();
|
|
2005
|
+
return start;
|
|
2006
|
+
},
|
|
2007
|
+
stop: async () => {
|
|
2008
|
+
if (!isRunning) return;
|
|
2009
|
+
isRunning = false;
|
|
2010
|
+
await start;
|
|
2011
|
+
}
|
|
2012
|
+
};
|
|
2013
|
+
};
|
|
2014
|
+
var zipSQLiteEventStoreMessageBatchPullerStartFrom = (options) => {
|
|
2015
|
+
if (options.length === 0 || options.some((o) => o === void 0 || o === "BEGINNING"))
|
|
2016
|
+
return "BEGINNING";
|
|
2017
|
+
if (options.every((o) => o === "END")) return "END";
|
|
2018
|
+
return options.filter((o) => o !== void 0 && o !== "BEGINNING" && o !== "END").sort((a, b) => a > b ? 1 : -1)[0];
|
|
2019
|
+
};
|
|
1144
2020
|
|
|
1145
|
-
// src/eventStore/
|
|
2021
|
+
// src/eventStore/consumers/sqliteEventStoreConsumer.ts
|
|
1146
2022
|
|
|
1147
|
-
var streamExists = (execute, streamId, options) => _dumbo.exists.call(void 0,
|
|
1148
|
-
execute.query(
|
|
1149
|
-
_dumbo.SQL`SELECT EXISTS (
|
|
1150
|
-
SELECT 1
|
|
1151
|
-
from ${_dumbo.SQL.identifier(streamsTable.name)}
|
|
1152
|
-
WHERE stream_id = ${streamId} AND partition = ${_nullishCoalesce(_optionalChain([options, 'optionalAccess', _48 => _48.partition]), () => ( defaultTag2))} AND is_archived = FALSE) as exists
|
|
1153
|
-
`
|
|
1154
|
-
)
|
|
1155
|
-
);
|
|
1156
2023
|
|
|
1157
|
-
// src/eventStore/schema/tables.ts
|
|
1158
2024
|
|
|
1159
|
-
|
|
1160
|
-
var
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
message_metadata JSONB NOT NULL,
|
|
1178
|
-
message_schema_version TEXT NOT NULL,
|
|
1179
|
-
message_type TEXT NOT NULL,
|
|
1180
|
-
message_id TEXT NOT NULL,
|
|
1181
|
-
is_archived BOOLEAN NOT NULL DEFAULT FALSE,
|
|
1182
|
-
global_position INTEGER PRIMARY KEY,
|
|
1183
|
-
created DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
1184
|
-
UNIQUE (stream_id, stream_position, partition, is_archived)
|
|
1185
|
-
);
|
|
1186
|
-
`;
|
|
1187
|
-
var processorsTableSQL = _dumbo.SQL`
|
|
1188
|
-
CREATE TABLE IF NOT EXISTS ${_dumbo.SQL.identifier(processorsTable.name)}(
|
|
1189
|
-
processor_id TEXT NOT NULL,
|
|
1190
|
-
version INTEGER NOT NULL DEFAULT 1,
|
|
1191
|
-
partition TEXT NOT NULL DEFAULT '${plain2(globalTag)}',
|
|
1192
|
-
status TEXT NOT NULL DEFAULT 'stopped',
|
|
1193
|
-
last_processed_checkpoint TEXT NOT NULL,
|
|
1194
|
-
processor_instance_id TEXT DEFAULT '${plain2(unknownTag2)}',
|
|
1195
|
-
PRIMARY KEY (processor_id, partition, version)
|
|
1196
|
-
);
|
|
1197
|
-
`;
|
|
1198
|
-
var projectionsTableSQL = _dumbo.SQL`
|
|
1199
|
-
CREATE TABLE IF NOT EXISTS ${_dumbo.SQL.identifier(projectionsTable.name)}(
|
|
1200
|
-
name TEXT NOT NULL,
|
|
1201
|
-
version INTEGER NOT NULL DEFAULT 1,
|
|
1202
|
-
partition TEXT NOT NULL DEFAULT '${plain2(globalTag)}',
|
|
1203
|
-
type CHAR(1) NOT NULL,
|
|
1204
|
-
kind TEXT NOT NULL,
|
|
1205
|
-
status TEXT NOT NULL,
|
|
1206
|
-
definition JSONB NOT NULL DEFAULT '{}',
|
|
1207
|
-
PRIMARY KEY (name, partition, version)
|
|
1208
|
-
);
|
|
1209
|
-
`;
|
|
1210
|
-
var schemaSQL = [
|
|
1211
|
-
streamsTableSQL,
|
|
1212
|
-
messagesTableSQL,
|
|
1213
|
-
processorsTableSQL,
|
|
1214
|
-
projectionsTableSQL
|
|
1215
|
-
];
|
|
1216
|
-
var createEventStoreSchema = async (pool, hooks) => {
|
|
1217
|
-
await pool.withTransaction(async (tx) => {
|
|
1218
|
-
await migration_0_42_0_FromSubscriptionsToProcessors(tx.execute);
|
|
1219
|
-
if (_optionalChain([hooks, 'optionalAccess', _49 => _49.onBeforeSchemaCreated])) {
|
|
1220
|
-
await hooks.onBeforeSchemaCreated({
|
|
1221
|
-
connection: tx.connection
|
|
1222
|
-
});
|
|
1223
|
-
}
|
|
1224
|
-
await tx.execute.batchCommand(schemaSQL);
|
|
1225
|
-
if (_optionalChain([hooks, 'optionalAccess', _50 => _50.onAfterSchemaCreated])) {
|
|
1226
|
-
await hooks.onAfterSchemaCreated();
|
|
1227
|
-
}
|
|
1228
|
-
});
|
|
1229
|
-
};
|
|
2025
|
+
// src/eventStore/consumers/sqliteCheckpointer.ts
|
|
2026
|
+
var sqliteCheckpointer = () => ({
|
|
2027
|
+
read: async (options, context) => {
|
|
2028
|
+
const result = await readProcessorCheckpoint(context.execute, options);
|
|
2029
|
+
return { lastCheckpoint: _optionalChain([result, 'optionalAccess', _90 => _90.lastProcessedCheckpoint]) };
|
|
2030
|
+
},
|
|
2031
|
+
store: async (options, context) => {
|
|
2032
|
+
const newCheckpoint = getCheckpoint(options.message);
|
|
2033
|
+
const result = await storeProcessorCheckpoint(context.execute, {
|
|
2034
|
+
lastProcessedCheckpoint: options.lastCheckpoint,
|
|
2035
|
+
newCheckpoint,
|
|
2036
|
+
processorId: options.processorId,
|
|
2037
|
+
partition: options.partition,
|
|
2038
|
+
version: options.version
|
|
2039
|
+
});
|
|
2040
|
+
return result.success ? { success: true, newCheckpoint: result.newCheckpoint } : result;
|
|
2041
|
+
}
|
|
2042
|
+
});
|
|
1230
2043
|
|
|
1231
2044
|
// src/eventStore/consumers/sqliteProcessor.ts
|
|
1232
|
-
var
|
|
1233
|
-
const
|
|
1234
|
-
|
|
1235
|
-
const mapToContext = (context) => {
|
|
1236
|
-
const connection = _nullishCoalesce(context.connection, () => ( _optionalChain([options, 'access', _51 => _51.connectionOptions, 'optionalAccess', _52 => _52.connection])));
|
|
2045
|
+
var sqliteProcessingScope = () => {
|
|
2046
|
+
const processingScope = async (handler, partialContext) => {
|
|
2047
|
+
const connection = _optionalChain([partialContext, 'optionalAccess', _91 => _91.connection]);
|
|
1237
2048
|
if (!connection)
|
|
1238
|
-
throw new
|
|
1239
|
-
return
|
|
2049
|
+
throw new EmmettError("Connection is required in context or options");
|
|
2050
|
+
return connection.withTransaction(
|
|
2051
|
+
async (transaction) => {
|
|
2052
|
+
return handler({
|
|
2053
|
+
...partialContext,
|
|
2054
|
+
connection,
|
|
2055
|
+
execute: transaction.execute
|
|
2056
|
+
});
|
|
2057
|
+
}
|
|
2058
|
+
);
|
|
1240
2059
|
};
|
|
1241
|
-
return
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
},
|
|
1258
|
-
handle: async ({ messages }, context) => {
|
|
1259
|
-
if (!isActive) return;
|
|
1260
|
-
const { connection } = mapToContext(context);
|
|
1261
|
-
return connection.withTransaction(async (tx) => {
|
|
1262
|
-
let result = void 0;
|
|
1263
|
-
let lastProcessedPosition = null;
|
|
1264
|
-
for (const message of messages) {
|
|
1265
|
-
const typedMessage = message;
|
|
1266
|
-
const messageProcessingResult = await eachMessage(typedMessage, {
|
|
1267
|
-
connection: tx.connection
|
|
1268
|
-
});
|
|
1269
|
-
const newPosition = getCheckpoint(typedMessage);
|
|
1270
|
-
await storeProcessorCheckpoint(tx.execute, {
|
|
1271
|
-
processorId: options.processorId,
|
|
1272
|
-
version: options.version,
|
|
1273
|
-
lastProcessedPosition,
|
|
1274
|
-
newPosition,
|
|
1275
|
-
partition: options.partition
|
|
1276
|
-
});
|
|
1277
|
-
lastProcessedPosition = typedMessage.metadata.globalPosition;
|
|
1278
|
-
if (messageProcessingResult && messageProcessingResult.type === "STOP") {
|
|
1279
|
-
isActive = false;
|
|
1280
|
-
result = messageProcessingResult;
|
|
1281
|
-
break;
|
|
1282
|
-
}
|
|
1283
|
-
if (options.stopAfter && options.stopAfter(typedMessage)) {
|
|
1284
|
-
isActive = false;
|
|
1285
|
-
result = { type: "STOP", reason: "Stop condition reached" };
|
|
1286
|
-
break;
|
|
1287
|
-
}
|
|
1288
|
-
if (messageProcessingResult && messageProcessingResult.type === "SKIP")
|
|
1289
|
-
continue;
|
|
1290
|
-
}
|
|
1291
|
-
return result;
|
|
1292
|
-
});
|
|
1293
|
-
}
|
|
2060
|
+
return processingScope;
|
|
2061
|
+
};
|
|
2062
|
+
var sqliteWorkflowProcessingScope = (messageStore) => {
|
|
2063
|
+
const processingScope = async (handler, partialContext) => {
|
|
2064
|
+
const connection = _optionalChain([partialContext, 'optionalAccess', _92 => _92.connection]);
|
|
2065
|
+
if (!connection)
|
|
2066
|
+
throw new EmmettError("Connection is required in context or options");
|
|
2067
|
+
return connection.withTransaction(
|
|
2068
|
+
async (transaction) => {
|
|
2069
|
+
return handler({
|
|
2070
|
+
...partialContext,
|
|
2071
|
+
connection: Object.assign(connection, { messageStore }),
|
|
2072
|
+
execute: transaction.execute
|
|
2073
|
+
});
|
|
2074
|
+
}
|
|
2075
|
+
);
|
|
1294
2076
|
};
|
|
2077
|
+
return processingScope;
|
|
1295
2078
|
};
|
|
1296
|
-
var
|
|
1297
|
-
const
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
2079
|
+
var sqliteWorkflowProcessor = (options) => {
|
|
2080
|
+
const {
|
|
2081
|
+
processorId = _nullishCoalesce(options.processorId, () => ( getWorkflowId({
|
|
2082
|
+
workflowName: _nullishCoalesce(options.workflow.name, () => ( "unknown"))
|
|
2083
|
+
}))),
|
|
2084
|
+
processorInstanceId = getProcessorInstanceId(processorId),
|
|
2085
|
+
version = defaultProcessorVersion,
|
|
2086
|
+
partition = defaultProcessorPartition
|
|
2087
|
+
} = options;
|
|
2088
|
+
const hooks = {
|
|
2089
|
+
..._nullishCoalesce(options.hooks, () => ( {})),
|
|
2090
|
+
onClose: _optionalChain([options, 'access', _93 => _93.hooks, 'optionalAccess', _94 => _94.onClose])
|
|
2091
|
+
};
|
|
2092
|
+
return workflowProcessor({
|
|
2093
|
+
...options,
|
|
2094
|
+
processorId,
|
|
2095
|
+
processorInstanceId,
|
|
2096
|
+
version,
|
|
2097
|
+
partition,
|
|
2098
|
+
hooks,
|
|
2099
|
+
processingScope: sqliteWorkflowProcessingScope(
|
|
2100
|
+
options.messageStore
|
|
2101
|
+
),
|
|
2102
|
+
checkpoints: sqliteCheckpointer()
|
|
1305
2103
|
});
|
|
1306
2104
|
};
|
|
1307
|
-
var
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
2105
|
+
var sqliteReactor = (options) => {
|
|
2106
|
+
const {
|
|
2107
|
+
processorId = options.processorId,
|
|
2108
|
+
processorInstanceId = getProcessorInstanceId(processorId),
|
|
2109
|
+
version = defaultProcessorVersion,
|
|
2110
|
+
partition = defaultProcessorPartition,
|
|
2111
|
+
hooks
|
|
2112
|
+
} = options;
|
|
2113
|
+
return reactor({
|
|
2114
|
+
...options,
|
|
2115
|
+
processorId,
|
|
2116
|
+
processorInstanceId,
|
|
2117
|
+
version,
|
|
2118
|
+
partition,
|
|
2119
|
+
hooks,
|
|
2120
|
+
processingScope: sqliteProcessingScope(),
|
|
2121
|
+
checkpoints: sqliteCheckpointer()
|
|
2122
|
+
});
|
|
2123
|
+
};
|
|
2124
|
+
var sqliteProjector = (options) => {
|
|
2125
|
+
const {
|
|
2126
|
+
processorId = getProjectorId({
|
|
2127
|
+
projectionName: _nullishCoalesce(options.projection.name, () => ( "unknown"))
|
|
2128
|
+
}),
|
|
2129
|
+
processorInstanceId = getProcessorInstanceId(processorId),
|
|
2130
|
+
version = defaultProcessorVersion,
|
|
2131
|
+
partition = defaultProcessorPartition
|
|
2132
|
+
} = options;
|
|
2133
|
+
const hooks = {
|
|
2134
|
+
..._nullishCoalesce(options.hooks, () => ( {})),
|
|
2135
|
+
onInit: options.projection.init !== void 0 || _optionalChain([options, 'access', _95 => _95.hooks, 'optionalAccess', _96 => _96.onInit]) ? async (context) => {
|
|
2136
|
+
if (options.projection.init)
|
|
2137
|
+
await options.projection.init({
|
|
2138
|
+
version: _nullishCoalesce(options.projection.version, () => ( version)),
|
|
2139
|
+
status: "active",
|
|
2140
|
+
registrationType: "async",
|
|
2141
|
+
context: {
|
|
2142
|
+
...context,
|
|
2143
|
+
migrationOptions: options.migrationOptions
|
|
2144
|
+
}
|
|
2145
|
+
});
|
|
2146
|
+
if (_optionalChain([options, 'access', _97 => _97.hooks, 'optionalAccess', _98 => _98.onInit]))
|
|
2147
|
+
await options.hooks.onInit({
|
|
2148
|
+
...context,
|
|
2149
|
+
migrationOptions: options.migrationOptions
|
|
2150
|
+
});
|
|
2151
|
+
} : _optionalChain([options, 'access', _99 => _99.hooks, 'optionalAccess', _100 => _100.onInit]),
|
|
2152
|
+
onClose: _optionalChain([options, 'access', _101 => _101.hooks, 'optionalAccess', _102 => _102.onClose])
|
|
2153
|
+
};
|
|
2154
|
+
const processor = projector({
|
|
2155
|
+
...options,
|
|
2156
|
+
processorId,
|
|
2157
|
+
processorInstanceId,
|
|
2158
|
+
version,
|
|
2159
|
+
partition,
|
|
2160
|
+
hooks,
|
|
2161
|
+
processingScope: sqliteProcessingScope(),
|
|
2162
|
+
checkpoints: sqliteCheckpointer()
|
|
2163
|
+
});
|
|
2164
|
+
return processor;
|
|
1312
2165
|
};
|
|
1313
2166
|
|
|
1314
2167
|
// src/eventStore/consumers/sqliteEventStoreConsumer.ts
|
|
1315
2168
|
var sqliteEventStoreConsumer = (options) => {
|
|
1316
2169
|
let isRunning = false;
|
|
2170
|
+
let isInitialized = false;
|
|
1317
2171
|
const { pulling } = options;
|
|
1318
2172
|
const processors = _nullishCoalesce(options.processors, () => ( []));
|
|
2173
|
+
let abortController = null;
|
|
1319
2174
|
let start;
|
|
1320
|
-
let
|
|
2175
|
+
let messagePuller;
|
|
1321
2176
|
const pool = _nullishCoalesce(options.pool, () => ( _dumbo.dumbo.call(void 0, {
|
|
2177
|
+
serialization: options.serialization,
|
|
1322
2178
|
transactionOptions: {
|
|
1323
2179
|
allowNestedTransactions: true,
|
|
1324
2180
|
mode: "session_based"
|
|
1325
2181
|
},
|
|
1326
|
-
...options
|
|
2182
|
+
...options.driver.mapToDumboOptions(options)
|
|
1327
2183
|
})));
|
|
1328
2184
|
const eachBatch = (messagesBatch) => pool.withConnection(async (connection) => {
|
|
1329
2185
|
const activeProcessors = processors.filter((s) => s.isActive);
|
|
@@ -1333,59 +2189,128 @@ var sqliteEventStoreConsumer = (options) => {
|
|
|
1333
2189
|
reason: "No active processors"
|
|
1334
2190
|
};
|
|
1335
2191
|
const result = await Promise.allSettled(
|
|
1336
|
-
activeProcessors.map((s) => {
|
|
1337
|
-
return s.handle(messagesBatch, {
|
|
1338
|
-
connection
|
|
2192
|
+
activeProcessors.map(async (s) => {
|
|
2193
|
+
return await s.handle(messagesBatch, {
|
|
2194
|
+
connection,
|
|
2195
|
+
execute: connection.execute
|
|
1339
2196
|
});
|
|
1340
2197
|
})
|
|
1341
2198
|
);
|
|
1342
2199
|
return result.some(
|
|
1343
|
-
(r) => r.status === "fulfilled" && _optionalChain([r, 'access',
|
|
2200
|
+
(r) => r.status === "fulfilled" && _optionalChain([r, 'access', _103 => _103.value, 'optionalAccess', _104 => _104.type]) !== "STOP"
|
|
1344
2201
|
) ? void 0 : {
|
|
1345
2202
|
type: "STOP"
|
|
1346
2203
|
};
|
|
1347
2204
|
});
|
|
1348
|
-
const
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
});
|
|
2205
|
+
const processorContext = {
|
|
2206
|
+
execute: void 0,
|
|
2207
|
+
connection: void 0
|
|
2208
|
+
};
|
|
2209
|
+
const stopProcessors = () => Promise.all(processors.map((p) => p.close(processorContext)));
|
|
1354
2210
|
const stop = async () => {
|
|
1355
2211
|
if (!isRunning) return;
|
|
1356
2212
|
isRunning = false;
|
|
1357
|
-
if (
|
|
1358
|
-
|
|
1359
|
-
|
|
2213
|
+
if (messagePuller) {
|
|
2214
|
+
_optionalChain([abortController, 'optionalAccess', _105 => _105.abort, 'call', _106 => _106()]);
|
|
2215
|
+
await messagePuller.stop();
|
|
1360
2216
|
}
|
|
1361
2217
|
await start;
|
|
2218
|
+
messagePuller = void 0;
|
|
2219
|
+
abortController = null;
|
|
2220
|
+
await stopProcessors();
|
|
2221
|
+
};
|
|
2222
|
+
const init = async () => {
|
|
2223
|
+
if (isInitialized) return;
|
|
2224
|
+
const sqliteProcessors = processors;
|
|
2225
|
+
await pool.withConnection(async (connection) => {
|
|
2226
|
+
for (const processor of sqliteProcessors) {
|
|
2227
|
+
if (processor.init) {
|
|
2228
|
+
await processor.init({
|
|
2229
|
+
...processorContext,
|
|
2230
|
+
connection,
|
|
2231
|
+
execute: connection.execute
|
|
2232
|
+
});
|
|
2233
|
+
}
|
|
2234
|
+
}
|
|
2235
|
+
});
|
|
2236
|
+
isInitialized = true;
|
|
1362
2237
|
};
|
|
1363
2238
|
return {
|
|
1364
|
-
|
|
2239
|
+
consumerId: _nullishCoalesce(options.consumerId, () => ( _uuid.v7.call(void 0, ))),
|
|
1365
2240
|
get isRunning() {
|
|
1366
2241
|
return isRunning;
|
|
1367
2242
|
},
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
2243
|
+
processors,
|
|
2244
|
+
init,
|
|
2245
|
+
reactor: (options2) => {
|
|
2246
|
+
const processor = sqliteReactor(options2);
|
|
2247
|
+
processors.push(
|
|
2248
|
+
// TODO: change that
|
|
2249
|
+
processor
|
|
2250
|
+
);
|
|
2251
|
+
return processor;
|
|
2252
|
+
},
|
|
2253
|
+
projector: (options2) => {
|
|
2254
|
+
const processor = sqliteProjector(options2);
|
|
2255
|
+
processors.push(
|
|
2256
|
+
// TODO: change that
|
|
2257
|
+
processor
|
|
2258
|
+
);
|
|
2259
|
+
return processor;
|
|
2260
|
+
},
|
|
2261
|
+
workflowProcessor: (processorOptions) => {
|
|
2262
|
+
const messageStore = getSQLiteEventStore({
|
|
2263
|
+
...options,
|
|
2264
|
+
pool,
|
|
2265
|
+
schema: { autoMigration: "None" }
|
|
2266
|
+
});
|
|
2267
|
+
const processor = sqliteWorkflowProcessor({
|
|
2268
|
+
...processorOptions,
|
|
2269
|
+
messageStore
|
|
2270
|
+
});
|
|
2271
|
+
processors.push(
|
|
2272
|
+
// TODO: change that
|
|
2273
|
+
processor
|
|
2274
|
+
);
|
|
1371
2275
|
return processor;
|
|
1372
2276
|
},
|
|
1373
2277
|
start: () => {
|
|
1374
2278
|
if (isRunning) return start;
|
|
2279
|
+
if (processors.length === 0)
|
|
2280
|
+
throw new EmmettError(
|
|
2281
|
+
"Cannot start consumer without at least a single processor"
|
|
2282
|
+
);
|
|
2283
|
+
isRunning = true;
|
|
2284
|
+
abortController = new AbortController();
|
|
2285
|
+
messagePuller = sqliteEventStoreMessageBatchPuller({
|
|
2286
|
+
stopWhen: options.stopWhen,
|
|
2287
|
+
executor: pool.execute,
|
|
2288
|
+
eachBatch,
|
|
2289
|
+
batchSize: _nullishCoalesce(_optionalChain([pulling, 'optionalAccess', _107 => _107.batchSize]), () => ( DefaultSQLiteEventStoreProcessorBatchSize)),
|
|
2290
|
+
pullingFrequencyInMs: _nullishCoalesce(_optionalChain([pulling, 'optionalAccess', _108 => _108.pullingFrequencyInMs]), () => ( DefaultSQLiteEventStoreProcessorPullingFrequencyInMs)),
|
|
2291
|
+
signal: abortController.signal
|
|
2292
|
+
});
|
|
1375
2293
|
start = (async () => {
|
|
1376
|
-
if (
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
2294
|
+
if (!isRunning) return;
|
|
2295
|
+
if (!isInitialized) {
|
|
2296
|
+
await init();
|
|
2297
|
+
}
|
|
2298
|
+
const startFrom = await pool.withConnection(
|
|
2299
|
+
async (connection) => zipSQLiteEventStoreMessageBatchPullerStartFrom(
|
|
2300
|
+
await Promise.all(
|
|
2301
|
+
processors.map(async (o) => {
|
|
2302
|
+
const result = await o.start({
|
|
2303
|
+
execute: connection.execute,
|
|
2304
|
+
connection
|
|
2305
|
+
});
|
|
2306
|
+
return result;
|
|
2307
|
+
})
|
|
1380
2308
|
)
|
|
1381
|
-
);
|
|
1382
|
-
isRunning = true;
|
|
1383
|
-
const startFrom = zipSQLiteEventStoreMessageBatchPullerStartFrom(
|
|
1384
|
-
await pool.withConnection(
|
|
1385
|
-
(connection) => Promise.all(processors.map((o) => o.start(connection)))
|
|
1386
2309
|
)
|
|
1387
2310
|
);
|
|
1388
|
-
|
|
2311
|
+
await messagePuller.start({ startFrom });
|
|
2312
|
+
await stopProcessors();
|
|
2313
|
+
isRunning = false;
|
|
1389
2314
|
})();
|
|
1390
2315
|
return start;
|
|
1391
2316
|
},
|
|
@@ -1393,7 +2318,6 @@ var sqliteEventStoreConsumer = (options) => {
|
|
|
1393
2318
|
close: async () => {
|
|
1394
2319
|
await stop();
|
|
1395
2320
|
await pool.close();
|
|
1396
|
-
await new Promise((resolve) => setTimeout(resolve, 250));
|
|
1397
2321
|
}
|
|
1398
2322
|
};
|
|
1399
2323
|
};
|
|
@@ -1402,22 +2326,20 @@ var sqliteEventStoreConsumer = (options) => {
|
|
|
1402
2326
|
var SQLiteEventStoreDefaultStreamVersion = 0n;
|
|
1403
2327
|
var getSQLiteEventStore = (options) => {
|
|
1404
2328
|
let autoGenerateSchema = false;
|
|
2329
|
+
const serializer = JSONSerializer.from(options);
|
|
1405
2330
|
const pool = _nullishCoalesce(options.pool, () => ( _dumbo.dumbo.call(void 0, {
|
|
2331
|
+
serialization: options.serialization,
|
|
1406
2332
|
transactionOptions: {
|
|
1407
2333
|
allowNestedTransactions: true,
|
|
1408
2334
|
mode: "session_based"
|
|
1409
2335
|
},
|
|
1410
|
-
...options
|
|
2336
|
+
...options.driver.mapToDumboOptions(options)
|
|
1411
2337
|
})));
|
|
1412
2338
|
let migrateSchema = void 0;
|
|
1413
2339
|
const inlineProjections = (_nullishCoalesce(options.projections, () => ( []))).filter(({ type }) => type === "inline").map(({ projection: projection2 }) => projection2);
|
|
1414
|
-
const onBeforeCommitHook = _optionalChain([options, 'access',
|
|
1415
|
-
const withConnection = async (handler) => pool.withConnection(async (connection) => {
|
|
1416
|
-
await ensureSchemaExists(connection);
|
|
1417
|
-
return await handler(connection);
|
|
1418
|
-
});
|
|
2340
|
+
const onBeforeCommitHook = _optionalChain([options, 'access', _109 => _109.hooks, 'optionalAccess', _110 => _110.onBeforeCommit]);
|
|
1419
2341
|
if (options) {
|
|
1420
|
-
autoGenerateSchema = _optionalChain([options, 'access',
|
|
2342
|
+
autoGenerateSchema = _optionalChain([options, 'access', _111 => _111.schema, 'optionalAccess', _112 => _112.autoMigration]) === void 0 || _optionalChain([options, 'access', _113 => _113.schema, 'optionalAccess', _114 => _114.autoMigration]) !== "None";
|
|
1421
2343
|
}
|
|
1422
2344
|
const migrate = (connection) => {
|
|
1423
2345
|
if (!migrateSchema) {
|
|
@@ -1429,33 +2351,40 @@ var getSQLiteEventStore = (options) => {
|
|
|
1429
2351
|
version: _nullishCoalesce(projection2.version, () => ( 1)),
|
|
1430
2352
|
registrationType: "async",
|
|
1431
2353
|
status: "active",
|
|
1432
|
-
context
|
|
2354
|
+
context: {
|
|
2355
|
+
execute: context.connection.execute,
|
|
2356
|
+
connection: context.connection,
|
|
2357
|
+
driverType: options.driver.driverType
|
|
2358
|
+
}
|
|
1433
2359
|
});
|
|
1434
2360
|
}
|
|
1435
2361
|
}
|
|
1436
|
-
if (_optionalChain([options, 'access',
|
|
2362
|
+
if (_optionalChain([options, 'access', _115 => _115.hooks, 'optionalAccess', _116 => _116.onBeforeSchemaCreated])) {
|
|
1437
2363
|
await options.hooks.onBeforeSchemaCreated(context);
|
|
1438
2364
|
}
|
|
1439
2365
|
},
|
|
1440
|
-
onAfterSchemaCreated: _optionalChain([options, 'access',
|
|
2366
|
+
onAfterSchemaCreated: _optionalChain([options, 'access', _117 => _117.hooks, 'optionalAccess', _118 => _118.onAfterSchemaCreated])
|
|
1441
2367
|
});
|
|
1442
2368
|
}
|
|
1443
2369
|
return migrateSchema;
|
|
1444
2370
|
};
|
|
1445
|
-
const ensureSchemaExists = (
|
|
2371
|
+
const ensureSchemaExists = () => {
|
|
1446
2372
|
if (!autoGenerateSchema) return Promise.resolve();
|
|
1447
|
-
return migrate(connection);
|
|
2373
|
+
return pool.withConnection((connection) => migrate(connection));
|
|
1448
2374
|
};
|
|
1449
2375
|
return {
|
|
1450
2376
|
async aggregateStream(streamName, options2) {
|
|
2377
|
+
await ensureSchemaExists();
|
|
1451
2378
|
const { evolve, initialState, read } = options2;
|
|
1452
|
-
const expectedStreamVersion = _optionalChain([read, 'optionalAccess',
|
|
2379
|
+
const expectedStreamVersion = _optionalChain([read, 'optionalAccess', _119 => _119.expectedStreamVersion]);
|
|
1453
2380
|
let state = initialState();
|
|
1454
2381
|
if (typeof streamName !== "string") {
|
|
1455
2382
|
throw new Error("Stream name is not string");
|
|
1456
2383
|
}
|
|
1457
|
-
const result = await
|
|
1458
|
-
|
|
2384
|
+
const result = await readStream(
|
|
2385
|
+
pool.execute,
|
|
2386
|
+
streamName,
|
|
2387
|
+
{ ...read, serializer: _nullishCoalesce(_optionalChain([read, 'optionalAccess', _120 => _120.serialization, 'optionalAccess', _121 => _121.serializer]), () => ( serializer)) }
|
|
1459
2388
|
);
|
|
1460
2389
|
const currentStreamVersion = result.currentStreamVersion;
|
|
1461
2390
|
assertExpectedVersionMatchesCurrent(
|
|
@@ -1473,31 +2402,40 @@ var getSQLiteEventStore = (options) => {
|
|
|
1473
2402
|
streamExists: result.streamExists
|
|
1474
2403
|
};
|
|
1475
2404
|
},
|
|
1476
|
-
readStream: async (streamName,
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
2405
|
+
readStream: async (streamName, readOptions) => {
|
|
2406
|
+
await ensureSchemaExists();
|
|
2407
|
+
return readStream(pool.execute, streamName, {
|
|
2408
|
+
...readOptions,
|
|
2409
|
+
serializer: _nullishCoalesce(_optionalChain([options, 'access', _122 => _122.serialization, 'optionalAccess', _123 => _123.serializer]), () => ( serializer))
|
|
2410
|
+
});
|
|
2411
|
+
},
|
|
2412
|
+
appendToStream: async (streamName, events, appendOptions) => {
|
|
2413
|
+
await ensureSchemaExists();
|
|
1480
2414
|
const [firstPart, ...rest] = streamName.split("-");
|
|
1481
2415
|
const streamType = firstPart && rest.length > 0 ? firstPart : unknownTag2;
|
|
1482
|
-
const appendResult = await withConnection(
|
|
2416
|
+
const appendResult = await pool.withConnection(
|
|
1483
2417
|
(connection) => appendToStream(connection, streamName, streamType, events, {
|
|
1484
|
-
...
|
|
2418
|
+
...appendOptions,
|
|
1485
2419
|
onBeforeCommit: async (messages, context) => {
|
|
1486
2420
|
if (inlineProjections.length > 0)
|
|
1487
2421
|
await handleProjections({
|
|
1488
2422
|
projections: inlineProjections,
|
|
1489
2423
|
events: messages,
|
|
1490
|
-
|
|
2424
|
+
execute: context.connection.execute,
|
|
2425
|
+
connection: context.connection,
|
|
2426
|
+
driverType: options.driver.driverType
|
|
1491
2427
|
});
|
|
1492
|
-
if (onBeforeCommitHook)
|
|
2428
|
+
if (onBeforeCommitHook)
|
|
2429
|
+
await onBeforeCommitHook(messages, context);
|
|
1493
2430
|
}
|
|
1494
|
-
})
|
|
2431
|
+
}),
|
|
2432
|
+
{ readonly: false }
|
|
1495
2433
|
);
|
|
1496
2434
|
if (!appendResult.success)
|
|
1497
2435
|
throw new ExpectedVersionConflictError(
|
|
1498
2436
|
-1n,
|
|
1499
2437
|
//TODO: Return actual version in case of error
|
|
1500
|
-
_nullishCoalesce(_optionalChain([
|
|
2438
|
+
_nullishCoalesce(_optionalChain([appendOptions, 'optionalAccess', _124 => _124.expectedStreamVersion]), () => ( NO_CONCURRENCY_CHECK))
|
|
1501
2439
|
);
|
|
1502
2440
|
return {
|
|
1503
2441
|
nextExpectedStreamVersion: appendResult.nextStreamPosition,
|
|
@@ -1505,16 +2443,41 @@ var getSQLiteEventStore = (options) => {
|
|
|
1505
2443
|
createdNewStream: appendResult.nextStreamPosition >= BigInt(events.length)
|
|
1506
2444
|
};
|
|
1507
2445
|
},
|
|
1508
|
-
streamExists(streamName, options2) {
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
);
|
|
2446
|
+
async streamExists(streamName, options2) {
|
|
2447
|
+
await ensureSchemaExists();
|
|
2448
|
+
return streamExists(pool.execute, streamName, options2);
|
|
1512
2449
|
},
|
|
1513
2450
|
consumer: (consumerOptions) => sqliteEventStoreConsumer({
|
|
1514
2451
|
..._nullishCoalesce(options, () => ( {})),
|
|
1515
2452
|
..._nullishCoalesce(consumerOptions, () => ( {})),
|
|
1516
2453
|
pool
|
|
1517
2454
|
}),
|
|
2455
|
+
async withSession(callback) {
|
|
2456
|
+
return await pool.withConnection(async (connection) => {
|
|
2457
|
+
const sessionStore = getSQLiteEventStore({
|
|
2458
|
+
...options,
|
|
2459
|
+
pool: _dumbo.dumbo.call(void 0, {
|
|
2460
|
+
...options.driver.mapToDumboOptions(options),
|
|
2461
|
+
connection,
|
|
2462
|
+
serialization: options.serialization
|
|
2463
|
+
}),
|
|
2464
|
+
transactionOptions: {
|
|
2465
|
+
allowNestedTransactions: true,
|
|
2466
|
+
mode: "session_based"
|
|
2467
|
+
},
|
|
2468
|
+
schema: {
|
|
2469
|
+
...options.schema,
|
|
2470
|
+
autoMigration: "None"
|
|
2471
|
+
},
|
|
2472
|
+
serialization: options.serialization
|
|
2473
|
+
});
|
|
2474
|
+
await ensureSchemaExists();
|
|
2475
|
+
return callback({
|
|
2476
|
+
eventStore: sessionStore,
|
|
2477
|
+
close: () => Promise.resolve()
|
|
2478
|
+
});
|
|
2479
|
+
});
|
|
2480
|
+
},
|
|
1518
2481
|
close: () => pool.close(),
|
|
1519
2482
|
schema: {
|
|
1520
2483
|
sql: () => schemaSQL.join(""),
|
|
@@ -1524,133 +2487,222 @@ var getSQLiteEventStore = (options) => {
|
|
|
1524
2487
|
};
|
|
1525
2488
|
};
|
|
1526
2489
|
|
|
1527
|
-
// src/eventStore/
|
|
1528
|
-
var
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
2490
|
+
// src/eventStore/schema/readStream.ts
|
|
2491
|
+
var { identifier: identifier6 } = _dumbo.SQL;
|
|
2492
|
+
var readStream = async (execute, streamId, options) => {
|
|
2493
|
+
const { serializer } = options;
|
|
2494
|
+
const fromCondition = options.from ? _dumbo.SQL`AND stream_position >= ${options.from}` : _dumbo.SQL.EMPTY;
|
|
2495
|
+
const to = Number(
|
|
2496
|
+
_nullishCoalesce(_optionalChain([options, 'optionalAccess', _125 => _125.to]), () => ( (_optionalChain([options, 'optionalAccess', _126 => _126.maxCount]) ? (_nullishCoalesce(options.from, () => ( 0n))) + options.maxCount : NaN)))
|
|
2497
|
+
);
|
|
2498
|
+
const toCondition = !isNaN(to) ? _dumbo.SQL`AND stream_position <= ${to}` : _dumbo.SQL.EMPTY;
|
|
2499
|
+
const { rows: results } = await execute.query(
|
|
2500
|
+
_dumbo.SQL`SELECT stream_id, stream_position, global_position, message_data, message_metadata, message_schema_version, message_type, message_id
|
|
2501
|
+
FROM ${identifier6(messagesTable.name)}
|
|
2502
|
+
WHERE stream_id = ${streamId} AND partition = ${_nullishCoalesce(_optionalChain([options, 'optionalAccess', _127 => _127.partition]), () => ( defaultTag2))} AND is_archived = FALSE ${fromCondition} ${toCondition}
|
|
2503
|
+
ORDER BY stream_position ASC`
|
|
2504
|
+
);
|
|
2505
|
+
const messages = results.map((row) => {
|
|
2506
|
+
const rawEvent = {
|
|
2507
|
+
type: row.message_type,
|
|
2508
|
+
data: serializer.deserialize(row.message_data),
|
|
2509
|
+
metadata: serializer.deserialize(row.message_metadata)
|
|
2510
|
+
};
|
|
2511
|
+
const metadata = {
|
|
2512
|
+
..."metadata" in rawEvent ? _nullishCoalesce(rawEvent.metadata, () => ( {})) : {},
|
|
2513
|
+
messageId: row.message_id,
|
|
2514
|
+
streamName: streamId,
|
|
2515
|
+
streamPosition: BigInt(row.stream_position),
|
|
2516
|
+
globalPosition: BigInt(row.global_position),
|
|
2517
|
+
checkpoint: bigIntProcessorCheckpoint(BigInt(row.global_position))
|
|
2518
|
+
};
|
|
2519
|
+
const event = {
|
|
2520
|
+
...rawEvent,
|
|
2521
|
+
kind: "Event",
|
|
2522
|
+
metadata
|
|
2523
|
+
};
|
|
2524
|
+
return upcastRecordedMessage(event, _optionalChain([options, 'optionalAccess', _128 => _128.schema, 'optionalAccess', _129 => _129.versioning]));
|
|
2525
|
+
});
|
|
2526
|
+
return messages.length > 0 ? {
|
|
2527
|
+
currentStreamVersion: messages[messages.length - 1].metadata.streamPosition,
|
|
2528
|
+
events: messages,
|
|
2529
|
+
streamExists: true
|
|
2530
|
+
} : {
|
|
2531
|
+
currentStreamVersion: SQLiteEventStoreDefaultStreamVersion,
|
|
2532
|
+
events: [],
|
|
2533
|
+
streamExists: false
|
|
2534
|
+
};
|
|
2535
|
+
};
|
|
2536
|
+
|
|
2537
|
+
// src/eventStore/schema/storeProcessorCheckpoint.ts
|
|
2538
|
+
|
|
2539
|
+
|
|
2540
|
+
|
|
2541
|
+
|
|
2542
|
+
|
|
2543
|
+
|
|
2544
|
+
var { identifier: identifier7 } = _dumbo.SQL;
|
|
2545
|
+
async function storeSubscriptionCheckpointSQLite(execute, processorId, version, position, checkPosition, partition, processorInstanceId) {
|
|
2546
|
+
processorInstanceId ??= unknownTag2;
|
|
2547
|
+
if (checkPosition !== null) {
|
|
2548
|
+
const updateResult = await execute.command(
|
|
2549
|
+
_dumbo.SQL`
|
|
2550
|
+
UPDATE ${identifier7(processorsTable.name)}
|
|
2551
|
+
SET
|
|
2552
|
+
last_processed_checkpoint = ${position},
|
|
2553
|
+
processor_instance_id = ${processorInstanceId}
|
|
2554
|
+
WHERE processor_id = ${processorId}
|
|
2555
|
+
AND last_processed_checkpoint = ${checkPosition}
|
|
2556
|
+
AND partition = ${partition}
|
|
2557
|
+
`
|
|
2558
|
+
);
|
|
2559
|
+
if (updateResult.rowCount && updateResult.rowCount > 0) {
|
|
2560
|
+
return 1;
|
|
2561
|
+
}
|
|
2562
|
+
const current_position = await _dumbo.singleOrNull.call(void 0,
|
|
2563
|
+
execute.query(
|
|
2564
|
+
_dumbo.SQL`
|
|
2565
|
+
SELECT last_processed_checkpoint FROM ${identifier7(processorsTable.name)}
|
|
2566
|
+
WHERE processor_id = ${processorId} AND partition = ${partition}`
|
|
2567
|
+
)
|
|
2568
|
+
);
|
|
2569
|
+
const currentPosition = current_position && _optionalChain([current_position, 'optionalAccess', _130 => _130.last_processed_checkpoint]) !== null ? current_position.last_processed_checkpoint : null;
|
|
2570
|
+
if (currentPosition === position) {
|
|
2571
|
+
return 0;
|
|
2572
|
+
} else if (position !== null && currentPosition !== null && currentPosition > position) {
|
|
2573
|
+
return 2;
|
|
2574
|
+
} else {
|
|
2575
|
+
return 2;
|
|
2576
|
+
}
|
|
2577
|
+
} else {
|
|
2578
|
+
try {
|
|
2579
|
+
await execute.command(
|
|
2580
|
+
_dumbo.SQL`INSERT INTO ${identifier7(processorsTable.name)} (processor_id, version, last_processed_checkpoint, partition, processor_instance_id)
|
|
2581
|
+
VALUES (${processorId}, ${version}, ${position}, ${partition}, ${processorInstanceId})`
|
|
2582
|
+
);
|
|
2583
|
+
return 1;
|
|
2584
|
+
} catch (err) {
|
|
2585
|
+
if (!_dumbo.DumboError.isInstanceOf(err, {
|
|
2586
|
+
errorType: _dumbo.UniqueConstraintError.ErrorType
|
|
2587
|
+
})) {
|
|
2588
|
+
throw err;
|
|
2589
|
+
}
|
|
2590
|
+
const current = await _dumbo.singleOrNull.call(void 0,
|
|
2591
|
+
execute.query(
|
|
2592
|
+
_dumbo.SQL`
|
|
2593
|
+
SELECT last_processed_checkpoint FROM ${identifier7(processorsTable.name)}
|
|
2594
|
+
WHERE processor_id = ${processorId} AND partition = ${partition}`
|
|
2595
|
+
)
|
|
2596
|
+
);
|
|
2597
|
+
const currentPosition = current && _optionalChain([current, 'optionalAccess', _131 => _131.last_processed_checkpoint]) !== null ? BigInt(current.last_processed_checkpoint) : null;
|
|
2598
|
+
if (currentPosition === position) {
|
|
2599
|
+
return 0;
|
|
2600
|
+
} else {
|
|
2601
|
+
return 2;
|
|
2602
|
+
}
|
|
1626
2603
|
}
|
|
1627
2604
|
}
|
|
1628
|
-
}
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
2605
|
+
}
|
|
2606
|
+
async function storeProcessorCheckpoint(execute, options) {
|
|
2607
|
+
try {
|
|
2608
|
+
const result = await storeSubscriptionCheckpointSQLite(
|
|
2609
|
+
execute,
|
|
2610
|
+
options.processorId,
|
|
2611
|
+
_nullishCoalesce(options.version, () => ( 1)),
|
|
2612
|
+
options.newCheckpoint,
|
|
2613
|
+
options.lastProcessedCheckpoint,
|
|
2614
|
+
_nullishCoalesce(options.partition, () => ( defaultTag2))
|
|
2615
|
+
);
|
|
2616
|
+
return result === 1 ? { success: true, newCheckpoint: options.newCheckpoint } : { success: false, reason: result === 0 ? "IGNORED" : "MISMATCH" };
|
|
2617
|
+
} catch (error) {
|
|
2618
|
+
console.log(error);
|
|
2619
|
+
throw error;
|
|
2620
|
+
}
|
|
2621
|
+
}
|
|
2622
|
+
|
|
2623
|
+
// src/eventStore/schema/streamExists.ts
|
|
2624
|
+
|
|
2625
|
+
var streamExists = (execute, streamId, options) => _dumbo.exists.call(void 0,
|
|
2626
|
+
execute.query(
|
|
2627
|
+
_dumbo.SQL`SELECT EXISTS (
|
|
2628
|
+
SELECT 1
|
|
2629
|
+
from ${_dumbo.SQL.identifier(streamsTable.name)}
|
|
2630
|
+
WHERE stream_id = ${streamId} AND partition = ${_nullishCoalesce(_optionalChain([options, 'optionalAccess', _132 => _132.partition]), () => ( defaultTag2))} AND is_archived = FALSE) as exists
|
|
2631
|
+
`
|
|
2632
|
+
)
|
|
2633
|
+
);
|
|
2634
|
+
|
|
2635
|
+
// src/eventStore/schema/tables.ts
|
|
2636
|
+
|
|
2637
|
+
var { identifier: identifier8, plain: plain2 } = _dumbo.SQL;
|
|
2638
|
+
var streamsTableSQL = _dumbo.SQL`CREATE TABLE IF NOT EXISTS ${identifier8(streamsTable.name)}(
|
|
2639
|
+
stream_id TEXT NOT NULL,
|
|
2640
|
+
stream_position BIGINT NOT NULL DEFAULT 0,
|
|
2641
|
+
partition TEXT NOT NULL DEFAULT '${plain2(globalTag)}',
|
|
2642
|
+
stream_type TEXT NOT NULL,
|
|
2643
|
+
stream_metadata JSONB NOT NULL,
|
|
2644
|
+
is_archived BOOLEAN NOT NULL DEFAULT FALSE,
|
|
2645
|
+
PRIMARY KEY (stream_id, partition, is_archived),
|
|
2646
|
+
UNIQUE (stream_id, partition, is_archived)
|
|
2647
|
+
);`;
|
|
2648
|
+
var messagesTableSQL = _dumbo.SQL`CREATE TABLE IF NOT EXISTS ${identifier8(messagesTable.name)}(
|
|
2649
|
+
stream_id TEXT NOT NULL,
|
|
2650
|
+
stream_position BIGINT NOT NULL,
|
|
2651
|
+
partition TEXT NOT NULL DEFAULT '${plain2(globalTag)}',
|
|
2652
|
+
message_kind CHAR(1) NOT NULL DEFAULT 'E',
|
|
2653
|
+
message_data JSONB NOT NULL,
|
|
2654
|
+
message_metadata JSONB NOT NULL,
|
|
2655
|
+
message_schema_version TEXT NOT NULL,
|
|
2656
|
+
message_type TEXT NOT NULL,
|
|
2657
|
+
message_id TEXT NOT NULL,
|
|
2658
|
+
is_archived BOOLEAN NOT NULL DEFAULT FALSE,
|
|
2659
|
+
global_position INTEGER PRIMARY KEY,
|
|
2660
|
+
created DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
2661
|
+
UNIQUE (stream_id, stream_position, partition, is_archived)
|
|
2662
|
+
);
|
|
2663
|
+
`;
|
|
2664
|
+
var processorsTableSQL = _dumbo.SQL`
|
|
2665
|
+
CREATE TABLE IF NOT EXISTS ${_dumbo.SQL.identifier(processorsTable.name)}(
|
|
2666
|
+
processor_id TEXT NOT NULL,
|
|
2667
|
+
version INTEGER NOT NULL DEFAULT 1,
|
|
2668
|
+
partition TEXT NOT NULL DEFAULT '${plain2(globalTag)}',
|
|
2669
|
+
status TEXT NOT NULL DEFAULT 'stopped',
|
|
2670
|
+
last_processed_checkpoint TEXT NOT NULL,
|
|
2671
|
+
processor_instance_id TEXT DEFAULT '${plain2(unknownTag2)}',
|
|
2672
|
+
PRIMARY KEY (processor_id, partition, version)
|
|
2673
|
+
);
|
|
2674
|
+
`;
|
|
2675
|
+
var projectionsTableSQL = _dumbo.SQL`
|
|
2676
|
+
CREATE TABLE IF NOT EXISTS ${_dumbo.SQL.identifier(projectionsTable.name)}(
|
|
2677
|
+
name TEXT NOT NULL,
|
|
2678
|
+
version INTEGER NOT NULL DEFAULT 1,
|
|
2679
|
+
partition TEXT NOT NULL DEFAULT '${plain2(globalTag)}',
|
|
2680
|
+
type CHAR(1) NOT NULL,
|
|
2681
|
+
kind TEXT NOT NULL,
|
|
2682
|
+
status TEXT NOT NULL,
|
|
2683
|
+
definition JSONB NOT NULL DEFAULT '{}',
|
|
2684
|
+
PRIMARY KEY (name, partition, version)
|
|
2685
|
+
);
|
|
2686
|
+
`;
|
|
2687
|
+
var schemaSQL = [
|
|
2688
|
+
streamsTableSQL,
|
|
2689
|
+
messagesTableSQL,
|
|
2690
|
+
processorsTableSQL,
|
|
2691
|
+
projectionsTableSQL
|
|
2692
|
+
];
|
|
2693
|
+
var createEventStoreSchema = async (pool, hooks) => {
|
|
2694
|
+
await pool.withTransaction(async (tx) => {
|
|
2695
|
+
await migration_0_42_0_FromSubscriptionsToProcessors(tx.execute);
|
|
2696
|
+
if (_optionalChain([hooks, 'optionalAccess', _133 => _133.onBeforeSchemaCreated])) {
|
|
2697
|
+
await hooks.onBeforeSchemaCreated({
|
|
2698
|
+
connection: tx.connection
|
|
2699
|
+
});
|
|
1635
2700
|
}
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
return events.map((e) => eventInStream(streamName, e));
|
|
1640
|
-
};
|
|
1641
|
-
var newEventsInStream = eventsInStream;
|
|
1642
|
-
var assertSQLQueryResultMatches = (sql, rows) => async ({
|
|
1643
|
-
connection
|
|
1644
|
-
}) => {
|
|
1645
|
-
const result = await connection.execute.query(sql);
|
|
1646
|
-
assertThatArray(rows).containsExactlyInAnyOrder(result.rows);
|
|
1647
|
-
};
|
|
1648
|
-
var expectSQL = {
|
|
1649
|
-
query: (sql) => ({
|
|
1650
|
-
resultRows: {
|
|
1651
|
-
toBeTheSame: (rows) => assertSQLQueryResultMatches(sql, rows)
|
|
2701
|
+
await tx.execute.batchCommand(schemaSQL);
|
|
2702
|
+
if (_optionalChain([hooks, 'optionalAccess', _134 => _134.onAfterSchemaCreated])) {
|
|
2703
|
+
await hooks.onAfterSchemaCreated();
|
|
1652
2704
|
}
|
|
1653
|
-
})
|
|
2705
|
+
});
|
|
1654
2706
|
};
|
|
1655
2707
|
|
|
1656
2708
|
|
|
@@ -1691,5 +2743,14 @@ var expectSQL = {
|
|
|
1691
2743
|
|
|
1692
2744
|
|
|
1693
2745
|
|
|
1694
|
-
|
|
2746
|
+
|
|
2747
|
+
|
|
2748
|
+
|
|
2749
|
+
|
|
2750
|
+
|
|
2751
|
+
|
|
2752
|
+
|
|
2753
|
+
|
|
2754
|
+
|
|
2755
|
+
exports.SQLiteEventStoreDefaultStreamVersion = SQLiteEventStoreDefaultStreamVersion; exports.SQLiteProjectionSpec = SQLiteProjectionSpec; exports.appendToStream = appendToStream; exports.assertSQLQueryResultMatches = assertSQLQueryResultMatches; exports.createEventStoreSchema = createEventStoreSchema; exports.defaultTag = defaultTag2; exports.documentDoesNotExist = documentDoesNotExist; exports.documentExists = documentExists; exports.documentMatchingExists = documentMatchingExists; exports.documentsAreTheSame = documentsAreTheSame; exports.documentsMatchingHaveCount = documentsMatchingHaveCount; exports.emmettPrefix = emmettPrefix2; exports.eventInStream = eventInStream; exports.eventsInStream = eventsInStream; exports.expectPongoDocuments = expectPongoDocuments; exports.expectSQL = expectSQL; exports.getSQLiteEventStore = getSQLiteEventStore; exports.globalNames = globalNames; exports.globalTag = globalTag; exports.handleProjections = handleProjections; exports.messagesTable = messagesTable; exports.messagesTableSQL = messagesTableSQL; exports.migration_0_42_0_FromSubscriptionsToProcessors = migration_0_42_0_FromSubscriptionsToProcessors; exports.migration_0_42_0_SQLs = migration_0_42_0_SQLs; exports.newEventsInStream = newEventsInStream; exports.pongoMultiStreamProjection = pongoMultiStreamProjection; exports.pongoProjection = pongoProjection; exports.pongoSingleStreamProjection = pongoSingleStreamProjection; exports.processorsTable = processorsTable; exports.processorsTableSQL = processorsTableSQL; exports.projectionsTable = projectionsTable; exports.projectionsTableSQL = projectionsTableSQL; exports.readLastMessageGlobalPosition = readLastMessageGlobalPosition; exports.readMessagesBatch = readMessagesBatch; exports.readProcessorCheckpoint = readProcessorCheckpoint; exports.readStream = readStream; exports.schemaSQL = schemaSQL; exports.schema_0_41_0 = schema_0_41_0; exports.schema_0_42_0 = schema_0_42_0; exports.sqliteProjection = sqliteProjection; exports.sqliteRawBatchSQLProjection = sqliteRawBatchSQLProjection; exports.sqliteRawSQLProjection = sqliteRawSQLProjection; exports.storeProcessorCheckpoint = storeProcessorCheckpoint; exports.streamExists = streamExists; exports.streamsTable = streamsTable; exports.streamsTableSQL = streamsTableSQL; exports.unknownTag = unknownTag2;
|
|
1695
2756
|
//# sourceMappingURL=index.cjs.map
|