@event-driven-io/emmett-postgresql 0.35.0-alpha.2 → 0.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +359 -188
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +144 -181
- package/dist/index.d.ts +144 -181
- package/dist/index.js +347 -176
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -176,6 +176,108 @@ var JSONParser = {
|
|
|
176
176
|
return options?.map ? options.map(parsed) : parsed;
|
|
177
177
|
}
|
|
178
178
|
};
|
|
179
|
+
var MessageProcessorType = {
|
|
180
|
+
PROJECTOR: "projector",
|
|
181
|
+
REACTOR: "reactor"
|
|
182
|
+
};
|
|
183
|
+
var defaultProcessingMessageProcessingScope = (handler, partialContext) => handler(partialContext);
|
|
184
|
+
var reactor = (options) => {
|
|
185
|
+
const eachMessage = "eachMessage" in options && options.eachMessage ? options.eachMessage : () => Promise.resolve();
|
|
186
|
+
let isActive = true;
|
|
187
|
+
const { checkpoints, processorId, partition } = options;
|
|
188
|
+
const processingScope = options.processingScope ?? defaultProcessingMessageProcessingScope;
|
|
189
|
+
return {
|
|
190
|
+
id: options.processorId,
|
|
191
|
+
type: options.type ?? MessageProcessorType.REACTOR,
|
|
192
|
+
close: () => options.hooks?.onClose ? options.hooks?.onClose() : Promise.resolve(),
|
|
193
|
+
start: async (startOptions) => {
|
|
194
|
+
isActive = true;
|
|
195
|
+
return await processingScope(async (context) => {
|
|
196
|
+
if (options.hooks?.onStart) {
|
|
197
|
+
await options.hooks?.onStart(context);
|
|
198
|
+
}
|
|
199
|
+
if (options.startFrom !== "CURRENT" && options.startFrom)
|
|
200
|
+
return options.startFrom;
|
|
201
|
+
let lastCheckpoint = null;
|
|
202
|
+
if (checkpoints) {
|
|
203
|
+
const readResult = await checkpoints?.read(
|
|
204
|
+
{
|
|
205
|
+
processorId,
|
|
206
|
+
partition
|
|
207
|
+
},
|
|
208
|
+
startOptions
|
|
209
|
+
);
|
|
210
|
+
lastCheckpoint = readResult.lastCheckpoint;
|
|
211
|
+
}
|
|
212
|
+
if (lastCheckpoint === null) return "BEGINNING";
|
|
213
|
+
return {
|
|
214
|
+
lastCheckpoint
|
|
215
|
+
};
|
|
216
|
+
}, startOptions);
|
|
217
|
+
},
|
|
218
|
+
get isActive() {
|
|
219
|
+
return isActive;
|
|
220
|
+
},
|
|
221
|
+
handle: async (messages, partialContext) => {
|
|
222
|
+
if (!isActive) return Promise.resolve();
|
|
223
|
+
return await processingScope(async (context) => {
|
|
224
|
+
let result = void 0;
|
|
225
|
+
let lastCheckpoint = null;
|
|
226
|
+
for (const message2 of messages) {
|
|
227
|
+
const messageProcessingResult = await eachMessage(message2, context);
|
|
228
|
+
if (checkpoints) {
|
|
229
|
+
const storeCheckpointResult = await checkpoints.store(
|
|
230
|
+
{
|
|
231
|
+
processorId: options.processorId,
|
|
232
|
+
version: options.version,
|
|
233
|
+
message: message2,
|
|
234
|
+
lastCheckpoint,
|
|
235
|
+
partition: options.partition
|
|
236
|
+
},
|
|
237
|
+
context
|
|
238
|
+
);
|
|
239
|
+
if (storeCheckpointResult && storeCheckpointResult.success) {
|
|
240
|
+
lastCheckpoint = storeCheckpointResult.newCheckpoint;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
if (messageProcessingResult && messageProcessingResult.type === "STOP") {
|
|
244
|
+
isActive = false;
|
|
245
|
+
result = messageProcessingResult;
|
|
246
|
+
break;
|
|
247
|
+
}
|
|
248
|
+
if (options.stopAfter && options.stopAfter(message2)) {
|
|
249
|
+
isActive = false;
|
|
250
|
+
result = { type: "STOP", reason: "Stop condition reached" };
|
|
251
|
+
break;
|
|
252
|
+
}
|
|
253
|
+
if (messageProcessingResult && messageProcessingResult.type === "SKIP")
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
return result;
|
|
257
|
+
}, partialContext);
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
};
|
|
261
|
+
var projector = (options) => {
|
|
262
|
+
const { projection: projection2, ...rest } = options;
|
|
263
|
+
return reactor({
|
|
264
|
+
...rest,
|
|
265
|
+
type: MessageProcessorType.PROJECTOR,
|
|
266
|
+
processorId: options.processorId ?? `projection:${projection2.name}`,
|
|
267
|
+
hooks: {
|
|
268
|
+
onStart: options.truncateOnStart && options.projection.truncate || options.hooks?.onStart ? async (context) => {
|
|
269
|
+
if (options.truncateOnStart && options.projection.truncate)
|
|
270
|
+
await options.projection.truncate(context);
|
|
271
|
+
if (options.hooks?.onStart) await options.hooks?.onStart(context);
|
|
272
|
+
} : void 0,
|
|
273
|
+
onClose: options.hooks?.onClose
|
|
274
|
+
},
|
|
275
|
+
eachMessage: async (event2, context) => {
|
|
276
|
+
if (!projection2.canHandle.includes(event2.type)) return;
|
|
277
|
+
await projection2.handle([event2], context);
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
};
|
|
179
281
|
var projection = (definition) => definition;
|
|
180
282
|
var filter = (filter2) => new TransformStream3({
|
|
181
283
|
transform(chunk, controller) {
|
|
@@ -502,7 +604,7 @@ var readMessagesBatch = async (execute, options) => {
|
|
|
502
604
|
const fromCondition = from !== -0n ? `AND global_position >= ${from}` : "";
|
|
503
605
|
const toCondition = "to" in options ? `AND global_position <= ${options.to}` : "";
|
|
504
606
|
const limitCondition = "batchSize" in options ? `LIMIT ${options.batchSize}` : "";
|
|
505
|
-
const
|
|
607
|
+
const messages = await mapRows(
|
|
506
608
|
execute.query(
|
|
507
609
|
sql2(
|
|
508
610
|
`SELECT stream_id, stream_position, global_position, message_data, message_metadata, message_schema_version, message_type, message_id
|
|
@@ -533,14 +635,14 @@ var readMessagesBatch = async (execute, options) => {
|
|
|
533
635
|
};
|
|
534
636
|
}
|
|
535
637
|
);
|
|
536
|
-
return
|
|
537
|
-
currentGlobalPosition:
|
|
538
|
-
messages
|
|
539
|
-
|
|
638
|
+
return messages.length > 0 ? {
|
|
639
|
+
currentGlobalPosition: messages[messages.length - 1].metadata.globalPosition,
|
|
640
|
+
messages,
|
|
641
|
+
areMessagesLeft: messages.length === batchSize
|
|
540
642
|
} : {
|
|
541
643
|
currentGlobalPosition: "from" in options ? options.from : "after" in options ? options.after : 0n,
|
|
542
644
|
messages: [],
|
|
543
|
-
|
|
645
|
+
areMessagesLeft: false
|
|
544
646
|
};
|
|
545
647
|
};
|
|
546
648
|
|
|
@@ -551,21 +653,22 @@ var postgreSQLEventStoreMessageBatchPuller = ({
|
|
|
551
653
|
executor,
|
|
552
654
|
batchSize,
|
|
553
655
|
eachBatch,
|
|
554
|
-
pullingFrequencyInMs
|
|
656
|
+
pullingFrequencyInMs,
|
|
657
|
+
stopWhen
|
|
555
658
|
}) => {
|
|
556
659
|
let isRunning = false;
|
|
557
660
|
let start;
|
|
558
661
|
const pullMessages = async (options) => {
|
|
559
|
-
const after = options.startFrom === "BEGINNING" ? 0n : options.startFrom === "END" ? (await readLastMessageGlobalPosition(executor)).currentGlobalPosition ?? 0n : options.startFrom.
|
|
662
|
+
const after = options.startFrom === "BEGINNING" ? 0n : options.startFrom === "END" ? (await readLastMessageGlobalPosition(executor)).currentGlobalPosition ?? 0n : options.startFrom.lastCheckpoint;
|
|
560
663
|
const readMessagesOptions = {
|
|
561
664
|
after,
|
|
562
665
|
batchSize
|
|
563
666
|
};
|
|
564
667
|
let waitTime = 100;
|
|
565
668
|
do {
|
|
566
|
-
const { messages, currentGlobalPosition,
|
|
669
|
+
const { messages, currentGlobalPosition, areMessagesLeft } = await readMessagesBatch(executor, readMessagesOptions);
|
|
567
670
|
if (messages.length > 0) {
|
|
568
|
-
const result = await eachBatch(
|
|
671
|
+
const result = await eachBatch(messages);
|
|
569
672
|
if (result && result.type === "STOP") {
|
|
570
673
|
isRunning = false;
|
|
571
674
|
break;
|
|
@@ -573,7 +676,11 @@ var postgreSQLEventStoreMessageBatchPuller = ({
|
|
|
573
676
|
}
|
|
574
677
|
readMessagesOptions.after = currentGlobalPosition;
|
|
575
678
|
await new Promise((resolve) => setTimeout(resolve, waitTime));
|
|
576
|
-
if (!
|
|
679
|
+
if (stopWhen?.noMessagesLeft === true && !areMessagesLeft) {
|
|
680
|
+
isRunning = false;
|
|
681
|
+
break;
|
|
682
|
+
}
|
|
683
|
+
if (!areMessagesLeft) {
|
|
577
684
|
waitTime = Math.min(waitTime * 2, 1e3);
|
|
578
685
|
} else {
|
|
579
686
|
waitTime = pullingFrequencyInMs;
|
|
@@ -608,6 +715,7 @@ var zipPostgreSQLEventStoreMessageBatchPullerStartFrom = (options) => {
|
|
|
608
715
|
|
|
609
716
|
// src/eventStore/consumers/postgreSQLEventStoreConsumer.ts
|
|
610
717
|
import { dumbo as dumbo2 } from "@event-driven-io/dumbo";
|
|
718
|
+
import { v7 as uuid6 } from "uuid";
|
|
611
719
|
|
|
612
720
|
// src/eventStore/consumers/postgreSQLProcessor.ts
|
|
613
721
|
import {
|
|
@@ -866,7 +974,7 @@ BEGIN
|
|
|
866
974
|
END;
|
|
867
975
|
$$ LANGUAGE plpgsql;
|
|
868
976
|
`);
|
|
869
|
-
async
|
|
977
|
+
var storeProcessorCheckpoint = async (execute, options) => {
|
|
870
978
|
try {
|
|
871
979
|
const { result } = await single2(
|
|
872
980
|
execute.command(
|
|
@@ -885,7 +993,7 @@ async function storeProcessorCheckpoint(execute, options) {
|
|
|
885
993
|
console.log(error);
|
|
886
994
|
throw error;
|
|
887
995
|
}
|
|
888
|
-
}
|
|
996
|
+
};
|
|
889
997
|
|
|
890
998
|
// src/eventStore/schema/tables.ts
|
|
891
999
|
import { rawSql as rawSql2 } from "@event-driven-io/dumbo";
|
|
@@ -1324,120 +1432,114 @@ var createEventStoreSchema = async (pool) => {
|
|
|
1324
1432
|
};
|
|
1325
1433
|
|
|
1326
1434
|
// src/eventStore/consumers/postgreSQLProcessor.ts
|
|
1327
|
-
var
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1435
|
+
var postgreSQLCheckpointer = () => ({
|
|
1436
|
+
read: async (options, context) => {
|
|
1437
|
+
const result = await readProcessorCheckpoint(context.execute, options);
|
|
1438
|
+
return { lastCheckpoint: result?.lastProcessedPosition };
|
|
1439
|
+
},
|
|
1440
|
+
store: async (options, context) => {
|
|
1441
|
+
const result = await storeProcessorCheckpoint(context.execute, {
|
|
1442
|
+
lastProcessedPosition: options.lastCheckpoint,
|
|
1443
|
+
newPosition: options.message.metadata.globalPosition,
|
|
1444
|
+
processorId: options.processorId,
|
|
1445
|
+
partition: options.partition,
|
|
1446
|
+
version: options.version
|
|
1447
|
+
});
|
|
1448
|
+
return result.success ? { success: true, newCheckpoint: result.newPosition } : result;
|
|
1337
1449
|
}
|
|
1338
|
-
};
|
|
1339
|
-
var
|
|
1340
|
-
const
|
|
1341
|
-
|
|
1342
|
-
const
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
const processorConnectionString = "connectionString" in poolOptions ? poolOptions.connectionString : null;
|
|
1346
|
-
const processorPool = "dumbo" in poolOptions ? poolOptions.dumbo : processorConnectionString ? dumbo({
|
|
1347
|
-
connectionString: processorConnectionString,
|
|
1348
|
-
...poolOptions
|
|
1349
|
-
}) : null;
|
|
1350
|
-
const getPool = (context) => {
|
|
1351
|
-
const connectionString = processorConnectionString ?? context.connectionString;
|
|
1450
|
+
});
|
|
1451
|
+
var postgreSQLProcessingScope = (options) => {
|
|
1452
|
+
const processorConnectionString = options.connectionString;
|
|
1453
|
+
const processorPool = options.pool;
|
|
1454
|
+
const processingScope = async (handler, partialContext) => {
|
|
1455
|
+
const connection = partialContext?.connection;
|
|
1456
|
+
const connectionString = processorConnectionString ?? connection?.connectionString;
|
|
1352
1457
|
if (!connectionString)
|
|
1353
1458
|
throw new EmmettError(
|
|
1354
1459
|
`PostgreSQL processor '${options.processorId}' is missing connection string. Ensure that you passed it through options`
|
|
1355
1460
|
);
|
|
1356
|
-
const pool = (!processorConnectionString || connectionString == processorConnectionString ?
|
|
1461
|
+
const pool = (!processorConnectionString || connectionString == processorConnectionString ? connection?.pool : processorPool) ?? processorPool;
|
|
1357
1462
|
if (!pool)
|
|
1358
1463
|
throw new EmmettError(
|
|
1359
1464
|
`PostgreSQL processor '${options.processorId}' is missing connection string. Ensure that you passed it through options`
|
|
1360
1465
|
);
|
|
1361
|
-
return {
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
if (options.startFrom !== "CURRENT") return options.startFrom;
|
|
1371
|
-
const { lastProcessedPosition } = await readProcessorCheckpoint(execute, {
|
|
1372
|
-
processorId: options.processorId,
|
|
1373
|
-
partition: options.partition
|
|
1374
|
-
});
|
|
1375
|
-
if (lastProcessedPosition === null) return "BEGINNING";
|
|
1376
|
-
return { globalPosition: lastProcessedPosition };
|
|
1377
|
-
},
|
|
1378
|
-
get isActive() {
|
|
1379
|
-
return isActive;
|
|
1380
|
-
},
|
|
1381
|
-
handle: async ({ messages }, context) => {
|
|
1382
|
-
if (!isActive) return;
|
|
1383
|
-
const { pool, connectionString } = getPool(context);
|
|
1384
|
-
return pool.withTransaction(async (transaction) => {
|
|
1385
|
-
let result = void 0;
|
|
1386
|
-
let lastProcessedPosition = null;
|
|
1387
|
-
for (const message of messages) {
|
|
1388
|
-
const typedMessage = message;
|
|
1389
|
-
const client = await transaction.connection.open();
|
|
1390
|
-
const messageProcessingResult = await eachMessage(typedMessage, {
|
|
1391
|
-
execute: transaction.execute,
|
|
1392
|
-
connection: {
|
|
1393
|
-
connectionString,
|
|
1394
|
-
pool,
|
|
1395
|
-
transaction,
|
|
1396
|
-
client
|
|
1397
|
-
}
|
|
1398
|
-
});
|
|
1399
|
-
await storeProcessorCheckpoint(transaction.execute, {
|
|
1400
|
-
processorId: options.processorId,
|
|
1401
|
-
version: options.version,
|
|
1402
|
-
lastProcessedPosition,
|
|
1403
|
-
newPosition: typedMessage.metadata.globalPosition,
|
|
1404
|
-
partition: options.partition
|
|
1405
|
-
});
|
|
1406
|
-
lastProcessedPosition = typedMessage.metadata.globalPosition;
|
|
1407
|
-
if (messageProcessingResult && messageProcessingResult.type === "STOP") {
|
|
1408
|
-
isActive = false;
|
|
1409
|
-
result = messageProcessingResult;
|
|
1410
|
-
break;
|
|
1411
|
-
}
|
|
1412
|
-
if (options.stopAfter && options.stopAfter(typedMessage)) {
|
|
1413
|
-
isActive = false;
|
|
1414
|
-
result = { type: "STOP", reason: "Stop condition reached" };
|
|
1415
|
-
break;
|
|
1416
|
-
}
|
|
1417
|
-
if (messageProcessingResult && messageProcessingResult.type === "SKIP")
|
|
1418
|
-
continue;
|
|
1466
|
+
return pool.withTransaction(async (transaction) => {
|
|
1467
|
+
const client = await transaction.connection.open();
|
|
1468
|
+
return handler({
|
|
1469
|
+
execute: transaction.execute,
|
|
1470
|
+
connection: {
|
|
1471
|
+
connectionString,
|
|
1472
|
+
pool,
|
|
1473
|
+
client,
|
|
1474
|
+
transaction
|
|
1419
1475
|
}
|
|
1420
|
-
return result;
|
|
1421
1476
|
});
|
|
1422
|
-
}
|
|
1477
|
+
});
|
|
1423
1478
|
};
|
|
1479
|
+
return processingScope;
|
|
1424
1480
|
};
|
|
1425
|
-
var
|
|
1426
|
-
const
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1481
|
+
var getProcessorPool = (options) => {
|
|
1482
|
+
const poolOptions = {
|
|
1483
|
+
...options.connectionOptions ? options.connectionOptions : {}
|
|
1484
|
+
};
|
|
1485
|
+
const processorConnectionString = "connectionString" in poolOptions ? poolOptions.connectionString ?? null : null;
|
|
1486
|
+
const processorPool = "dumbo" in poolOptions ? poolOptions.dumbo : processorConnectionString ? dumbo({
|
|
1487
|
+
connectionString: processorConnectionString,
|
|
1488
|
+
...poolOptions
|
|
1489
|
+
}) : null;
|
|
1490
|
+
return {
|
|
1491
|
+
pool: processorPool,
|
|
1492
|
+
connectionString: processorConnectionString,
|
|
1493
|
+
close: processorPool != null && !("dumbo" in poolOptions) ? processorPool.close : void 0
|
|
1494
|
+
};
|
|
1495
|
+
};
|
|
1496
|
+
var postgreSQLProjector = (options) => {
|
|
1497
|
+
const { pool, connectionString, close } = getProcessorPool(options);
|
|
1498
|
+
const hooks = {
|
|
1499
|
+
onStart: options.hooks?.onStart,
|
|
1500
|
+
onClose: options.hooks?.onClose || close ? async () => {
|
|
1501
|
+
if (options.hooks?.onClose) await options.hooks?.onClose();
|
|
1502
|
+
if (close) await close();
|
|
1503
|
+
} : void 0
|
|
1504
|
+
};
|
|
1505
|
+
return projector({
|
|
1506
|
+
...options,
|
|
1507
|
+
hooks,
|
|
1508
|
+
processingScope: postgreSQLProcessingScope({
|
|
1509
|
+
pool,
|
|
1510
|
+
connectionString,
|
|
1511
|
+
processorId: options.processorId ?? `projection:${options.projection.name}`
|
|
1512
|
+
}),
|
|
1513
|
+
checkpoints: postgreSQLCheckpointer()
|
|
1514
|
+
});
|
|
1515
|
+
};
|
|
1516
|
+
var postgreSQLReactor = (options) => {
|
|
1517
|
+
const { pool, connectionString, close } = getProcessorPool(options);
|
|
1518
|
+
const hooks = {
|
|
1519
|
+
onStart: options.hooks?.onStart,
|
|
1520
|
+
onClose: options.hooks?.onClose || close ? async () => {
|
|
1521
|
+
if (options.hooks?.onClose) await options.hooks?.onClose();
|
|
1522
|
+
if (close) await close();
|
|
1523
|
+
} : void 0
|
|
1524
|
+
};
|
|
1525
|
+
return reactor({
|
|
1526
|
+
...options,
|
|
1527
|
+
hooks,
|
|
1528
|
+
processingScope: postgreSQLProcessingScope({
|
|
1529
|
+
pool,
|
|
1530
|
+
connectionString,
|
|
1531
|
+
processorId: options.processorId
|
|
1532
|
+
}),
|
|
1533
|
+
checkpoints: postgreSQLCheckpointer()
|
|
1434
1534
|
});
|
|
1435
1535
|
};
|
|
1436
|
-
var
|
|
1536
|
+
var postgreSQLMessageProcessor = (options) => {
|
|
1437
1537
|
if ("projection" in options) {
|
|
1438
|
-
return
|
|
1538
|
+
return postgreSQLProjector(
|
|
1539
|
+
options
|
|
1540
|
+
);
|
|
1439
1541
|
}
|
|
1440
|
-
return
|
|
1542
|
+
return postgreSQLReactor(options);
|
|
1441
1543
|
};
|
|
1442
1544
|
|
|
1443
1545
|
// src/eventStore/consumers/postgreSQLEventStoreConsumer.ts
|
|
@@ -1458,8 +1560,10 @@ var postgreSQLEventStoreConsumer = (options) => {
|
|
|
1458
1560
|
const result = await Promise.allSettled(
|
|
1459
1561
|
activeProcessors.map((s) => {
|
|
1460
1562
|
return s.handle(messagesBatch, {
|
|
1461
|
-
|
|
1462
|
-
|
|
1563
|
+
connection: {
|
|
1564
|
+
connectionString: options.connectionString,
|
|
1565
|
+
pool
|
|
1566
|
+
}
|
|
1463
1567
|
});
|
|
1464
1568
|
})
|
|
1465
1569
|
);
|
|
@@ -1470,6 +1574,7 @@ var postgreSQLEventStoreConsumer = (options) => {
|
|
|
1470
1574
|
};
|
|
1471
1575
|
};
|
|
1472
1576
|
const messagePooler = currentMessagePuller = postgreSQLEventStoreMessageBatchPuller({
|
|
1577
|
+
stopWhen: options.stopWhen,
|
|
1473
1578
|
executor: pool.execute,
|
|
1474
1579
|
eachBatch,
|
|
1475
1580
|
batchSize: pulling?.batchSize ?? DefaultPostgreSQLEventStoreProcessorBatchSize,
|
|
@@ -1483,15 +1588,20 @@ var postgreSQLEventStoreConsumer = (options) => {
|
|
|
1483
1588
|
currentMessagePuller = void 0;
|
|
1484
1589
|
}
|
|
1485
1590
|
await start;
|
|
1591
|
+
await Promise.all(processors.map((p) => p.close()));
|
|
1486
1592
|
};
|
|
1487
1593
|
return {
|
|
1488
|
-
|
|
1594
|
+
consumerId: options.consumerId ?? uuid6(),
|
|
1489
1595
|
get isRunning() {
|
|
1490
1596
|
return isRunning;
|
|
1491
1597
|
},
|
|
1598
|
+
processors,
|
|
1492
1599
|
processor: (options2) => {
|
|
1493
|
-
const processor =
|
|
1494
|
-
processors.push(
|
|
1600
|
+
const processor = postgreSQLMessageProcessor(options2);
|
|
1601
|
+
processors.push(
|
|
1602
|
+
// TODO: change that
|
|
1603
|
+
processor
|
|
1604
|
+
);
|
|
1495
1605
|
return processor;
|
|
1496
1606
|
},
|
|
1497
1607
|
start: () => {
|
|
@@ -1505,7 +1615,18 @@ var postgreSQLEventStoreConsumer = (options) => {
|
|
|
1505
1615
|
);
|
|
1506
1616
|
isRunning = true;
|
|
1507
1617
|
const startFrom = zipPostgreSQLEventStoreMessageBatchPullerStartFrom(
|
|
1508
|
-
await Promise.all(
|
|
1618
|
+
await Promise.all(
|
|
1619
|
+
processors.map(async (o) => {
|
|
1620
|
+
const result = await o.start({
|
|
1621
|
+
execute: pool.execute,
|
|
1622
|
+
connection: {
|
|
1623
|
+
connectionString: options.connectionString,
|
|
1624
|
+
pool
|
|
1625
|
+
}
|
|
1626
|
+
});
|
|
1627
|
+
return result;
|
|
1628
|
+
})
|
|
1629
|
+
)
|
|
1509
1630
|
);
|
|
1510
1631
|
return messagePooler.start({ startFrom });
|
|
1511
1632
|
})();
|
|
@@ -1519,18 +1640,114 @@ var postgreSQLEventStoreConsumer = (options) => {
|
|
|
1519
1640
|
};
|
|
1520
1641
|
};
|
|
1521
1642
|
|
|
1522
|
-
// src/eventStore/
|
|
1523
|
-
import "
|
|
1643
|
+
// src/eventStore/consumers/rebuildPostgreSQLProjections.ts
|
|
1644
|
+
import { v7 as uuid7 } from "uuid";
|
|
1645
|
+
var rebuildPostgreSQLProjections = (options) => {
|
|
1646
|
+
const consumer = postgreSQLEventStoreConsumer({
|
|
1647
|
+
...options,
|
|
1648
|
+
stopWhen: { noMessagesLeft: true }
|
|
1649
|
+
});
|
|
1650
|
+
const projections = "projections" in options ? options.projections.map(
|
|
1651
|
+
(p) => "projection" in p ? {
|
|
1652
|
+
...p,
|
|
1653
|
+
processorId: `projection:${p.projection.name ?? uuid7()}-rebuild`,
|
|
1654
|
+
truncateOnStart: p.truncateOnStart ?? true
|
|
1655
|
+
} : {
|
|
1656
|
+
projection: p,
|
|
1657
|
+
processorId: `projection:${p.name ?? uuid7()}-rebuild`,
|
|
1658
|
+
truncateOnStart: true
|
|
1659
|
+
}
|
|
1660
|
+
) : [options];
|
|
1661
|
+
for (const projectionDefinition of projections) {
|
|
1662
|
+
consumer.processor({
|
|
1663
|
+
...projectionDefinition,
|
|
1664
|
+
processorId: projectionDefinition.processorId ?? `projection:${projectionDefinition.projection.name ?? uuid7()}-rebuild`,
|
|
1665
|
+
truncateOnStart: projectionDefinition.truncateOnStart ?? true
|
|
1666
|
+
});
|
|
1667
|
+
}
|
|
1668
|
+
return consumer;
|
|
1669
|
+
};
|
|
1670
|
+
|
|
1671
|
+
// src/eventStore/projections/pongo/pongoProjections.ts
|
|
1672
|
+
import {
|
|
1673
|
+
pongoClient
|
|
1674
|
+
} from "@event-driven-io/pongo";
|
|
1675
|
+
var pongoProjection = ({
|
|
1676
|
+
truncate,
|
|
1677
|
+
handle,
|
|
1678
|
+
canHandle
|
|
1679
|
+
}) => postgreSQLProjection({
|
|
1680
|
+
canHandle,
|
|
1681
|
+
handle: async (events, context) => {
|
|
1682
|
+
const {
|
|
1683
|
+
connection: { connectionString, client, pool }
|
|
1684
|
+
} = context;
|
|
1685
|
+
const pongo = pongoClient(connectionString, {
|
|
1686
|
+
connectionOptions: { client, pool }
|
|
1687
|
+
});
|
|
1688
|
+
await handle(events, {
|
|
1689
|
+
...context,
|
|
1690
|
+
pongo
|
|
1691
|
+
});
|
|
1692
|
+
},
|
|
1693
|
+
truncate: truncate ? (context) => {
|
|
1694
|
+
const {
|
|
1695
|
+
connection: { connectionString, client, pool }
|
|
1696
|
+
} = context;
|
|
1697
|
+
const pongo = pongoClient(connectionString, {
|
|
1698
|
+
connectionOptions: { client, pool }
|
|
1699
|
+
});
|
|
1700
|
+
return truncate({
|
|
1701
|
+
...context,
|
|
1702
|
+
pongo
|
|
1703
|
+
});
|
|
1704
|
+
} : void 0
|
|
1705
|
+
});
|
|
1706
|
+
var pongoMultiStreamProjection = (options) => {
|
|
1707
|
+
const { collectionName, getDocumentId, canHandle } = options;
|
|
1708
|
+
return pongoProjection({
|
|
1709
|
+
handle: async (events, { pongo }) => {
|
|
1710
|
+
const collection = pongo.db().collection(collectionName);
|
|
1711
|
+
for (const event of events) {
|
|
1712
|
+
await collection.handle(getDocumentId(event), async (document) => {
|
|
1713
|
+
return "initialState" in options ? await options.evolve(
|
|
1714
|
+
document ?? options.initialState(),
|
|
1715
|
+
event
|
|
1716
|
+
) : await options.evolve(
|
|
1717
|
+
document,
|
|
1718
|
+
event
|
|
1719
|
+
);
|
|
1720
|
+
});
|
|
1721
|
+
}
|
|
1722
|
+
},
|
|
1723
|
+
canHandle,
|
|
1724
|
+
truncate: async (context) => {
|
|
1725
|
+
const {
|
|
1726
|
+
connection: { connectionString, client, pool }
|
|
1727
|
+
} = context;
|
|
1728
|
+
const pongo = pongoClient(connectionString, {
|
|
1729
|
+
connectionOptions: { client, pool }
|
|
1730
|
+
});
|
|
1731
|
+
await pongo.db().collection(collectionName).deleteMany();
|
|
1732
|
+
}
|
|
1733
|
+
});
|
|
1734
|
+
};
|
|
1735
|
+
var pongoSingleStreamProjection = (options) => {
|
|
1736
|
+
return pongoMultiStreamProjection({
|
|
1737
|
+
...options,
|
|
1738
|
+
getDocumentId: options.getDocumentId ?? ((event) => event.metadata.streamName)
|
|
1739
|
+
});
|
|
1740
|
+
};
|
|
1524
1741
|
|
|
1525
1742
|
// src/eventStore/projections/pongo/pongoProjectionSpec.ts
|
|
1526
1743
|
import "@event-driven-io/dumbo";
|
|
1527
1744
|
import {
|
|
1528
|
-
pongoClient
|
|
1745
|
+
pongoClient as pongoClient2
|
|
1529
1746
|
} from "@event-driven-io/pongo";
|
|
1530
1747
|
var withCollection = (handle, options) => {
|
|
1531
1748
|
const { pool, connectionString, inDatabase, inCollection } = options;
|
|
1532
1749
|
return pool.withConnection(async (connection) => {
|
|
1533
|
-
const pongo =
|
|
1750
|
+
const pongo = pongoClient2(connectionString, {
|
|
1534
1751
|
connectionOptions: { connection }
|
|
1535
1752
|
});
|
|
1536
1753
|
try {
|
|
@@ -1658,60 +1875,11 @@ var expectPongoDocuments = {
|
|
|
1658
1875
|
}
|
|
1659
1876
|
};
|
|
1660
1877
|
|
|
1661
|
-
// src/eventStore/projections/pongo/projections.ts
|
|
1662
|
-
import {
|
|
1663
|
-
pongoClient as pongoClient2
|
|
1664
|
-
} from "@event-driven-io/pongo";
|
|
1665
|
-
var pongoProjection = ({
|
|
1666
|
-
handle,
|
|
1667
|
-
canHandle
|
|
1668
|
-
}) => postgreSQLProjection({
|
|
1669
|
-
canHandle,
|
|
1670
|
-
handle: async (events, context) => {
|
|
1671
|
-
const {
|
|
1672
|
-
connection: { connectionString, client }
|
|
1673
|
-
} = context;
|
|
1674
|
-
const pongo = pongoClient2(connectionString, {
|
|
1675
|
-
connectionOptions: { client }
|
|
1676
|
-
});
|
|
1677
|
-
await handle(events, {
|
|
1678
|
-
...context,
|
|
1679
|
-
pongo
|
|
1680
|
-
});
|
|
1681
|
-
}
|
|
1682
|
-
});
|
|
1683
|
-
var pongoMultiStreamProjection = (options) => {
|
|
1684
|
-
const { collectionName, getDocumentId, canHandle } = options;
|
|
1685
|
-
return pongoProjection({
|
|
1686
|
-
handle: async (events, { pongo }) => {
|
|
1687
|
-
const collection = pongo.db().collection(collectionName);
|
|
1688
|
-
for (const event of events) {
|
|
1689
|
-
await collection.handle(getDocumentId(event), async (document) => {
|
|
1690
|
-
return "initialState" in options ? await options.evolve(
|
|
1691
|
-
document ?? options.initialState(),
|
|
1692
|
-
event
|
|
1693
|
-
) : await options.evolve(
|
|
1694
|
-
document,
|
|
1695
|
-
event
|
|
1696
|
-
);
|
|
1697
|
-
});
|
|
1698
|
-
}
|
|
1699
|
-
},
|
|
1700
|
-
canHandle
|
|
1701
|
-
});
|
|
1702
|
-
};
|
|
1703
|
-
var pongoSingleStreamProjection = (options) => {
|
|
1704
|
-
return pongoMultiStreamProjection({
|
|
1705
|
-
...options,
|
|
1706
|
-
getDocumentId: options.getDocumentId ?? ((event) => event.metadata.streamName)
|
|
1707
|
-
});
|
|
1708
|
-
};
|
|
1709
|
-
|
|
1710
1878
|
// src/eventStore/projections/postgresProjectionSpec.ts
|
|
1711
1879
|
import {
|
|
1712
1880
|
dumbo as dumbo3
|
|
1713
1881
|
} from "@event-driven-io/dumbo";
|
|
1714
|
-
import { v4 as
|
|
1882
|
+
import { v4 as uuid8 } from "uuid";
|
|
1715
1883
|
var PostgreSQLProjectionSpec = {
|
|
1716
1884
|
for: (options) => {
|
|
1717
1885
|
{
|
|
@@ -1731,8 +1899,8 @@ var PostgreSQLProjectionSpec = {
|
|
|
1731
1899
|
const metadata = {
|
|
1732
1900
|
globalPosition: ++globalPosition,
|
|
1733
1901
|
streamPosition: globalPosition,
|
|
1734
|
-
streamName: `test-${
|
|
1735
|
-
messageId:
|
|
1902
|
+
streamName: `test-${uuid8()}`,
|
|
1903
|
+
messageId: uuid8()
|
|
1736
1904
|
};
|
|
1737
1905
|
allEvents.push({
|
|
1738
1906
|
...event,
|
|
@@ -1830,7 +1998,8 @@ var expectSQL = {
|
|
|
1830
1998
|
})
|
|
1831
1999
|
};
|
|
1832
2000
|
|
|
1833
|
-
// src/eventStore/projections/
|
|
2001
|
+
// src/eventStore/projections/postgreSQLProjection.ts
|
|
2002
|
+
import "@event-driven-io/dumbo";
|
|
1834
2003
|
var handleProjections = async (options) => {
|
|
1835
2004
|
const {
|
|
1836
2005
|
projections: allProjections,
|
|
@@ -1995,7 +2164,6 @@ export {
|
|
|
1995
2164
|
DefaultPostgreSQLEventStoreProcessorBatchSize,
|
|
1996
2165
|
DefaultPostgreSQLEventStoreProcessorPullingFrequencyInMs,
|
|
1997
2166
|
PostgreSQLEventStoreDefaultStreamVersion,
|
|
1998
|
-
PostgreSQLProcessor,
|
|
1999
2167
|
PostgreSQLProjectionSpec,
|
|
2000
2168
|
addDefaultPartitionSQL,
|
|
2001
2169
|
addModuleForAllTenantsSQL,
|
|
@@ -2031,17 +2199,20 @@ export {
|
|
|
2031
2199
|
pongoMultiStreamProjection,
|
|
2032
2200
|
pongoProjection,
|
|
2033
2201
|
pongoSingleStreamProjection,
|
|
2202
|
+
postgreSQLCheckpointer,
|
|
2034
2203
|
postgreSQLEventStoreConsumer,
|
|
2035
2204
|
postgreSQLEventStoreMessageBatchPuller,
|
|
2036
|
-
|
|
2205
|
+
postgreSQLMessageProcessor,
|
|
2037
2206
|
postgreSQLProjection,
|
|
2038
|
-
|
|
2207
|
+
postgreSQLProjector,
|
|
2039
2208
|
postgreSQLRawBatchSQLProjection,
|
|
2040
2209
|
postgreSQLRawSQLProjection,
|
|
2210
|
+
postgreSQLReactor,
|
|
2041
2211
|
readLastMessageGlobalPosition,
|
|
2042
2212
|
readMessagesBatch,
|
|
2043
2213
|
readProcessorCheckpoint,
|
|
2044
2214
|
readStream,
|
|
2215
|
+
rebuildPostgreSQLProjections,
|
|
2045
2216
|
sanitizeNameSQL,
|
|
2046
2217
|
schemaSQL,
|
|
2047
2218
|
storeProcessorCheckpoint,
|