@event-driven-io/emmett 0.43.0-beta.35 → 0.43.0-beta.37
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 +55 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +62 -4
- package/dist/index.d.ts +62 -4
- package/dist/index.js +55 -16
- package/dist/index.js.map +1 -1
- package/dist/otel.cjs +1 -1
- package/dist/otel.cjs.map +1 -1
- package/dist/otel.js +1 -1
- package/dist/otel.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -1102,7 +1102,7 @@ const ProcessorCheckpoint = Object.assign((checkpoint) => checkpoint, {
|
|
|
1102
1102
|
BEGINNING: "BEGINNING",
|
|
1103
1103
|
isBeginning: (checkpoint) => checkpoint === void 0 || checkpoint === "BEGINNING",
|
|
1104
1104
|
isEnd: (checkpoint) => checkpoint === "END",
|
|
1105
|
-
compare: (a, b) => a > b ? 1 : -1
|
|
1105
|
+
compare: (a, b) => a > b ? 1 : a < b ? -1 : 0
|
|
1106
1106
|
});
|
|
1107
1107
|
const bigIntProcessorCheckpoint = (value) => bigInt.toNormalizedString(value);
|
|
1108
1108
|
const parseBigIntProcessorCheckpoint = (value) => BigInt(value);
|
|
@@ -1229,7 +1229,7 @@ const processorCollector = (observability) => {
|
|
|
1229
1229
|
//#endregion
|
|
1230
1230
|
//#region src/processors/processors.ts
|
|
1231
1231
|
const CurrentMessageProcessorPosition = {
|
|
1232
|
-
compare: (a, b, compareCheckpoints =
|
|
1232
|
+
compare: (a, b, compareCheckpoints = ProcessorCheckpoint.compare) => {
|
|
1233
1233
|
if (a === b) return 0;
|
|
1234
1234
|
if (a === "BEGINNING") return -1;
|
|
1235
1235
|
if (b === "BEGINNING") return 1;
|
|
@@ -1242,14 +1242,22 @@ const CurrentMessageProcessorPosition = {
|
|
|
1242
1242
|
return checkpoints.map((pos) => pos === void 0 ? "BEGINNING" : pos).sort((a, b) => CurrentMessageProcessorPosition.compare(a, b, compareCheckpoints))[0] ?? "BEGINNING";
|
|
1243
1243
|
}
|
|
1244
1244
|
};
|
|
1245
|
-
const wasMessageHandled = (message, checkpoint) => {
|
|
1245
|
+
const wasMessageHandled = (message, checkpoint, compareCheckpoints = ProcessorCheckpoint.compare) => {
|
|
1246
1246
|
const messageCheckpoint = getCheckpoint(message);
|
|
1247
|
-
return messageCheckpoint !== null && messageCheckpoint !== void 0 && checkpoint !== null && checkpoint !== void 0 && messageCheckpoint <=
|
|
1247
|
+
return messageCheckpoint !== null && messageCheckpoint !== void 0 && checkpoint !== null && checkpoint !== void 0 && compareCheckpoints(messageCheckpoint, checkpoint) <= 0;
|
|
1248
1248
|
};
|
|
1249
1249
|
const MessageProcessorType = {
|
|
1250
1250
|
PROJECTOR: "projector",
|
|
1251
1251
|
REACTOR: "reactor"
|
|
1252
1252
|
};
|
|
1253
|
+
const raceWithTimeout = (wait, timeout, timeoutMessage) => {
|
|
1254
|
+
if (timeout === void 0) return wait;
|
|
1255
|
+
let timer;
|
|
1256
|
+
const timeoutPromise = new Promise((_resolve, reject) => {
|
|
1257
|
+
timer = setTimeout(() => reject(new require_plugins.EmmettError(timeoutMessage())), timeout);
|
|
1258
|
+
});
|
|
1259
|
+
return Promise.race([wait, timeoutPromise]).finally(() => clearTimeout(timer));
|
|
1260
|
+
};
|
|
1253
1261
|
const MessageProcessor = { result: {
|
|
1254
1262
|
skip: (options) => ({
|
|
1255
1263
|
type: "SKIP",
|
|
@@ -1270,7 +1278,7 @@ const getProcessorInstanceId = (processorId) => `${processorId}:${(0, uuid.v7)()
|
|
|
1270
1278
|
const getProjectorId = (options) => `emt:processor:projector:${options.projectionName}`;
|
|
1271
1279
|
const { info, error } = _event_driven_io_almanac.LogEvent;
|
|
1272
1280
|
const reactor = (options) => {
|
|
1273
|
-
const { checkpoints, processorId, processorInstanceId: instanceId = getProcessorInstanceId(processorId), type = MessageProcessorType.REACTOR, version = 1, partition = defaultProcessorPartition, hooks = {}, processingScope = defaultProcessingMessageProcessingScope, startFrom, canHandle, stopAfter } = options;
|
|
1281
|
+
const { checkpoints, processorId, processorInstanceId: instanceId = getProcessorInstanceId(processorId), type = MessageProcessorType.REACTOR, version = 1, partition = defaultProcessorPartition, hooks = {}, processingScope = defaultProcessingMessageProcessingScope, startFrom, canHandle, stopAfter, compareCheckpoints = ProcessorCheckpoint.compare } = options;
|
|
1274
1282
|
const checkpointer = checkpoints === "DISABLED" ? inMemoryCheckpointer() : checkpoints;
|
|
1275
1283
|
const collector = processorCollector(processorObservability(options));
|
|
1276
1284
|
const isCustomBatch = "eachBatch" in options && !!options.eachBatch;
|
|
@@ -1315,7 +1323,26 @@ const reactor = (options) => {
|
|
|
1315
1323
|
let isInitiated = false;
|
|
1316
1324
|
let isActive = false;
|
|
1317
1325
|
let lastCheckpoint = null;
|
|
1326
|
+
let lastStoredCheckpoint = null;
|
|
1318
1327
|
let closeSignal = null;
|
|
1328
|
+
const checkpointWaiters = /* @__PURE__ */ new Set();
|
|
1329
|
+
const hasProcessed = (target) => lastCheckpoint !== null && compareCheckpoints(lastCheckpoint, target) >= 0;
|
|
1330
|
+
const notifyCheckpointWaiters = () => {
|
|
1331
|
+
for (const waiter of checkpointWaiters) if (hasProcessed(waiter.target)) {
|
|
1332
|
+
checkpointWaiters.delete(waiter);
|
|
1333
|
+
waiter.resolve();
|
|
1334
|
+
}
|
|
1335
|
+
};
|
|
1336
|
+
const whenProcessed = (checkpoint, options) => {
|
|
1337
|
+
if (hasProcessed(checkpoint)) return Promise.resolve();
|
|
1338
|
+
const awaiter = asyncAwaiter();
|
|
1339
|
+
const waiter = {
|
|
1340
|
+
target: checkpoint,
|
|
1341
|
+
resolve: awaiter.resolve
|
|
1342
|
+
};
|
|
1343
|
+
checkpointWaiters.add(waiter);
|
|
1344
|
+
return raceWithTimeout(awaiter.wait, options?.timeout, () => `Processor ${processorId} with instance id ${instanceId} did not process checkpoint ${checkpoint} within ${options.timeout}ms (last processed checkpoint: ${lastCheckpoint ?? "none"})`).finally(() => checkpointWaiters.delete(waiter));
|
|
1345
|
+
};
|
|
1319
1346
|
const init = async (initOptions) => {
|
|
1320
1347
|
if (isInitiated) return;
|
|
1321
1348
|
if (hooks.onInit === void 0) {
|
|
@@ -1372,18 +1399,23 @@ const reactor = (options) => {
|
|
|
1372
1399
|
log(info(`Executing onStart hook for processor ${processorId} with instance id ${instanceId}`));
|
|
1373
1400
|
await hooks.onStart(context);
|
|
1374
1401
|
}
|
|
1375
|
-
if (
|
|
1376
|
-
if (typeof startFrom !== "string") lastCheckpoint = startFrom.lastCheckpoint;
|
|
1377
|
-
log(info(`Processor ${processorId} with instance id ${instanceId} starting from: ${JSONSerializer.serialize(startFrom)}`));
|
|
1378
|
-
return startFrom;
|
|
1379
|
-
}
|
|
1380
|
-
if (checkpointer) lastCheckpoint = (await checkpointer.read({
|
|
1402
|
+
if (checkpointer) lastStoredCheckpoint = (await checkpointer.read({
|
|
1381
1403
|
processorId,
|
|
1382
1404
|
partition
|
|
1383
1405
|
}, {
|
|
1384
1406
|
...startOptions,
|
|
1385
1407
|
...context
|
|
1386
1408
|
})).lastCheckpoint;
|
|
1409
|
+
if (startFrom !== void 0 && typeof startFrom !== "string") {
|
|
1410
|
+
lastCheckpoint = startFrom.lastCheckpoint;
|
|
1411
|
+
log(info(`Processor ${processorId} with instance id ${instanceId} starting from: ${JSONSerializer.serialize(startFrom)}`));
|
|
1412
|
+
return startFrom;
|
|
1413
|
+
}
|
|
1414
|
+
if (startFrom === "BEGINNING" || startFrom === "END") {
|
|
1415
|
+
log(info(`Processor ${processorId} with instance id ${instanceId} starting from: ${JSONSerializer.serialize(startFrom)}`));
|
|
1416
|
+
return startFrom;
|
|
1417
|
+
}
|
|
1418
|
+
lastCheckpoint = lastStoredCheckpoint;
|
|
1387
1419
|
if (lastCheckpoint === null) {
|
|
1388
1420
|
log(info(`Processor ${processorId} with instance id ${instanceId} starting from: BEGINNING`));
|
|
1389
1421
|
return "BEGINNING";
|
|
@@ -1402,6 +1434,7 @@ const reactor = (options) => {
|
|
|
1402
1434
|
get isActive() {
|
|
1403
1435
|
return isActive;
|
|
1404
1436
|
},
|
|
1437
|
+
whenProcessed,
|
|
1405
1438
|
handle: async (messages, partialContext) => {
|
|
1406
1439
|
if (!isActive) return Promise.resolve();
|
|
1407
1440
|
return collector.startScope({
|
|
@@ -1410,8 +1443,8 @@ const reactor = (options) => {
|
|
|
1410
1443
|
checkpoint: lastCheckpoint
|
|
1411
1444
|
}, messages, async (scope) => {
|
|
1412
1445
|
try {
|
|
1413
|
-
|
|
1414
|
-
const messagesAboveCheckpoint = messages.filter((message) => !wasMessageHandled(message, lastCheckpoint));
|
|
1446
|
+
const result = await processingScope(async (context) => {
|
|
1447
|
+
const messagesAboveCheckpoint = messages.filter((message) => !wasMessageHandled(message, lastCheckpoint, compareCheckpoints));
|
|
1415
1448
|
const upcastedMessages = messagesAboveCheckpoint.map((message) => upcastRecordedMessage(message, options.messageOptions?.schema?.versioning)).filter((upcasted) => !canHandle || canHandle.includes(upcasted.type));
|
|
1416
1449
|
const stopMessageIndex = isCustomBatch && stopAfter ? upcastedMessages.findIndex(stopAfter) : -1;
|
|
1417
1450
|
const unhandledMessages = stopMessageIndex !== -1 ? upcastedMessages.slice(0, stopMessageIndex + 1) : upcastedMessages;
|
|
@@ -1431,10 +1464,13 @@ const reactor = (options) => {
|
|
|
1431
1464
|
processorId,
|
|
1432
1465
|
version,
|
|
1433
1466
|
message: checkpointMessage,
|
|
1434
|
-
lastCheckpoint,
|
|
1467
|
+
lastCheckpoint: lastStoredCheckpoint,
|
|
1435
1468
|
partition
|
|
1436
1469
|
}, context);
|
|
1437
|
-
if (storeCheckpointResult.success)
|
|
1470
|
+
if (storeCheckpointResult.success) {
|
|
1471
|
+
lastCheckpoint = storeCheckpointResult.newCheckpoint;
|
|
1472
|
+
lastStoredCheckpoint = storeCheckpointResult.newCheckpoint;
|
|
1473
|
+
}
|
|
1438
1474
|
}
|
|
1439
1475
|
scope.setAttributes({ [EmmettAttributes.processor.status]: messageProcessingResult?.type ?? "ack" });
|
|
1440
1476
|
if (isStop) {
|
|
@@ -1445,6 +1481,8 @@ const reactor = (options) => {
|
|
|
1445
1481
|
...partialContext,
|
|
1446
1482
|
observabilityScope: scope
|
|
1447
1483
|
});
|
|
1484
|
+
if (result?.type !== "STOP") notifyCheckpointWaiters();
|
|
1485
|
+
return result;
|
|
1448
1486
|
} catch (err) {
|
|
1449
1487
|
scope.log(error({ err }, `Error during message processing for processor ${processorId} with instance id ${instanceId}. Stopping the processor.`));
|
|
1450
1488
|
isActive = false;
|
|
@@ -1572,9 +1610,10 @@ const ProcessorStartPositions = (options) => {
|
|
|
1572
1610
|
const position = positions.get(processorId);
|
|
1573
1611
|
if (position === void 0 || position === "BEGINNING" || position === "END") return messages;
|
|
1574
1612
|
const { lastCheckpoint } = position;
|
|
1613
|
+
const compareCheckpoints = options?.compareCheckpoints ?? ProcessorCheckpoint.compare;
|
|
1575
1614
|
return messages.filter((message) => {
|
|
1576
1615
|
const checkpoint = getCheckpoint(message);
|
|
1577
|
-
return checkpoint !== null && checkpoint >
|
|
1616
|
+
return checkpoint !== null && compareCheckpoints(checkpoint, lastCheckpoint) > 0;
|
|
1578
1617
|
});
|
|
1579
1618
|
}
|
|
1580
1619
|
};
|