@event-driven-io/emmett 0.43.0-beta.22 → 0.43.0-beta.24
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 +289 -311
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +108 -114
- package/dist/index.d.ts +108 -114
- package/dist/index.js +285 -306
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { n as __reExport, t as __exportAll } from "./chunk-zc3tnsvq.js";
|
|
|
2
2
|
import { _ as isValidYYYYMMDD, a as IllegalStateError, c as isErrorConstructor, d as assertPositiveNumber, f as assertUnsignedBigInt, g as formatDateToUtcYYYYMMDD, h as isString, i as EmmettError, l as ValidationErrors, m as isNumber, n as ConcurrencyError, o as NotFoundError, p as isBigint, r as ConcurrencyInMemoryDatabaseError, s as ValidationError, t as isPluginConfig, u as assertNotEmptyString, v as parseDateFromUtcYYYYMMDD } from "./plugins-DgfqJ5af.js";
|
|
3
3
|
import { v4, v7 } from "uuid";
|
|
4
4
|
import retry from "async-retry";
|
|
5
|
-
import { MessagingAttributes, ObservabilityScope, noopMeter, noopScope, noopTracer } from "@event-driven-io/almanac";
|
|
5
|
+
import { LogEvent, MessagingAttributes, ObservabilityScope, noopMeter, noopScope, noopTracer } from "@event-driven-io/almanac";
|
|
6
6
|
|
|
7
7
|
export * from "@event-driven-io/almanac"
|
|
8
8
|
|
|
@@ -620,6 +620,11 @@ const bigIntReplacer = (_key, value) => {
|
|
|
620
620
|
const dateReplacer = (_key, value) => {
|
|
621
621
|
return value instanceof Date ? value.toISOString() : value;
|
|
622
622
|
};
|
|
623
|
+
const errorReplacer = (_key, value) => value instanceof Error ? {
|
|
624
|
+
type: value.constructor.name || "error",
|
|
625
|
+
message: value.message,
|
|
626
|
+
stack: value.stack
|
|
627
|
+
} : value;
|
|
623
628
|
const isFirstLetterNumeric = (str) => {
|
|
624
629
|
const c = str.charCodeAt(0);
|
|
625
630
|
return c >= 48 && c <= 57;
|
|
@@ -661,11 +666,12 @@ const composeJSONRevivers = (...revivers) => {
|
|
|
661
666
|
if (filteredRevivers.length === 0) return void 0;
|
|
662
667
|
return (key, value, context) => filteredRevivers.reduce((accValue, reviver) => reviver(key, accValue, context), value);
|
|
663
668
|
};
|
|
664
|
-
const JSONReplacer = (opts) => composeJSONReplacers(opts?.replacer, opts?.failOnBigIntSerialization !== true ? JSONReplacers.bigInt : void 0, opts?.useDefaultDateSerialization !== true ? JSONReplacers.date : void 0);
|
|
669
|
+
const JSONReplacer = (opts) => composeJSONReplacers(opts?.replacer, opts?.failOnBigIntSerialization !== true ? JSONReplacers.bigInt : void 0, opts?.useDefaultDateSerialization !== true ? JSONReplacers.date : void 0, opts?.skipErrorSerialization !== true ? JSONReplacers.error : void 0);
|
|
665
670
|
const JSONReviver = (opts) => composeJSONRevivers(opts?.reviver, opts?.parseBigInts === true ? JSONRevivers.bigInt : void 0, opts?.parseDates === true ? JSONRevivers.date : void 0);
|
|
666
671
|
const JSONReplacers = {
|
|
667
672
|
bigInt: bigIntReplacer,
|
|
668
|
-
date: dateReplacer
|
|
673
|
+
date: dateReplacer,
|
|
674
|
+
error: errorReplacer
|
|
669
675
|
};
|
|
670
676
|
const JSONRevivers = {
|
|
671
677
|
bigInt: bigIntReviver,
|
|
@@ -674,8 +680,19 @@ const JSONRevivers = {
|
|
|
674
680
|
const jsonSerializer = (options) => {
|
|
675
681
|
const defaultReplacer = JSONReplacer(options);
|
|
676
682
|
const defaultReviver = JSONReviver(options);
|
|
683
|
+
const defaultFormat = options?.format ?? "compact";
|
|
684
|
+
const defaultSafe = options?.safe ?? false;
|
|
677
685
|
return {
|
|
678
|
-
serialize: (object, serializerOptions) =>
|
|
686
|
+
serialize: (object, serializerOptions) => {
|
|
687
|
+
const replacer = serializerOptions ? JSONReplacer(serializerOptions) : defaultReplacer;
|
|
688
|
+
const indent = (serializerOptions?.format ?? defaultFormat) === "pretty" ? 2 : void 0;
|
|
689
|
+
if (serializerOptions?.safe ?? defaultSafe) try {
|
|
690
|
+
return JSON.stringify(object, replacer, indent);
|
|
691
|
+
} catch (e) {
|
|
692
|
+
return `{"__serializationError":${JSON.stringify(String(e))}}`;
|
|
693
|
+
}
|
|
694
|
+
return JSON.stringify(object, replacer, indent);
|
|
695
|
+
},
|
|
679
696
|
deserialize: (payload, deserializerOptions) => JSON.parse(payload, deserializerOptions ? JSONReviver(deserializerOptions) : defaultReviver)
|
|
680
697
|
};
|
|
681
698
|
};
|
|
@@ -979,6 +996,15 @@ const getInMemoryDatabase = () => {
|
|
|
979
996
|
} };
|
|
980
997
|
};
|
|
981
998
|
|
|
999
|
+
//#endregion
|
|
1000
|
+
//#region src/processors/checkpoints.ts
|
|
1001
|
+
const ProcessorCheckpoint = (checkpoint) => checkpoint;
|
|
1002
|
+
const bigIntProcessorCheckpoint = (value) => bigInt.toNormalizedString(value);
|
|
1003
|
+
const parseBigIntProcessorCheckpoint = (value) => BigInt(value);
|
|
1004
|
+
const getCheckpoint = (message) => {
|
|
1005
|
+
return message.metadata.checkpoint;
|
|
1006
|
+
};
|
|
1007
|
+
|
|
982
1008
|
//#endregion
|
|
983
1009
|
//#region src/observability/attributes.ts
|
|
984
1010
|
const EmmettAttributes = {
|
|
@@ -1066,281 +1092,21 @@ const MessagingSystemName = "emmett";
|
|
|
1066
1092
|
|
|
1067
1093
|
//#endregion
|
|
1068
1094
|
//#region src/observability/options.ts
|
|
1069
|
-
const
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
attributeTarget: options?.observability?.attributeTarget ?? parent?.observability?.attributeTarget ?? "both"
|
|
1074
|
-
});
|
|
1075
|
-
const resolveWorkflowObservability = (options, parent) => ({
|
|
1076
|
-
tracer: options?.observability?.tracer ?? parent?.observability?.tracer ?? noopTracer(),
|
|
1077
|
-
meter: options?.observability?.meter ?? parent?.observability?.meter ?? noopMeter(),
|
|
1078
|
-
propagation: options?.observability?.propagation ?? parent?.observability?.propagation ?? "links",
|
|
1079
|
-
attributeTarget: options?.observability?.attributeTarget ?? parent?.observability?.attributeTarget ?? "both",
|
|
1080
|
-
includeMessagePayloads: options?.observability?.includeMessagePayloads ?? parent?.observability?.includeMessagePayloads ?? false
|
|
1081
|
-
});
|
|
1082
|
-
|
|
1083
|
-
//#endregion
|
|
1084
|
-
//#region src/observability/tracer.ts
|
|
1085
|
-
const tracer = () => {};
|
|
1086
|
-
const LogLevel = {
|
|
1087
|
-
DISABLED: "DISABLED",
|
|
1088
|
-
INFO: "INFO",
|
|
1089
|
-
LOG: "LOG",
|
|
1090
|
-
WARN: "WARN",
|
|
1091
|
-
ERROR: "ERROR"
|
|
1092
|
-
};
|
|
1093
|
-
const LogStyle = {
|
|
1094
|
-
RAW: "RAW",
|
|
1095
|
-
PRETTY: "PRETTY"
|
|
1096
|
-
};
|
|
1097
|
-
const getEnvVariable = (name) => {
|
|
1098
|
-
try {
|
|
1099
|
-
if (typeof process !== "undefined" && process.env) return process.env[name];
|
|
1100
|
-
return;
|
|
1101
|
-
} catch {
|
|
1102
|
-
return;
|
|
1103
|
-
}
|
|
1104
|
-
};
|
|
1105
|
-
const shouldLog = (logLevel) => {
|
|
1106
|
-
const definedLogLevel = getEnvVariable("DUMBO_LOG_LEVEL") ?? LogLevel.ERROR;
|
|
1107
|
-
if (definedLogLevel === LogLevel.ERROR && logLevel === LogLevel.ERROR) return true;
|
|
1108
|
-
if (definedLogLevel === LogLevel.WARN && [LogLevel.ERROR, LogLevel.WARN].includes(logLevel)) return true;
|
|
1109
|
-
if (definedLogLevel === LogLevel.LOG && [
|
|
1110
|
-
LogLevel.ERROR,
|
|
1111
|
-
LogLevel.WARN,
|
|
1112
|
-
LogLevel.LOG
|
|
1113
|
-
].includes(logLevel)) return true;
|
|
1114
|
-
if (definedLogLevel === LogLevel.INFO && [
|
|
1115
|
-
LogLevel.ERROR,
|
|
1116
|
-
LogLevel.WARN,
|
|
1117
|
-
LogLevel.LOG,
|
|
1118
|
-
LogLevel.INFO
|
|
1119
|
-
].includes(logLevel)) return true;
|
|
1120
|
-
return false;
|
|
1121
|
-
};
|
|
1122
|
-
const nulloTraceEventRecorder = () => {};
|
|
1123
|
-
const getTraceEventFormatter = (logStyle, serializer) => (event) => {
|
|
1124
|
-
serializer = serializer ?? JSONSerializer.from();
|
|
1125
|
-
switch (logStyle) {
|
|
1126
|
-
case "RAW": return serializer.serialize(event);
|
|
1127
|
-
case "PRETTY": return serializer.serialize(event);
|
|
1128
|
-
}
|
|
1129
|
-
};
|
|
1130
|
-
const getTraceEventRecorder = (logLevel, logStyle) => {
|
|
1131
|
-
const format = getTraceEventFormatter(logStyle);
|
|
1132
|
-
switch (logLevel) {
|
|
1133
|
-
case "DISABLED": return nulloTraceEventRecorder;
|
|
1134
|
-
case "INFO": return (event) => console.info(format(event));
|
|
1135
|
-
case "LOG": return (event) => console.log(format(event));
|
|
1136
|
-
case "WARN": return (event) => console.warn(format(event));
|
|
1137
|
-
case "ERROR": return (event) => console.error(format(event));
|
|
1138
|
-
}
|
|
1139
|
-
};
|
|
1140
|
-
const recordTraceEvent = (logLevel, eventName, attributes) => {
|
|
1141
|
-
if (!shouldLog(LogLevel.LOG)) return;
|
|
1142
|
-
const event = {
|
|
1143
|
-
name: eventName,
|
|
1144
|
-
timestamp: (/* @__PURE__ */ new Date()).getTime(),
|
|
1145
|
-
...attributes
|
|
1095
|
+
const mergeObservabilityOptions = (options, defaults) => {
|
|
1096
|
+
const observability = defaults === void 0 ? options.observability : options.observability === void 0 ? defaults : {
|
|
1097
|
+
...defaults,
|
|
1098
|
+
...options.observability
|
|
1146
1099
|
};
|
|
1147
|
-
|
|
1148
|
-
};
|
|
1149
|
-
tracer.info = (eventName, attributes) => recordTraceEvent(LogLevel.INFO, eventName, attributes);
|
|
1150
|
-
tracer.warn = (eventName, attributes) => recordTraceEvent(LogLevel.WARN, eventName, attributes);
|
|
1151
|
-
tracer.log = (eventName, attributes) => recordTraceEvent(LogLevel.LOG, eventName, attributes);
|
|
1152
|
-
tracer.error = (eventName, attributes) => recordTraceEvent(LogLevel.ERROR, eventName, attributes);
|
|
1153
|
-
|
|
1154
|
-
//#endregion
|
|
1155
|
-
//#region src/eventStore/observability/eventStoreCollector.ts
|
|
1156
|
-
const resolveEventStoreObservability = (options, parent) => ({
|
|
1157
|
-
tracer: options?.observability?.tracer ?? parent?.observability?.tracer ?? noopTracer(),
|
|
1158
|
-
meter: options?.observability?.meter ?? parent?.observability?.meter ?? noopMeter(),
|
|
1159
|
-
attributeTarget: options?.observability?.attributeTarget ?? parent?.observability?.attributeTarget ?? "both"
|
|
1160
|
-
});
|
|
1161
|
-
const eventStoreCollector = (observability) => {
|
|
1162
|
-
const A = EmmettAttributes;
|
|
1163
|
-
const M = MessagingAttributes;
|
|
1164
|
-
const streamReadingDuration = observability.meter.histogram(EmmettMetrics.stream.readingDuration);
|
|
1165
|
-
const streamReadingSize = observability.meter.histogram(EmmettMetrics.stream.readingSize);
|
|
1166
|
-
const eventReadingCount = observability.meter.counter(EmmettMetrics.event.readingCount);
|
|
1167
|
-
const streamAppendingDuration = observability.meter.histogram(EmmettMetrics.stream.appendingDuration);
|
|
1168
|
-
const streamAppendingSize = observability.meter.histogram(EmmettMetrics.stream.appendingSize);
|
|
1169
|
-
const eventAppendingCount = observability.meter.counter(EmmettMetrics.event.appendingCount);
|
|
1100
|
+
if (observability === options.observability) return options;
|
|
1170
1101
|
return {
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
return observability.tracer.startSpan("eventStore.readStream", async (span) => {
|
|
1174
|
-
span.setAttributes({
|
|
1175
|
-
[A.eventStore.operation]: "readStream",
|
|
1176
|
-
[A.stream.name]: streamName,
|
|
1177
|
-
[M.operation.type]: "receive",
|
|
1178
|
-
[M.destination.name]: streamName,
|
|
1179
|
-
[M.system]: MessagingSystemName
|
|
1180
|
-
});
|
|
1181
|
-
let status = "success";
|
|
1182
|
-
try {
|
|
1183
|
-
const result = await fn();
|
|
1184
|
-
const events = result.events;
|
|
1185
|
-
span.setAttributes({
|
|
1186
|
-
[A.eventStore.read.status]: status,
|
|
1187
|
-
[A.eventStore.read.eventCount]: events.length,
|
|
1188
|
-
[A.eventStore.read.eventTypes]: [...new Set(events.map((e) => e.type))]
|
|
1189
|
-
});
|
|
1190
|
-
streamReadingSize.record(events.length, { [A.eventStore.read.status]: status });
|
|
1191
|
-
for (const event of events) eventReadingCount.add(1, { [A.event.type]: event.type });
|
|
1192
|
-
return result;
|
|
1193
|
-
} catch (err) {
|
|
1194
|
-
status = "failure";
|
|
1195
|
-
span.setAttributes({ [A.eventStore.read.status]: status });
|
|
1196
|
-
throw err;
|
|
1197
|
-
} finally {
|
|
1198
|
-
streamReadingDuration.record(Date.now() - start, { [A.eventStore.read.status]: status });
|
|
1199
|
-
}
|
|
1200
|
-
});
|
|
1201
|
-
},
|
|
1202
|
-
instrumentAppend: (streamName, events, fn) => {
|
|
1203
|
-
const start = Date.now();
|
|
1204
|
-
return observability.tracer.startSpan("eventStore.appendToStream", async (span) => {
|
|
1205
|
-
span.setAttributes({
|
|
1206
|
-
[A.eventStore.operation]: "appendToStream",
|
|
1207
|
-
[A.stream.name]: streamName,
|
|
1208
|
-
[A.eventStore.append.batchSize]: events.length,
|
|
1209
|
-
[M.operation.type]: "send",
|
|
1210
|
-
[M.batch.messageCount]: events.length,
|
|
1211
|
-
[M.destination.name]: streamName,
|
|
1212
|
-
[M.system]: MessagingSystemName
|
|
1213
|
-
});
|
|
1214
|
-
let status = "success";
|
|
1215
|
-
try {
|
|
1216
|
-
const result = await fn();
|
|
1217
|
-
span.setAttributes({
|
|
1218
|
-
[A.eventStore.append.status]: status,
|
|
1219
|
-
[A.stream.versionAfter]: Number(result.nextExpectedStreamVersion)
|
|
1220
|
-
});
|
|
1221
|
-
streamAppendingSize.record(events.length, { [A.eventStore.append.status]: status });
|
|
1222
|
-
for (const event of events) eventAppendingCount.add(1, { [A.event.type]: event.type });
|
|
1223
|
-
return result;
|
|
1224
|
-
} catch (err) {
|
|
1225
|
-
status = "failure";
|
|
1226
|
-
span.setAttributes({ [A.eventStore.append.status]: status });
|
|
1227
|
-
throw err;
|
|
1228
|
-
} finally {
|
|
1229
|
-
streamAppendingDuration.record(Date.now() - start, { [A.eventStore.append.status]: status });
|
|
1230
|
-
}
|
|
1231
|
-
});
|
|
1232
|
-
}
|
|
1233
|
-
};
|
|
1234
|
-
};
|
|
1235
|
-
|
|
1236
|
-
//#endregion
|
|
1237
|
-
//#region src/observability/collectors/consumerCollector.ts
|
|
1238
|
-
const consumerCollector = (observability) => {
|
|
1239
|
-
const { startScope } = ObservabilityScope({
|
|
1240
|
-
...observability,
|
|
1241
|
-
attributePrefix: "emmett"
|
|
1242
|
-
});
|
|
1243
|
-
const A = EmmettAttributes;
|
|
1244
|
-
const M = MessagingAttributes;
|
|
1245
|
-
const pollDuration = observability.meter.histogram(EmmettMetrics.consumer.pollDuration);
|
|
1246
|
-
const deliveryDuration = observability.meter.histogram(EmmettMetrics.consumer.deliveryDuration);
|
|
1247
|
-
return {
|
|
1248
|
-
tracePoll: (context, fn) => {
|
|
1249
|
-
if (observability.pollTracing === "off" || observability.pollTracing === "active" && context.batchSize === 0) return fn(noopScope);
|
|
1250
|
-
return startScope("consumer.poll", async (scope) => {
|
|
1251
|
-
scope.setAttributes({
|
|
1252
|
-
[A.scope.type]: ScopeTypes.consumer,
|
|
1253
|
-
[A.consumer.batchSize]: context.batchSize,
|
|
1254
|
-
[A.consumer.processorCount]: context.processorCount,
|
|
1255
|
-
[M.system]: MessagingSystemName,
|
|
1256
|
-
[M.operation.type]: "receive",
|
|
1257
|
-
...context.empty ? { "emmett.consumer.poll.empty": true } : {},
|
|
1258
|
-
...context.waitMs != null ? { "emmett.consumer.poll.wait_ms": context.waitMs } : {}
|
|
1259
|
-
});
|
|
1260
|
-
return fn(scope);
|
|
1261
|
-
});
|
|
1262
|
-
},
|
|
1263
|
-
recordPollMetrics: (durationMs, attrs) => {
|
|
1264
|
-
pollDuration.record(durationMs, attrs);
|
|
1265
|
-
},
|
|
1266
|
-
traceDelivery: (scope, processorId, fn) => {
|
|
1267
|
-
const start = Date.now();
|
|
1268
|
-
return scope.scope(`consumer.deliver.${processorId}`, async (child) => {
|
|
1269
|
-
try {
|
|
1270
|
-
return await fn();
|
|
1271
|
-
} catch (error) {
|
|
1272
|
-
if (error instanceof Error) child.recordException(error);
|
|
1273
|
-
throw error;
|
|
1274
|
-
} finally {
|
|
1275
|
-
deliveryDuration.record(Date.now() - start, { [A.consumer.delivery.processorId]: processorId });
|
|
1276
|
-
}
|
|
1277
|
-
}, { attributes: { [A.consumer.delivery.processorId]: processorId } });
|
|
1278
|
-
}
|
|
1279
|
-
};
|
|
1280
|
-
};
|
|
1281
|
-
|
|
1282
|
-
//#endregion
|
|
1283
|
-
//#region src/observability/collectors/workflowCollector.ts
|
|
1284
|
-
const workflowCollector = (observability) => {
|
|
1285
|
-
const { startScope } = ObservabilityScope({
|
|
1286
|
-
...observability,
|
|
1287
|
-
attributePrefix: "emmett"
|
|
1288
|
-
});
|
|
1289
|
-
const A = EmmettAttributes;
|
|
1290
|
-
const M = MessagingAttributes;
|
|
1291
|
-
const processingDuration = observability.meter.histogram(EmmettMetrics.workflow.processingDuration);
|
|
1292
|
-
return {
|
|
1293
|
-
startScope: (context, fn) => {
|
|
1294
|
-
const start = Date.now();
|
|
1295
|
-
return startScope("workflow.handle", async (scope) => {
|
|
1296
|
-
scope.setAttributes({
|
|
1297
|
-
[A.scope.type]: ScopeTypes.workflow,
|
|
1298
|
-
[A.workflow.id]: context.workflowId,
|
|
1299
|
-
[A.workflow.type]: context.workflowType,
|
|
1300
|
-
[A.workflow.inputType]: context.inputType,
|
|
1301
|
-
[M.system]: MessagingSystemName
|
|
1302
|
-
});
|
|
1303
|
-
let status = "success";
|
|
1304
|
-
try {
|
|
1305
|
-
return await fn(scope);
|
|
1306
|
-
} catch (err) {
|
|
1307
|
-
status = "failure";
|
|
1308
|
-
throw err;
|
|
1309
|
-
} finally {
|
|
1310
|
-
processingDuration.record(Date.now() - start, {
|
|
1311
|
-
[A.workflow.type]: context.workflowType,
|
|
1312
|
-
status
|
|
1313
|
-
});
|
|
1314
|
-
}
|
|
1315
|
-
}, { attributes: {
|
|
1316
|
-
[A.scope.type]: ScopeTypes.workflow,
|
|
1317
|
-
[A.workflow.type]: context.workflowType
|
|
1318
|
-
} });
|
|
1319
|
-
},
|
|
1320
|
-
recordOutputs: (scope, outputs) => {
|
|
1321
|
-
scope.setAttributes({
|
|
1322
|
-
[A.workflow.outputs]: outputs.map((o) => o.type),
|
|
1323
|
-
[A.workflow.outputsCount]: outputs.length
|
|
1324
|
-
});
|
|
1325
|
-
},
|
|
1326
|
-
recordStateRebuild: (scope, eventCount) => {
|
|
1327
|
-
scope.setAttributes({ [A.workflow.stateRebuildEventCount]: eventCount });
|
|
1328
|
-
}
|
|
1102
|
+
...options,
|
|
1103
|
+
observability
|
|
1329
1104
|
};
|
|
1330
1105
|
};
|
|
1331
1106
|
|
|
1332
|
-
//#endregion
|
|
1333
|
-
//#region src/processors/checkpoints.ts
|
|
1334
|
-
const ProcessorCheckpoint = (checkpoint) => checkpoint;
|
|
1335
|
-
const bigIntProcessorCheckpoint = (value) => bigInt.toNormalizedString(value);
|
|
1336
|
-
const parseBigIntProcessorCheckpoint = (value) => BigInt(value);
|
|
1337
|
-
const getCheckpoint = (message) => {
|
|
1338
|
-
return message.metadata.checkpoint;
|
|
1339
|
-
};
|
|
1340
|
-
|
|
1341
1107
|
//#endregion
|
|
1342
1108
|
//#region src/processors/observability/processorCollector.ts
|
|
1343
|
-
const
|
|
1109
|
+
const processorObservability = (options, parent) => ({
|
|
1344
1110
|
tracer: options?.observability?.tracer ?? parent?.observability?.tracer ?? noopTracer(),
|
|
1345
1111
|
meter: options?.observability?.meter ?? parent?.observability?.meter ?? noopMeter(),
|
|
1346
1112
|
propagation: options?.observability?.propagation ?? parent?.observability?.propagation ?? "links",
|
|
@@ -1448,9 +1214,10 @@ const defaultProcessorVersion = 1;
|
|
|
1448
1214
|
const defaultProcessorPartition = defaultTag;
|
|
1449
1215
|
const getProcessorInstanceId = (processorId) => `${processorId}:${v7()}`;
|
|
1450
1216
|
const getProjectorId = (options) => `emt:processor:projector:${options.projectionName}`;
|
|
1217
|
+
const { info, error } = LogEvent;
|
|
1451
1218
|
const reactor = (options) => {
|
|
1452
1219
|
const { checkpoints, processorId, processorInstanceId: instanceId = getProcessorInstanceId(processorId), type = MessageProcessorType.REACTOR, version = 1, partition = defaultProcessorPartition, hooks = {}, processingScope = defaultProcessingMessageProcessingScope, startFrom, canHandle, stopAfter } = options;
|
|
1453
|
-
const collector = processorCollector(
|
|
1220
|
+
const collector = processorCollector(processorObservability(options));
|
|
1454
1221
|
const isCustomBatch = "eachBatch" in options && !!options.eachBatch;
|
|
1455
1222
|
const eachBatch = isCustomBatch ? options.eachBatch : async (messages, context) => {
|
|
1456
1223
|
const batchCtx = context.observabilityScope.spanContext();
|
|
@@ -1532,25 +1299,27 @@ const reactor = (options) => {
|
|
|
1532
1299
|
...partialOptions,
|
|
1533
1300
|
observabilityScope: ("observabilityScope" in partialOptions ? partialOptions.observabilityScope ?? noopScope : noopScope) ?? noopScope
|
|
1534
1301
|
};
|
|
1302
|
+
const log = startOptions.observabilityScope.log;
|
|
1535
1303
|
if (isActive) {
|
|
1536
|
-
|
|
1304
|
+
log(info(`Processor ${processorId} with instance id ${instanceId} is already active. Start request ignored.`));
|
|
1537
1305
|
return;
|
|
1538
1306
|
}
|
|
1539
|
-
|
|
1307
|
+
log(info(`Starting processor ${processorId} with instance id ${instanceId}`));
|
|
1540
1308
|
await init(startOptions);
|
|
1541
1309
|
isActive = true;
|
|
1542
1310
|
closeSignal = onShutdown(() => close(startOptions));
|
|
1543
1311
|
if (lastCheckpoint !== null) {
|
|
1544
|
-
|
|
1312
|
+
log(info(`Processor ${processorId} started with instance id ${instanceId}, checkpoint: ${JSONSerializer.serialize(lastCheckpoint)}`));
|
|
1545
1313
|
return { lastCheckpoint };
|
|
1546
1314
|
}
|
|
1547
1315
|
return await processingScope(async (context) => {
|
|
1316
|
+
const log = context.observabilityScope.log;
|
|
1548
1317
|
if (hooks.onStart) {
|
|
1549
|
-
|
|
1318
|
+
log(info(`Executing onStart hook for processor ${processorId} with instance id ${instanceId}`));
|
|
1550
1319
|
await hooks.onStart(context);
|
|
1551
1320
|
}
|
|
1552
1321
|
if (startFrom && startFrom !== "CURRENT") {
|
|
1553
|
-
|
|
1322
|
+
log(info(`Processor ${processorId} with instance id ${instanceId} starting from: ${JSONSerializer.serialize(startFrom)}`));
|
|
1554
1323
|
return startFrom;
|
|
1555
1324
|
}
|
|
1556
1325
|
if (checkpoints) lastCheckpoint = (await checkpoints?.read({
|
|
@@ -1561,10 +1330,10 @@ const reactor = (options) => {
|
|
|
1561
1330
|
...context
|
|
1562
1331
|
})).lastCheckpoint;
|
|
1563
1332
|
if (lastCheckpoint === null) {
|
|
1564
|
-
|
|
1333
|
+
log(info(`Processor ${processorId} with instance id ${instanceId} starting from: BEGINNING`));
|
|
1565
1334
|
return "BEGINNING";
|
|
1566
1335
|
}
|
|
1567
|
-
|
|
1336
|
+
log(info(`Checkpoint read for processor ${processorId} with instance id ${instanceId}: ${JSONSerializer.serialize(lastCheckpoint)}`));
|
|
1568
1337
|
return { lastCheckpoint };
|
|
1569
1338
|
}, startOptions);
|
|
1570
1339
|
},
|
|
@@ -1621,12 +1390,12 @@ const reactor = (options) => {
|
|
|
1621
1390
|
...partialContext,
|
|
1622
1391
|
observabilityScope: scope
|
|
1623
1392
|
});
|
|
1624
|
-
} catch (
|
|
1625
|
-
|
|
1393
|
+
} catch (err) {
|
|
1394
|
+
scope.log(error({ err }, `Error during message processing for processor ${processorId} with instance id ${instanceId}. Stopping the processor.`));
|
|
1626
1395
|
isActive = false;
|
|
1627
1396
|
return {
|
|
1628
1397
|
type: "STOP",
|
|
1629
|
-
error,
|
|
1398
|
+
error: err,
|
|
1630
1399
|
reason: "Error during message processing"
|
|
1631
1400
|
};
|
|
1632
1401
|
}
|
|
@@ -1996,6 +1765,7 @@ const assertThatArray = (array) => {
|
|
|
1996
1765
|
|
|
1997
1766
|
//#endregion
|
|
1998
1767
|
//#region src/testing/deciderSpecification.ts
|
|
1768
|
+
const isPromiseLike = (value) => value !== null && (typeof value === "object" || typeof value === "function") && typeof value.then === "function";
|
|
1999
1769
|
const DeciderSpecification = { for: deciderSpecificationFor };
|
|
2000
1770
|
function deciderSpecificationFor(decider) {
|
|
2001
1771
|
return (givenEvents) => {
|
|
@@ -2005,16 +1775,14 @@ function deciderSpecificationFor(decider) {
|
|
|
2005
1775
|
return decider.decide(command, currentState);
|
|
2006
1776
|
};
|
|
2007
1777
|
return {
|
|
2008
|
-
then: (
|
|
1778
|
+
then: (expectedEventsOrAssert) => {
|
|
2009
1779
|
const resultEvents = handle();
|
|
2010
|
-
if (resultEvents
|
|
2011
|
-
|
|
2012
|
-
});
|
|
2013
|
-
thenHandler$1(resultEvents, expectedEvents);
|
|
1780
|
+
if (isPromiseLike(resultEvents)) return Promise.resolve(resultEvents).then((events) => thenHandler$1(events, expectedEventsOrAssert));
|
|
1781
|
+
return thenHandler$1(resultEvents, expectedEventsOrAssert);
|
|
2014
1782
|
},
|
|
2015
1783
|
thenNothingHappened: () => {
|
|
2016
1784
|
const resultEvents = handle();
|
|
2017
|
-
if (resultEvents
|
|
1785
|
+
if (isPromiseLike(resultEvents)) return Promise.resolve(resultEvents).then((events) => {
|
|
2018
1786
|
thenNothingHappensHandler$1(events);
|
|
2019
1787
|
});
|
|
2020
1788
|
thenNothingHappensHandler$1(resultEvents);
|
|
@@ -2022,7 +1790,7 @@ function deciderSpecificationFor(decider) {
|
|
|
2022
1790
|
thenThrows: (...args) => {
|
|
2023
1791
|
try {
|
|
2024
1792
|
const result = handle();
|
|
2025
|
-
if (result
|
|
1793
|
+
if (isPromiseLike(result)) return Promise.resolve(result).then(() => {
|
|
2026
1794
|
throw new AssertionError("Handler did not fail as expected");
|
|
2027
1795
|
}).catch((error) => {
|
|
2028
1796
|
thenThrowsErrorHandler$1(error, args);
|
|
@@ -2036,11 +1804,26 @@ function deciderSpecificationFor(decider) {
|
|
|
2036
1804
|
} };
|
|
2037
1805
|
};
|
|
2038
1806
|
}
|
|
2039
|
-
function thenHandler$1(events,
|
|
1807
|
+
function thenHandler$1(events, expectedEventsOrAssert) {
|
|
2040
1808
|
const resultEventsArray = Array.isArray(events) ? events : [events];
|
|
2041
|
-
|
|
1809
|
+
if (typeof expectedEventsOrAssert === "function") return runThenAssert(resultEventsArray, expectedEventsOrAssert);
|
|
1810
|
+
const expectedEventsArray = Array.isArray(expectedEventsOrAssert) ? expectedEventsOrAssert : [expectedEventsOrAssert];
|
|
2042
1811
|
assertThatArray(resultEventsArray).containsOnlyElementsMatching(expectedEventsArray);
|
|
2043
1812
|
}
|
|
1813
|
+
/**
|
|
1814
|
+
* Runs the client-provided assertion. The test fails (throws) when the callback
|
|
1815
|
+
* throws, returns an `Error`, or returns a Promise that rejects or resolves to
|
|
1816
|
+
* an `Error`. A thrown error is propagated as-is so the client's assertion
|
|
1817
|
+
* library (node:assert, Vitest `expect`, ...) keeps its own message and diff.
|
|
1818
|
+
*/
|
|
1819
|
+
function runThenAssert(events, assert) {
|
|
1820
|
+
const outcome = assert(events);
|
|
1821
|
+
if (isPromiseLike(outcome)) return Promise.resolve(outcome).then(failIfError);
|
|
1822
|
+
failIfError(outcome);
|
|
1823
|
+
}
|
|
1824
|
+
function failIfError(outcome) {
|
|
1825
|
+
if (outcome instanceof Error) throw outcome;
|
|
1826
|
+
}
|
|
2044
1827
|
function thenNothingHappensHandler$1(events) {
|
|
2045
1828
|
assertThatArray(Array.isArray(events) ? events : [events]).isEmpty();
|
|
2046
1829
|
}
|
|
@@ -2185,7 +1968,7 @@ const InMemoryProjectionSpec = { for: (options) => {
|
|
|
2185
1968
|
return Promise.resolve(false);
|
|
2186
1969
|
}
|
|
2187
1970
|
},
|
|
2188
|
-
observability:
|
|
1971
|
+
observability: eventStoreObservability(void 0)
|
|
2189
1972
|
});
|
|
2190
1973
|
};
|
|
2191
1974
|
return {
|
|
@@ -2290,6 +2073,88 @@ const upcastRecordedMessages = (recordedMessages, options) => {
|
|
|
2290
2073
|
return recordedMessages.map((recordedMessage) => upcastRecordedMessage(recordedMessage, options));
|
|
2291
2074
|
};
|
|
2292
2075
|
|
|
2076
|
+
//#endregion
|
|
2077
|
+
//#region src/eventStore/observability/eventStoreCollector.ts
|
|
2078
|
+
const eventStoreObservability = (options, parent) => ({
|
|
2079
|
+
tracer: options?.observability?.tracer ?? parent?.observability?.tracer ?? noopTracer(),
|
|
2080
|
+
meter: options?.observability?.meter ?? parent?.observability?.meter ?? noopMeter(),
|
|
2081
|
+
attributeTarget: options?.observability?.attributeTarget ?? parent?.observability?.attributeTarget ?? "both"
|
|
2082
|
+
});
|
|
2083
|
+
const eventStoreCollector = (observability) => {
|
|
2084
|
+
const A = EmmettAttributes;
|
|
2085
|
+
const M = MessagingAttributes;
|
|
2086
|
+
const streamReadingDuration = observability.meter.histogram(EmmettMetrics.stream.readingDuration);
|
|
2087
|
+
const streamReadingSize = observability.meter.histogram(EmmettMetrics.stream.readingSize);
|
|
2088
|
+
const eventReadingCount = observability.meter.counter(EmmettMetrics.event.readingCount);
|
|
2089
|
+
const streamAppendingDuration = observability.meter.histogram(EmmettMetrics.stream.appendingDuration);
|
|
2090
|
+
const streamAppendingSize = observability.meter.histogram(EmmettMetrics.stream.appendingSize);
|
|
2091
|
+
const eventAppendingCount = observability.meter.counter(EmmettMetrics.event.appendingCount);
|
|
2092
|
+
return {
|
|
2093
|
+
instrumentRead: (streamName, fn) => {
|
|
2094
|
+
const start = Date.now();
|
|
2095
|
+
return observability.tracer.startSpan("eventStore.readStream", async (span) => {
|
|
2096
|
+
span.setAttributes({
|
|
2097
|
+
[A.eventStore.operation]: "readStream",
|
|
2098
|
+
[A.stream.name]: streamName,
|
|
2099
|
+
[M.operation.type]: "receive",
|
|
2100
|
+
[M.destination.name]: streamName,
|
|
2101
|
+
[M.system]: MessagingSystemName
|
|
2102
|
+
});
|
|
2103
|
+
let status = "success";
|
|
2104
|
+
try {
|
|
2105
|
+
const result = await fn();
|
|
2106
|
+
const events = result.events;
|
|
2107
|
+
span.setAttributes({
|
|
2108
|
+
[A.eventStore.read.status]: status,
|
|
2109
|
+
[A.eventStore.read.eventCount]: events.length,
|
|
2110
|
+
[A.eventStore.read.eventTypes]: [...new Set(events.map((e) => e.type))]
|
|
2111
|
+
});
|
|
2112
|
+
streamReadingSize.record(events.length, { [A.eventStore.read.status]: status });
|
|
2113
|
+
for (const event of events) eventReadingCount.add(1, { [A.event.type]: event.type });
|
|
2114
|
+
return result;
|
|
2115
|
+
} catch (err) {
|
|
2116
|
+
status = "failure";
|
|
2117
|
+
span.setAttributes({ [A.eventStore.read.status]: status });
|
|
2118
|
+
throw err;
|
|
2119
|
+
} finally {
|
|
2120
|
+
streamReadingDuration.record(Date.now() - start, { [A.eventStore.read.status]: status });
|
|
2121
|
+
}
|
|
2122
|
+
});
|
|
2123
|
+
},
|
|
2124
|
+
instrumentAppend: (streamName, events, fn) => {
|
|
2125
|
+
const start = Date.now();
|
|
2126
|
+
return observability.tracer.startSpan("eventStore.appendToStream", async (span) => {
|
|
2127
|
+
span.setAttributes({
|
|
2128
|
+
[A.eventStore.operation]: "appendToStream",
|
|
2129
|
+
[A.stream.name]: streamName,
|
|
2130
|
+
[A.eventStore.append.batchSize]: events.length,
|
|
2131
|
+
[M.operation.type]: "send",
|
|
2132
|
+
[M.batch.messageCount]: events.length,
|
|
2133
|
+
[M.destination.name]: streamName,
|
|
2134
|
+
[M.system]: MessagingSystemName
|
|
2135
|
+
});
|
|
2136
|
+
let status = "success";
|
|
2137
|
+
try {
|
|
2138
|
+
const result = await fn();
|
|
2139
|
+
span.setAttributes({
|
|
2140
|
+
[A.eventStore.append.status]: status,
|
|
2141
|
+
[A.stream.versionAfter]: Number(result.nextExpectedStreamVersion)
|
|
2142
|
+
});
|
|
2143
|
+
streamAppendingSize.record(events.length, { [A.eventStore.append.status]: status });
|
|
2144
|
+
for (const event of events) eventAppendingCount.add(1, { [A.event.type]: event.type });
|
|
2145
|
+
return result;
|
|
2146
|
+
} catch (err) {
|
|
2147
|
+
status = "failure";
|
|
2148
|
+
span.setAttributes({ [A.eventStore.append.status]: status });
|
|
2149
|
+
throw err;
|
|
2150
|
+
} finally {
|
|
2151
|
+
streamAppendingDuration.record(Date.now() - start, { [A.eventStore.append.status]: status });
|
|
2152
|
+
}
|
|
2153
|
+
});
|
|
2154
|
+
}
|
|
2155
|
+
};
|
|
2156
|
+
};
|
|
2157
|
+
|
|
2293
2158
|
//#endregion
|
|
2294
2159
|
//#region src/eventStore/inMemoryEventStore.ts
|
|
2295
2160
|
const InMemoryEventStoreDefaultStreamVersion = 0n;
|
|
@@ -2300,7 +2165,7 @@ const getInMemoryEventStore = (eventStoreOptions) => {
|
|
|
2300
2165
|
};
|
|
2301
2166
|
const database = eventStoreOptions?.database || getInMemoryDatabase();
|
|
2302
2167
|
const inlineProjections = (eventStoreOptions?.projections ?? []).filter(({ type }) => type === "inline").map(({ projection }) => projection);
|
|
2303
|
-
const observability =
|
|
2168
|
+
const observability = eventStoreObservability(eventStoreOptions);
|
|
2304
2169
|
const collector = eventStoreCollector(observability);
|
|
2305
2170
|
const eventStore = {
|
|
2306
2171
|
database,
|
|
@@ -2382,7 +2247,7 @@ const getInMemoryEventStore = (eventStoreOptions) => {
|
|
|
2382
2247
|
|
|
2383
2248
|
//#endregion
|
|
2384
2249
|
//#region src/commandHandling/observability/commandHandlerCollector.ts
|
|
2385
|
-
const
|
|
2250
|
+
const commandObservability = (options, parent) => ({
|
|
2386
2251
|
tracer: options?.observability?.tracer ?? parent?.observability?.tracer ?? noopTracer(),
|
|
2387
2252
|
meter: options?.observability?.meter ?? parent?.observability?.meter ?? noopMeter(),
|
|
2388
2253
|
attributeTarget: options?.observability?.attributeTarget ?? parent?.observability?.attributeTarget ?? "both",
|
|
@@ -2426,7 +2291,7 @@ const commandHandlerCollector = (observability) => {
|
|
|
2426
2291
|
"exception.message": err instanceof Error ? err.message : String(err),
|
|
2427
2292
|
"exception.type": err instanceof Error ? err.constructor.name : "unknown"
|
|
2428
2293
|
});
|
|
2429
|
-
scope.
|
|
2294
|
+
scope.log(LogEvent.error(err instanceof Error ? err : new Error(String(err))));
|
|
2430
2295
|
throw err;
|
|
2431
2296
|
} finally {
|
|
2432
2297
|
commandHandlingDuration.record(Date.now() - start, {
|
|
@@ -2475,7 +2340,7 @@ const CommandHandlerStreamVersionConflictRetryOptions = {
|
|
|
2475
2340
|
shouldRetryError: isExpectedVersionConflictError
|
|
2476
2341
|
};
|
|
2477
2342
|
const CommandHandler = (options) => async (store, id, handle, handleOptions) => {
|
|
2478
|
-
const collector = commandHandlerCollector(
|
|
2343
|
+
const collector = commandHandlerCollector(commandObservability(options));
|
|
2479
2344
|
const streamName = (options.mapToStreamId ?? ((id) => id))(id);
|
|
2480
2345
|
const commandType = handleOptions?.commandType ?? options.commandType ?? options.name ?? handlerNames(handle);
|
|
2481
2346
|
const correlationId = handleOptions?.observability?.correlationId ?? v7();
|
|
@@ -2574,6 +2439,61 @@ const DeciderCommandHandler = (options) => async (eventStore, id, commands, hand
|
|
|
2574
2439
|
});
|
|
2575
2440
|
};
|
|
2576
2441
|
|
|
2442
|
+
//#endregion
|
|
2443
|
+
//#region src/consumers/observability/consumerCollector.ts
|
|
2444
|
+
const consumerObservability = (options, parent) => {
|
|
2445
|
+
const observability = mergeObservabilityOptions({ observability: options?.observability }, parent?.observability).observability;
|
|
2446
|
+
return {
|
|
2447
|
+
tracer: observability?.tracer ?? noopTracer(),
|
|
2448
|
+
meter: observability?.meter ?? noopMeter(),
|
|
2449
|
+
pollTracing: observability?.pollTracing ?? "off",
|
|
2450
|
+
attributeTarget: observability?.attributeTarget ?? "both"
|
|
2451
|
+
};
|
|
2452
|
+
};
|
|
2453
|
+
const consumerCollector = (observability) => {
|
|
2454
|
+
const { startScope } = ObservabilityScope({
|
|
2455
|
+
...observability,
|
|
2456
|
+
attributePrefix: "emmett"
|
|
2457
|
+
});
|
|
2458
|
+
const A = EmmettAttributes;
|
|
2459
|
+
const M = MessagingAttributes;
|
|
2460
|
+
const pollDuration = observability.meter.histogram(EmmettMetrics.consumer.pollDuration);
|
|
2461
|
+
const deliveryDuration = observability.meter.histogram(EmmettMetrics.consumer.deliveryDuration);
|
|
2462
|
+
return {
|
|
2463
|
+
tracePoll: (context, fn) => {
|
|
2464
|
+
if (observability.pollTracing === "off" || observability.pollTracing === "active" && context.batchSize === 0) return fn(noopScope);
|
|
2465
|
+
return startScope("consumer.poll", async (scope) => {
|
|
2466
|
+
scope.setAttributes({
|
|
2467
|
+
[A.scope.type]: ScopeTypes.consumer,
|
|
2468
|
+
[A.consumer.batchSize]: context.batchSize,
|
|
2469
|
+
[A.consumer.processorCount]: context.processorCount,
|
|
2470
|
+
[M.system]: MessagingSystemName,
|
|
2471
|
+
[M.operation.type]: "receive",
|
|
2472
|
+
...context.empty ? { "emmett.consumer.poll.empty": true } : {},
|
|
2473
|
+
...context.waitMs != null ? { "emmett.consumer.poll.wait_ms": context.waitMs } : {}
|
|
2474
|
+
});
|
|
2475
|
+
return fn(scope);
|
|
2476
|
+
});
|
|
2477
|
+
},
|
|
2478
|
+
recordPollMetrics: (durationMs, attrs) => {
|
|
2479
|
+
pollDuration.record(durationMs, attrs);
|
|
2480
|
+
},
|
|
2481
|
+
traceDelivery: (scope, processorId, fn) => {
|
|
2482
|
+
const start = Date.now();
|
|
2483
|
+
return scope.scope(`consumer.deliver.${processorId}`, async (child) => {
|
|
2484
|
+
try {
|
|
2485
|
+
return await fn();
|
|
2486
|
+
} catch (error) {
|
|
2487
|
+
if (error instanceof Error) child.log(LogEvent.error(error));
|
|
2488
|
+
throw error;
|
|
2489
|
+
} finally {
|
|
2490
|
+
deliveryDuration.record(Date.now() - start, { [A.consumer.delivery.processorId]: processorId });
|
|
2491
|
+
}
|
|
2492
|
+
}, { attributes: { [A.consumer.delivery.processorId]: processorId } });
|
|
2493
|
+
}
|
|
2494
|
+
};
|
|
2495
|
+
};
|
|
2496
|
+
|
|
2577
2497
|
//#endregion
|
|
2578
2498
|
//#region src/messageBus/index.ts
|
|
2579
2499
|
const getInMemoryMessageBus = () => {
|
|
@@ -2640,6 +2560,66 @@ const projections = {
|
|
|
2640
2560
|
async: asyncProjections
|
|
2641
2561
|
};
|
|
2642
2562
|
|
|
2563
|
+
//#endregion
|
|
2564
|
+
//#region src/workflows/observability/workflowCollector.ts
|
|
2565
|
+
const workflowObservability = (options, parent) => {
|
|
2566
|
+
const observability = mergeObservabilityOptions({ observability: options?.observability }, parent?.observability).observability;
|
|
2567
|
+
return {
|
|
2568
|
+
tracer: observability?.tracer ?? noopTracer(),
|
|
2569
|
+
meter: observability?.meter ?? noopMeter(),
|
|
2570
|
+
propagation: observability?.propagation ?? "links",
|
|
2571
|
+
attributeTarget: observability?.attributeTarget ?? "both",
|
|
2572
|
+
includeMessagePayloads: observability?.includeMessagePayloads ?? false
|
|
2573
|
+
};
|
|
2574
|
+
};
|
|
2575
|
+
const workflowCollector = (observability) => {
|
|
2576
|
+
const { startScope } = ObservabilityScope({
|
|
2577
|
+
...observability,
|
|
2578
|
+
attributePrefix: "emmett"
|
|
2579
|
+
});
|
|
2580
|
+
const A = EmmettAttributes;
|
|
2581
|
+
const M = MessagingAttributes;
|
|
2582
|
+
const processingDuration = observability.meter.histogram(EmmettMetrics.workflow.processingDuration);
|
|
2583
|
+
return {
|
|
2584
|
+
startScope: (context, fn) => {
|
|
2585
|
+
const start = Date.now();
|
|
2586
|
+
return startScope("workflow.handle", async (scope) => {
|
|
2587
|
+
scope.setAttributes({
|
|
2588
|
+
[A.scope.type]: ScopeTypes.workflow,
|
|
2589
|
+
[A.workflow.id]: context.workflowId,
|
|
2590
|
+
[A.workflow.type]: context.workflowType,
|
|
2591
|
+
[A.workflow.inputType]: context.inputType,
|
|
2592
|
+
[M.system]: MessagingSystemName
|
|
2593
|
+
});
|
|
2594
|
+
let status = "success";
|
|
2595
|
+
try {
|
|
2596
|
+
return await fn(scope);
|
|
2597
|
+
} catch (err) {
|
|
2598
|
+
status = "failure";
|
|
2599
|
+
throw err;
|
|
2600
|
+
} finally {
|
|
2601
|
+
processingDuration.record(Date.now() - start, {
|
|
2602
|
+
[A.workflow.type]: context.workflowType,
|
|
2603
|
+
status
|
|
2604
|
+
});
|
|
2605
|
+
}
|
|
2606
|
+
}, { attributes: {
|
|
2607
|
+
[A.scope.type]: ScopeTypes.workflow,
|
|
2608
|
+
[A.workflow.type]: context.workflowType
|
|
2609
|
+
} });
|
|
2610
|
+
},
|
|
2611
|
+
recordOutputs: (scope, outputs) => {
|
|
2612
|
+
scope.setAttributes({
|
|
2613
|
+
[A.workflow.outputs]: outputs.map((o) => o.type),
|
|
2614
|
+
[A.workflow.outputsCount]: outputs.length
|
|
2615
|
+
});
|
|
2616
|
+
},
|
|
2617
|
+
recordStateRebuild: (scope, eventCount) => {
|
|
2618
|
+
scope.setAttributes({ [A.workflow.stateRebuildEventCount]: eventCount });
|
|
2619
|
+
}
|
|
2620
|
+
};
|
|
2621
|
+
};
|
|
2622
|
+
|
|
2643
2623
|
//#endregion
|
|
2644
2624
|
//#region src/workflows/handleWorkflow.ts
|
|
2645
2625
|
const WorkflowHandlerStreamVersionConflictRetryOptions = {
|
|
@@ -2709,7 +2689,7 @@ const createWrappedEvolve = (evolve, workflowName, separateInputInboxFromProcess
|
|
|
2709
2689
|
};
|
|
2710
2690
|
const workflowStreamName = ({ workflowName, workflowId }) => `emt:workflow:${workflowName}:${workflowId}`;
|
|
2711
2691
|
const WorkflowHandler = (options) => async (store, message, handleOptions) => {
|
|
2712
|
-
const collector = workflowCollector(
|
|
2692
|
+
const collector = workflowCollector(workflowObservability(options));
|
|
2713
2693
|
const workflowType = options.workflow.name;
|
|
2714
2694
|
const inputType = message.type;
|
|
2715
2695
|
const workflowId = options.getWorkflowId(message) ?? "";
|
|
@@ -2895,8 +2875,6 @@ var src_exports = /* @__PURE__ */ __exportAll({
|
|
|
2895
2875
|
JSONReviver: () => JSONReviver,
|
|
2896
2876
|
JSONRevivers: () => JSONRevivers,
|
|
2897
2877
|
JSONSerializer: () => JSONSerializer,
|
|
2898
|
-
LogLevel: () => LogLevel,
|
|
2899
|
-
LogStyle: () => LogStyle,
|
|
2900
2878
|
MessageProcessor: () => MessageProcessor,
|
|
2901
2879
|
MessageProcessorType: () => MessageProcessorType,
|
|
2902
2880
|
MessagingSystemName: () => MessagingSystemName,
|
|
@@ -2952,6 +2930,7 @@ var src_exports = /* @__PURE__ */ __exportAll({
|
|
|
2952
2930
|
composeJSONReplacers: () => composeJSONReplacers,
|
|
2953
2931
|
composeJSONRevivers: () => composeJSONRevivers,
|
|
2954
2932
|
consumerCollector: () => consumerCollector,
|
|
2933
|
+
consumerObservability: () => consumerObservability,
|
|
2955
2934
|
deepEquals: () => deepEquals,
|
|
2956
2935
|
defaultProcessingMessageProcessingScope: () => defaultProcessingMessageProcessingScope,
|
|
2957
2936
|
defaultProcessorPartition: () => defaultProcessorPartition,
|
|
@@ -2962,9 +2941,11 @@ var src_exports = /* @__PURE__ */ __exportAll({
|
|
|
2962
2941
|
downcastRecordedMessage: () => downcastRecordedMessage,
|
|
2963
2942
|
downcastRecordedMessages: () => downcastRecordedMessages,
|
|
2964
2943
|
emmettPrefix: () => "emt",
|
|
2944
|
+
errorReplacer: () => errorReplacer,
|
|
2965
2945
|
event: () => event,
|
|
2966
2946
|
eventInStream: () => eventInStream,
|
|
2967
2947
|
eventStoreCollector: () => eventStoreCollector,
|
|
2948
|
+
eventStoreObservability: () => eventStoreObservability,
|
|
2968
2949
|
eventsInStream: () => eventsInStream,
|
|
2969
2950
|
expectInMemoryDocuments: () => expectInMemoryDocuments,
|
|
2970
2951
|
filterProjections: () => filterProjections,
|
|
@@ -3006,6 +2987,7 @@ var src_exports = /* @__PURE__ */ __exportAll({
|
|
|
3006
2987
|
jsonSerializer: () => jsonSerializer,
|
|
3007
2988
|
matchesExpectedVersion: () => matchesExpectedVersion,
|
|
3008
2989
|
merge: () => merge,
|
|
2990
|
+
mergeObservabilityOptions: () => mergeObservabilityOptions,
|
|
3009
2991
|
message: () => message,
|
|
3010
2992
|
newEventsInStream: () => newEventsInStream,
|
|
3011
2993
|
nulloSessionFactory: () => nulloSessionFactory,
|
|
@@ -3013,18 +2995,14 @@ var src_exports = /* @__PURE__ */ __exportAll({
|
|
|
3013
2995
|
parseBigIntProcessorCheckpoint: () => parseBigIntProcessorCheckpoint,
|
|
3014
2996
|
parseDateFromUtcYYYYMMDD: () => parseDateFromUtcYYYYMMDD,
|
|
3015
2997
|
processorCollector: () => processorCollector,
|
|
2998
|
+
processorObservability: () => processorObservability,
|
|
3016
2999
|
projection: () => projection,
|
|
3017
3000
|
projections: () => projections,
|
|
3018
3001
|
projector: () => projector,
|
|
3019
3002
|
reactor: () => reactor,
|
|
3020
3003
|
reduceAsync: () => reduceAsync,
|
|
3021
|
-
resolveConsumerObservability: () => resolveConsumerObservability,
|
|
3022
|
-
resolveEventStoreObservability: () => resolveEventStoreObservability,
|
|
3023
|
-
resolveProcessorObservability: () => resolveProcessorObservability,
|
|
3024
|
-
resolveWorkflowObservability: () => resolveWorkflowObservability,
|
|
3025
3004
|
sum: () => sum,
|
|
3026
3005
|
toNormalizedString: () => toNormalizedString,
|
|
3027
|
-
tracer: () => tracer,
|
|
3028
3006
|
tryPublishMessagesAfterCommit: () => tryPublishMessagesAfterCommit,
|
|
3029
3007
|
unknownTag: () => unknownTag,
|
|
3030
3008
|
upcastRecordedMessage: () => upcastRecordedMessage,
|
|
@@ -3032,11 +3010,12 @@ var src_exports = /* @__PURE__ */ __exportAll({
|
|
|
3032
3010
|
verifyThat: () => verifyThat,
|
|
3033
3011
|
wasMessageHandled: () => wasMessageHandled,
|
|
3034
3012
|
workflowCollector: () => workflowCollector,
|
|
3013
|
+
workflowObservability: () => workflowObservability,
|
|
3035
3014
|
workflowOutputHandler: () => workflowOutputHandler,
|
|
3036
3015
|
workflowProcessor: () => workflowProcessor,
|
|
3037
3016
|
workflowStreamName: () => workflowStreamName
|
|
3038
3017
|
});
|
|
3039
3018
|
|
|
3040
3019
|
//#endregion
|
|
3041
|
-
export { AssertionError, CommandHandler, CommandHandlerStreamVersionConflictRetryOptions, ConcurrencyError, ConcurrencyInMemoryDatabaseError, DATABASE_REQUIRED_ERROR_MESSAGE, DeciderCommandHandler, DeciderSpecification, EmmettAttributes, EmmettError, EmmettMetrics, ExpectedVersionConflictError, GlobalStreamCaughtUpType, IllegalStateError, InMemoryEventStoreDefaultStreamVersion, InMemoryProjectionSpec, InProcessLock, JSONCodec, JSONReplacer, JSONReplacers, JSONReviver, JSONRevivers, JSONSerializer,
|
|
3020
|
+
export { AssertionError, CommandHandler, CommandHandlerStreamVersionConflictRetryOptions, ConcurrencyError, ConcurrencyInMemoryDatabaseError, DATABASE_REQUIRED_ERROR_MESSAGE, DeciderCommandHandler, DeciderSpecification, EmmettAttributes, EmmettError, EmmettMetrics, ExpectedVersionConflictError, GlobalStreamCaughtUpType, IllegalStateError, InMemoryEventStoreDefaultStreamVersion, InMemoryProjectionSpec, InProcessLock, JSONCodec, JSONReplacer, JSONReplacers, JSONReviver, JSONRevivers, JSONSerializer, MessageProcessor, MessageProcessorType, MessagingSystemName, NO_CONCURRENCY_CHECK, NoRetries, NotFoundError, ProcessorCheckpoint, STREAM_DOES_NOT_EXIST, STREAM_EXISTS, ScopeTypes, TaskProcessor, ValidationError, ValidationErrors, Workflow, WorkflowHandler, WorkflowHandlerStreamVersionConflictRetryOptions, WorkflowSpecification, WrapEventStore, argMatches, argValue, arrayUtils, assertDeepEqual, assertDefined, assertDoesNotThrow, assertEqual, assertExpectedVersionMatchesCurrent, assertFails, assertFalse, assertIsNotNull, assertIsNull, assertMatches, assertNotDeepEqual, assertNotEmptyString, assertNotEqual, assertOk, assertPositiveNumber, assertRejects, assertThat, assertThatArray, assertThrows, assertThrowsAsync, assertTrue, assertUndefined, assertUnsignedBigInt, asyncAwaiter, asyncProjections, asyncRetry, bigInt, bigIntProcessorCheckpoint, canCreateEventStoreSession, caughtUpEventFrom, command, composeJSONReplacers, composeJSONRevivers, consumerCollector, consumerObservability, deepEquals, defaultProcessingMessageProcessingScope, defaultProcessorPartition, defaultProcessorVersion, defaultTag, delay, documentExists, downcastRecordedMessage, downcastRecordedMessages, emmettPrefix, errorReplacer, event, eventInStream, eventStoreCollector, eventStoreObservability, eventsInStream, expectInMemoryDocuments, filterProjections, formatDateToUtcYYYYMMDD, forwardToMessageBus, getCheckpoint, getInMemoryDatabase, getInMemoryEventStore, getInMemoryMessageBus, getProcessorInstanceId, getProjectorId, getWorkflowId, globalStreamCaughtUp, globalTag, guardBoundedAccess, guardExclusiveAccess, guardInitializedOnce, handleInMemoryProjections, hashText, inMemoryCheckpointer, inMemoryMultiStreamProjection, inMemoryProjection, inMemoryProjector, inMemoryReactor, inMemorySingleStreamProjection, inlineProjections, isBigint, isEquatable, isErrorConstructor, isExpectedVersionConflictError, isGlobalStreamCaughtUp, isNotInternalEvent, isNumber, isPluginConfig, isString, isSubscriptionEvent, isSubset, isValidYYYYMMDD, jsonSerializer, matchesExpectedVersion, merge, mergeObservabilityOptions, message, newEventsInStream, nulloSessionFactory, onShutdown, parseBigIntProcessorCheckpoint, parseDateFromUtcYYYYMMDD, processorCollector, processorObservability, projection, projections, projector, reactor, reduceAsync, sum, toNormalizedString, tryPublishMessagesAfterCommit, unknownTag, upcastRecordedMessage, upcastRecordedMessages, verifyThat, wasMessageHandled, workflowCollector, workflowObservability, workflowOutputHandler, workflowProcessor, workflowStreamName };
|
|
3042
3021
|
//# sourceMappingURL=index.js.map
|