@event-driven-io/emmett 0.43.0-beta.14 → 0.43.0-beta.16
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/cli.cjs.map +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +389 -80
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +36 -6
- package/dist/index.d.ts +36 -6
- package/dist/index.js +389 -81
- package/dist/index.js.map +1 -1
- package/dist/plugins-CUbnGFPp.js.map +1 -1
- package/dist/plugins-DB9xe8AV.cjs.map +1 -1
- package/package.json +6 -3
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
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-CUbnGFPp.js";
|
|
2
2
|
import { v4, v7 } from "uuid";
|
|
3
3
|
import retry from "async-retry";
|
|
4
|
+
import { MessagingAttributes, ObservabilityScope, noopMeter, noopTracer } from "@event-driven-io/almanac";
|
|
4
5
|
|
|
5
6
|
//#region src/eventStore/afterCommit/afterEventStoreCommitHandler.ts
|
|
6
7
|
async function tryPublishMessagesAfterCommit(messages, options, context) {
|
|
@@ -1068,14 +1069,27 @@ const reactor = (options) => {
|
|
|
1068
1069
|
canHandle,
|
|
1069
1070
|
init,
|
|
1070
1071
|
start: async (startOptions) => {
|
|
1071
|
-
if (isActive)
|
|
1072
|
+
if (isActive) {
|
|
1073
|
+
console.log(`Processor ${processorId} with instance id ${instanceId} is already active. Start request ignored.`);
|
|
1074
|
+
return;
|
|
1075
|
+
}
|
|
1076
|
+
console.log(`Starting processor ${processorId} with instance id ${instanceId}`);
|
|
1072
1077
|
await init(startOptions);
|
|
1073
1078
|
isActive = true;
|
|
1074
1079
|
closeSignal = onShutdown(() => close(startOptions));
|
|
1075
|
-
if (lastCheckpoint !== null)
|
|
1080
|
+
if (lastCheckpoint !== null) {
|
|
1081
|
+
console.log(`Processor ${processorId} started with instance id ${instanceId}, checkpoint: ${JSONSerializer.serialize(lastCheckpoint)}`);
|
|
1082
|
+
return { lastCheckpoint };
|
|
1083
|
+
}
|
|
1076
1084
|
return await processingScope(async (context) => {
|
|
1077
|
-
if (hooks.onStart)
|
|
1078
|
-
|
|
1085
|
+
if (hooks.onStart) {
|
|
1086
|
+
console.log(`Executing onStart hook for processor ${processorId} with instance id ${instanceId}`);
|
|
1087
|
+
await hooks.onStart(context);
|
|
1088
|
+
}
|
|
1089
|
+
if (startFrom && startFrom !== "CURRENT") {
|
|
1090
|
+
console.log(`Processor ${processorId} with instance id ${instanceId} starting from: ${JSONSerializer.serialize(startFrom)}`);
|
|
1091
|
+
return startFrom;
|
|
1092
|
+
}
|
|
1079
1093
|
if (checkpoints) lastCheckpoint = (await checkpoints?.read({
|
|
1080
1094
|
processorId,
|
|
1081
1095
|
partition
|
|
@@ -1083,7 +1097,11 @@ const reactor = (options) => {
|
|
|
1083
1097
|
...startOptions,
|
|
1084
1098
|
...context
|
|
1085
1099
|
})).lastCheckpoint;
|
|
1086
|
-
if (lastCheckpoint === null)
|
|
1100
|
+
if (lastCheckpoint === null) {
|
|
1101
|
+
console.log(`Processor ${processorId} with instance id ${instanceId} starting from: BEGINNING`);
|
|
1102
|
+
return "BEGINNING";
|
|
1103
|
+
}
|
|
1104
|
+
console.log(`Checkpoint read for processor ${processorId} with instance id ${instanceId}: ${JSONSerializer.serialize(lastCheckpoint)}`);
|
|
1087
1105
|
return { lastCheckpoint };
|
|
1088
1106
|
}, startOptions);
|
|
1089
1107
|
},
|
|
@@ -1093,34 +1111,44 @@ const reactor = (options) => {
|
|
|
1093
1111
|
},
|
|
1094
1112
|
handle: async (messages, partialContext) => {
|
|
1095
1113
|
if (!isActive) return Promise.resolve();
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1114
|
+
try {
|
|
1115
|
+
return await processingScope(async (context) => {
|
|
1116
|
+
const messagesAboveCheckpoint = messages.filter((message) => !wasMessageHandled(message, lastCheckpoint));
|
|
1117
|
+
const upcastedMessages = messagesAboveCheckpoint.map((message) => upcastRecordedMessage(message, options.messageOptions?.schema?.versioning)).filter((upcasted) => !canHandle || canHandle.includes(upcasted.type));
|
|
1118
|
+
const stopMessageIndex = isCustomBatch && stopAfter ? upcastedMessages.findIndex(stopAfter) : -1;
|
|
1119
|
+
const unhandledMessages = stopMessageIndex !== -1 ? upcastedMessages.slice(0, stopMessageIndex + 1) : upcastedMessages;
|
|
1120
|
+
const batchResult = await eachBatch(unhandledMessages, context);
|
|
1121
|
+
const messageProcessingResult = batchResult?.type === "STOP" ? batchResult : stopMessageIndex !== -1 ? {
|
|
1122
|
+
type: "STOP",
|
|
1123
|
+
reason: "Stop condition reached",
|
|
1124
|
+
lastSuccessfulMessage: unhandledMessages[stopMessageIndex]
|
|
1125
|
+
} : batchResult;
|
|
1126
|
+
const isStop = messageProcessingResult && messageProcessingResult.type === "STOP";
|
|
1127
|
+
const checkpointMessage = messageProcessingResult?.type === "STOP" ? messageProcessingResult.lastSuccessfulMessage : messagesAboveCheckpoint[messagesAboveCheckpoint.length - 1];
|
|
1128
|
+
if (checkpointMessage && checkpoints) {
|
|
1129
|
+
const storeCheckpointResult = await checkpoints.store({
|
|
1130
|
+
processorId,
|
|
1131
|
+
version,
|
|
1132
|
+
message: checkpointMessage,
|
|
1133
|
+
lastCheckpoint,
|
|
1134
|
+
partition
|
|
1135
|
+
}, context);
|
|
1136
|
+
if (storeCheckpointResult.success) lastCheckpoint = storeCheckpointResult.newCheckpoint;
|
|
1137
|
+
}
|
|
1138
|
+
if (isStop) {
|
|
1139
|
+
isActive = false;
|
|
1140
|
+
return messageProcessingResult;
|
|
1141
|
+
}
|
|
1142
|
+
}, partialContext);
|
|
1143
|
+
} catch (error) {
|
|
1144
|
+
console.log(`Error during message processing for processor ${processorId} with instance id ${instanceId}. Stopping the processor.`, error);
|
|
1145
|
+
isActive = false;
|
|
1146
|
+
return {
|
|
1103
1147
|
type: "STOP",
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
}
|
|
1107
|
-
|
|
1108
|
-
const checkpointMessage = messageProcessingResult?.type === "STOP" ? messageProcessingResult.lastSuccessfulMessage : messagesAboveCheckpoint[messagesAboveCheckpoint.length - 1];
|
|
1109
|
-
if (checkpointMessage && checkpoints) {
|
|
1110
|
-
const storeCheckpointResult = await checkpoints.store({
|
|
1111
|
-
processorId,
|
|
1112
|
-
version,
|
|
1113
|
-
message: checkpointMessage,
|
|
1114
|
-
lastCheckpoint,
|
|
1115
|
-
partition
|
|
1116
|
-
}, context);
|
|
1117
|
-
if (storeCheckpointResult.success) lastCheckpoint = storeCheckpointResult.newCheckpoint;
|
|
1118
|
-
}
|
|
1119
|
-
if (isStop) {
|
|
1120
|
-
isActive = false;
|
|
1121
|
-
return messageProcessingResult;
|
|
1122
|
-
}
|
|
1123
|
-
}, partialContext);
|
|
1148
|
+
error,
|
|
1149
|
+
reason: "Error during message processing"
|
|
1150
|
+
};
|
|
1151
|
+
}
|
|
1124
1152
|
}
|
|
1125
1153
|
};
|
|
1126
1154
|
};
|
|
@@ -1372,9 +1400,12 @@ const assertNotDeepEqual = (actual, expected, message) => {
|
|
|
1372
1400
|
const assertThat = (item) => {
|
|
1373
1401
|
return { isEqualTo: (other) => assertTrue(deepEquals(item, other)) };
|
|
1374
1402
|
};
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
}
|
|
1403
|
+
function assertDefined(value, message) {
|
|
1404
|
+
if (value === void 0 || value === null) throw new AssertionError((message instanceof Error ? message.message : message) ?? "Value is not defined");
|
|
1405
|
+
}
|
|
1406
|
+
function assertUndefined(value, message) {
|
|
1407
|
+
if (value !== void 0 && value !== null) throw new AssertionError((message instanceof Error ? message.message : message) ?? "Value is defined");
|
|
1408
|
+
}
|
|
1378
1409
|
function assertFalse(condition, message) {
|
|
1379
1410
|
if (condition !== false) throw new AssertionError(message ?? `Condition is true`);
|
|
1380
1411
|
}
|
|
@@ -1853,6 +1884,247 @@ const getInMemoryEventStore = (eventStoreOptions) => {
|
|
|
1853
1884
|
return eventStore;
|
|
1854
1885
|
};
|
|
1855
1886
|
|
|
1887
|
+
//#endregion
|
|
1888
|
+
//#region src/observability/attributes.ts
|
|
1889
|
+
const EmmettAttributes = {
|
|
1890
|
+
scope: { type: "emmett.scope.type" },
|
|
1891
|
+
command: {
|
|
1892
|
+
type: "emmett.command.type",
|
|
1893
|
+
status: "emmett.command.status",
|
|
1894
|
+
eventCount: "emmett.command.event_count",
|
|
1895
|
+
eventTypes: "emmett.command.event_types"
|
|
1896
|
+
},
|
|
1897
|
+
stream: {
|
|
1898
|
+
name: "emmett.stream.name",
|
|
1899
|
+
versionBefore: "emmett.stream.version.before",
|
|
1900
|
+
versionAfter: "emmett.stream.version.after"
|
|
1901
|
+
},
|
|
1902
|
+
eventStore: {
|
|
1903
|
+
operation: "emmett.eventstore.operation",
|
|
1904
|
+
read: {
|
|
1905
|
+
eventCount: "emmett.eventstore.read.event_count",
|
|
1906
|
+
eventTypes: "emmett.eventstore.read.event_types",
|
|
1907
|
+
status: "emmett.eventstore.read.status"
|
|
1908
|
+
},
|
|
1909
|
+
append: {
|
|
1910
|
+
batchSize: "emmett.eventstore.append.batch_size",
|
|
1911
|
+
status: "emmett.eventstore.append.status"
|
|
1912
|
+
}
|
|
1913
|
+
},
|
|
1914
|
+
event: { type: "emmett.event.type" },
|
|
1915
|
+
processor: {
|
|
1916
|
+
id: "emmett.processor.id",
|
|
1917
|
+
type: "emmett.processor.type",
|
|
1918
|
+
status: "emmett.processor.status",
|
|
1919
|
+
batchSize: "emmett.processor.batch_size",
|
|
1920
|
+
eventTypes: "emmett.processor.event_types",
|
|
1921
|
+
checkpointBefore: "emmett.processor.checkpoint.before",
|
|
1922
|
+
checkpointAfter: "emmett.processor.checkpoint.after",
|
|
1923
|
+
lagEvents: "emmett.processor.lag_events"
|
|
1924
|
+
},
|
|
1925
|
+
workflow: {
|
|
1926
|
+
id: "emmett.workflow.id",
|
|
1927
|
+
type: "emmett.workflow.type",
|
|
1928
|
+
inputType: "emmett.workflow.input.type",
|
|
1929
|
+
outputs: "emmett.workflow.outputs",
|
|
1930
|
+
outputsCount: "emmett.workflow.outputs.count",
|
|
1931
|
+
streamPosition: "emmett.workflow.stream_position",
|
|
1932
|
+
stateRebuildEventCount: "emmett.workflow.state_rebuild.event_count"
|
|
1933
|
+
},
|
|
1934
|
+
consumer: {
|
|
1935
|
+
batchSize: "emmett.consumer.batch_size",
|
|
1936
|
+
processorCount: "emmett.consumer.processor_count",
|
|
1937
|
+
delivery: { processorId: "emmett.consumer.delivery.processor_id" }
|
|
1938
|
+
}
|
|
1939
|
+
};
|
|
1940
|
+
const EmmettMetrics = {
|
|
1941
|
+
command: { handlingDuration: "emmett.command.handling.duration" },
|
|
1942
|
+
event: {
|
|
1943
|
+
appendingCount: "emmett.event.appending.count",
|
|
1944
|
+
readingCount: "emmett.event.reading.count"
|
|
1945
|
+
},
|
|
1946
|
+
stream: {
|
|
1947
|
+
readingDuration: "emmett.stream.reading.duration",
|
|
1948
|
+
readingSize: "emmett.stream.reading.size",
|
|
1949
|
+
appendingDuration: "emmett.stream.appending.duration",
|
|
1950
|
+
appendingSize: "emmett.stream.appending.size"
|
|
1951
|
+
},
|
|
1952
|
+
processor: {
|
|
1953
|
+
processingDuration: "emmett.processor.processing.duration",
|
|
1954
|
+
lagEvents: "emmett.processor.lag_events"
|
|
1955
|
+
},
|
|
1956
|
+
workflow: { processingDuration: "emmett.workflow.processing.duration" },
|
|
1957
|
+
consumer: {
|
|
1958
|
+
pollDuration: "emmett.consumer.poll.duration",
|
|
1959
|
+
deliveryDuration: "emmett.consumer.delivery.duration"
|
|
1960
|
+
}
|
|
1961
|
+
};
|
|
1962
|
+
const ScopeTypes = {
|
|
1963
|
+
command: "command",
|
|
1964
|
+
processor: "processor",
|
|
1965
|
+
reactor: "reactor",
|
|
1966
|
+
projector: "projector",
|
|
1967
|
+
workflow: "workflow",
|
|
1968
|
+
consumer: "consumer"
|
|
1969
|
+
};
|
|
1970
|
+
const MessagingSystemName = "emmett";
|
|
1971
|
+
|
|
1972
|
+
//#endregion
|
|
1973
|
+
//#region src/observability/options.ts
|
|
1974
|
+
const resolveCommandObservability = (options, parent) => ({
|
|
1975
|
+
tracer: options?.observability?.tracer ?? parent?.observability?.tracer ?? noopTracer(),
|
|
1976
|
+
meter: options?.observability?.meter ?? parent?.observability?.meter ?? noopMeter(),
|
|
1977
|
+
attributeTarget: options?.observability?.attributeTarget ?? parent?.observability?.attributeTarget ?? "both",
|
|
1978
|
+
includeMessagePayloads: options?.observability?.includeMessagePayloads ?? parent?.observability?.includeMessagePayloads ?? false
|
|
1979
|
+
});
|
|
1980
|
+
|
|
1981
|
+
//#endregion
|
|
1982
|
+
//#region src/observability/tracer.ts
|
|
1983
|
+
const tracer = () => {};
|
|
1984
|
+
const LogLevel = {
|
|
1985
|
+
DISABLED: "DISABLED",
|
|
1986
|
+
INFO: "INFO",
|
|
1987
|
+
LOG: "LOG",
|
|
1988
|
+
WARN: "WARN",
|
|
1989
|
+
ERROR: "ERROR"
|
|
1990
|
+
};
|
|
1991
|
+
const getEnvVariable = (name) => {
|
|
1992
|
+
try {
|
|
1993
|
+
if (typeof process !== "undefined" && process.env) return process.env[name];
|
|
1994
|
+
return;
|
|
1995
|
+
} catch {
|
|
1996
|
+
return;
|
|
1997
|
+
}
|
|
1998
|
+
};
|
|
1999
|
+
const shouldLog = (logLevel) => {
|
|
2000
|
+
const definedLogLevel = getEnvVariable("DUMBO_LOG_LEVEL") ?? LogLevel.ERROR;
|
|
2001
|
+
if (definedLogLevel === LogLevel.ERROR && logLevel === LogLevel.ERROR) return true;
|
|
2002
|
+
if (definedLogLevel === LogLevel.WARN && [LogLevel.ERROR, LogLevel.WARN].includes(logLevel)) return true;
|
|
2003
|
+
if (definedLogLevel === LogLevel.LOG && [
|
|
2004
|
+
LogLevel.ERROR,
|
|
2005
|
+
LogLevel.WARN,
|
|
2006
|
+
LogLevel.LOG
|
|
2007
|
+
].includes(logLevel)) return true;
|
|
2008
|
+
if (definedLogLevel === LogLevel.INFO && [
|
|
2009
|
+
LogLevel.ERROR,
|
|
2010
|
+
LogLevel.WARN,
|
|
2011
|
+
LogLevel.LOG,
|
|
2012
|
+
LogLevel.INFO
|
|
2013
|
+
].includes(logLevel)) return true;
|
|
2014
|
+
return false;
|
|
2015
|
+
};
|
|
2016
|
+
const nulloTraceEventRecorder = () => {};
|
|
2017
|
+
const getTraceEventFormatter = (logStyle, serializer) => (event) => {
|
|
2018
|
+
serializer = serializer ?? JSONSerializer.from();
|
|
2019
|
+
switch (logStyle) {
|
|
2020
|
+
case "RAW": return serializer.serialize(event);
|
|
2021
|
+
case "PRETTY": return serializer.serialize(event);
|
|
2022
|
+
}
|
|
2023
|
+
};
|
|
2024
|
+
const getTraceEventRecorder = (logLevel, logStyle) => {
|
|
2025
|
+
const format = getTraceEventFormatter(logStyle);
|
|
2026
|
+
switch (logLevel) {
|
|
2027
|
+
case "DISABLED": return nulloTraceEventRecorder;
|
|
2028
|
+
case "INFO": return (event) => console.info(format(event));
|
|
2029
|
+
case "LOG": return (event) => console.log(format(event));
|
|
2030
|
+
case "WARN": return (event) => console.warn(format(event));
|
|
2031
|
+
case "ERROR": return (event) => console.error(format(event));
|
|
2032
|
+
}
|
|
2033
|
+
};
|
|
2034
|
+
const recordTraceEvent = (logLevel, eventName, attributes) => {
|
|
2035
|
+
if (!shouldLog(LogLevel.LOG)) return;
|
|
2036
|
+
const event = {
|
|
2037
|
+
name: eventName,
|
|
2038
|
+
timestamp: (/* @__PURE__ */ new Date()).getTime(),
|
|
2039
|
+
...attributes
|
|
2040
|
+
};
|
|
2041
|
+
getTraceEventRecorder(logLevel, getEnvVariable("DUMBO_LOG_STYLE") ?? "RAW")(event);
|
|
2042
|
+
};
|
|
2043
|
+
tracer.info = (eventName, attributes) => recordTraceEvent(LogLevel.INFO, eventName, attributes);
|
|
2044
|
+
tracer.warn = (eventName, attributes) => recordTraceEvent(LogLevel.WARN, eventName, attributes);
|
|
2045
|
+
tracer.log = (eventName, attributes) => recordTraceEvent(LogLevel.LOG, eventName, attributes);
|
|
2046
|
+
tracer.error = (eventName, attributes) => recordTraceEvent(LogLevel.ERROR, eventName, attributes);
|
|
2047
|
+
|
|
2048
|
+
//#endregion
|
|
2049
|
+
//#region src/commandHandling/observability/commandHandlerCollector.ts
|
|
2050
|
+
const commandHandlerCollector = (observability) => {
|
|
2051
|
+
const { startScope } = ObservabilityScope({
|
|
2052
|
+
...observability,
|
|
2053
|
+
attributePrefix: "emmett"
|
|
2054
|
+
});
|
|
2055
|
+
const A = EmmettAttributes;
|
|
2056
|
+
const M = MessagingAttributes;
|
|
2057
|
+
const commandHandlingDuration = observability.meter.histogram(EmmettMetrics.command.handlingDuration);
|
|
2058
|
+
const eventAppendingCount = observability.meter.counter(EmmettMetrics.event.appendingCount);
|
|
2059
|
+
return {
|
|
2060
|
+
startScope: (context, fn) => {
|
|
2061
|
+
const start = Date.now();
|
|
2062
|
+
return startScope("command.handle", async (scope) => {
|
|
2063
|
+
scope.setAttributes({
|
|
2064
|
+
[A.scope.type]: ScopeTypes.command,
|
|
2065
|
+
[M.system]: MessagingSystemName,
|
|
2066
|
+
[M.destination.name]: context.streamName,
|
|
2067
|
+
...context.commandType ? { [A.command.type]: context.commandType } : {},
|
|
2068
|
+
...context.correlationId ? { [M.message.correlationId]: context.correlationId } : {},
|
|
2069
|
+
...context.causationId ? { [M.message.causationId]: context.causationId } : {}
|
|
2070
|
+
});
|
|
2071
|
+
let status = "success";
|
|
2072
|
+
try {
|
|
2073
|
+
const result = await fn(scope);
|
|
2074
|
+
status = "success";
|
|
2075
|
+
scope.setAttributes({
|
|
2076
|
+
[A.command.status]: "success",
|
|
2077
|
+
error: false
|
|
2078
|
+
});
|
|
2079
|
+
return result;
|
|
2080
|
+
} catch (err) {
|
|
2081
|
+
status = "failure";
|
|
2082
|
+
scope.setAttributes({
|
|
2083
|
+
[A.command.status]: "failure",
|
|
2084
|
+
error: true,
|
|
2085
|
+
"exception.message": err instanceof Error ? err.message : String(err),
|
|
2086
|
+
"exception.type": err instanceof Error ? err.constructor.name : "unknown"
|
|
2087
|
+
});
|
|
2088
|
+
scope.recordException(err instanceof Error ? err : new Error(String(err)));
|
|
2089
|
+
throw err;
|
|
2090
|
+
} finally {
|
|
2091
|
+
commandHandlingDuration.record(Date.now() - start, {
|
|
2092
|
+
[A.command.status]: status,
|
|
2093
|
+
...typeof context.commandType === "string" ? { [A.command.type]: context.commandType } : {}
|
|
2094
|
+
});
|
|
2095
|
+
}
|
|
2096
|
+
}, {
|
|
2097
|
+
parent: context.traceId && context.spanId ? {
|
|
2098
|
+
traceId: context.traceId,
|
|
2099
|
+
spanId: context.spanId
|
|
2100
|
+
} : void 0,
|
|
2101
|
+
attributes: {
|
|
2102
|
+
[A.scope.type]: ScopeTypes.command,
|
|
2103
|
+
[A.stream.name]: context.streamName,
|
|
2104
|
+
...context.commandType ? { [A.command.type]: context.commandType } : {},
|
|
2105
|
+
...context.correlationId ? { [M.message.correlationId]: context.correlationId } : {},
|
|
2106
|
+
...context.causationId ? { [M.message.causationId]: context.causationId } : {}
|
|
2107
|
+
}
|
|
2108
|
+
});
|
|
2109
|
+
},
|
|
2110
|
+
recordEvents: (scope, events, status) => {
|
|
2111
|
+
scope.setAttributes({
|
|
2112
|
+
[A.command.eventCount]: events.length,
|
|
2113
|
+
[A.command.eventTypes]: events.map((e) => e.type),
|
|
2114
|
+
[M.batch.messageCount]: events.length,
|
|
2115
|
+
[A.command.status]: status
|
|
2116
|
+
});
|
|
2117
|
+
for (const event of events) eventAppendingCount.add(1, { [A.event.type]: event.type });
|
|
2118
|
+
},
|
|
2119
|
+
recordVersions: (scope, before, after) => {
|
|
2120
|
+
scope.setAttributes({
|
|
2121
|
+
[A.stream.versionBefore]: Number(before),
|
|
2122
|
+
[A.stream.versionAfter]: Number(after)
|
|
2123
|
+
});
|
|
2124
|
+
}
|
|
2125
|
+
};
|
|
2126
|
+
};
|
|
2127
|
+
|
|
1856
2128
|
//#endregion
|
|
1857
2129
|
//#region src/commandHandling/handleCommand.ts
|
|
1858
2130
|
const CommandHandlerStreamVersionConflictRetryOptions = {
|
|
@@ -1861,6 +2133,76 @@ const CommandHandlerStreamVersionConflictRetryOptions = {
|
|
|
1861
2133
|
factor: 1.5,
|
|
1862
2134
|
shouldRetryError: isExpectedVersionConflictError
|
|
1863
2135
|
};
|
|
2136
|
+
const CommandHandler = (options) => async (store, id, handle, handleOptions) => {
|
|
2137
|
+
const collector = commandHandlerCollector(resolveCommandObservability(options));
|
|
2138
|
+
const streamName = (options.mapToStreamId ?? ((id) => id))(id);
|
|
2139
|
+
const commandType = handleOptions?.commandType ?? options.commandType ?? options.name ?? handlerNames(handle);
|
|
2140
|
+
const correlationId = handleOptions?.observability?.correlationId ?? v7();
|
|
2141
|
+
const causationId = handleOptions?.observability?.causationId;
|
|
2142
|
+
return asyncRetry(() => collector.startScope({
|
|
2143
|
+
streamName,
|
|
2144
|
+
commandType,
|
|
2145
|
+
correlationId,
|
|
2146
|
+
causationId,
|
|
2147
|
+
traceId: handleOptions?.observability?.traceId,
|
|
2148
|
+
spanId: handleOptions?.observability?.spanId
|
|
2149
|
+
}, async (scope) => {
|
|
2150
|
+
return await withSession$1(store, async ({ eventStore }) => {
|
|
2151
|
+
const { evolve, initialState } = options;
|
|
2152
|
+
const aggregationResult = await eventStore.aggregateStream(streamName, {
|
|
2153
|
+
evolve,
|
|
2154
|
+
initialState,
|
|
2155
|
+
read: {
|
|
2156
|
+
schema: options.schema,
|
|
2157
|
+
...handleOptions,
|
|
2158
|
+
serialization: options.serialization,
|
|
2159
|
+
expectedStreamVersion: handleOptions?.expectedStreamVersion ?? "NO_CONCURRENCY_CHECK"
|
|
2160
|
+
}
|
|
2161
|
+
});
|
|
2162
|
+
const { currentStreamVersion, streamExists: _streamExists, ...restOfAggregationResult } = aggregationResult;
|
|
2163
|
+
let state = aggregationResult.state;
|
|
2164
|
+
const handlers = Array.isArray(handle) ? handle : [handle];
|
|
2165
|
+
let eventsToAppend = [];
|
|
2166
|
+
for (const handler of handlers) {
|
|
2167
|
+
const result = await handler(state);
|
|
2168
|
+
const newEvents = Array.isArray(result) ? result : [result];
|
|
2169
|
+
if (newEvents.length > 0) state = newEvents.reduce(evolve, state);
|
|
2170
|
+
eventsToAppend = [...eventsToAppend, ...newEvents];
|
|
2171
|
+
}
|
|
2172
|
+
if (eventsToAppend.length === 0) {
|
|
2173
|
+
collector.recordVersions(scope, currentStreamVersion, currentStreamVersion);
|
|
2174
|
+
return {
|
|
2175
|
+
...restOfAggregationResult,
|
|
2176
|
+
newEvents: [],
|
|
2177
|
+
newState: state,
|
|
2178
|
+
nextExpectedStreamVersion: currentStreamVersion,
|
|
2179
|
+
createdNewStream: false
|
|
2180
|
+
};
|
|
2181
|
+
}
|
|
2182
|
+
const expectedStreamVersion = handleOptions?.expectedStreamVersion ?? (aggregationResult.streamExists ? currentStreamVersion : "STREAM_DOES_NOT_EXIST");
|
|
2183
|
+
const { traceId, spanId } = scope.spanContext();
|
|
2184
|
+
const { observability: _appendObservability, ...handleOptionsForAppend } = handleOptions ?? {};
|
|
2185
|
+
const appendResult = await eventStore.appendToStream(streamName, eventsToAppend, {
|
|
2186
|
+
...handleOptionsForAppend,
|
|
2187
|
+
expectedStreamVersion,
|
|
2188
|
+
correlationId,
|
|
2189
|
+
...causationId ? { causationId } : {},
|
|
2190
|
+
traceId,
|
|
2191
|
+
spanId
|
|
2192
|
+
});
|
|
2193
|
+
collector.recordEvents(scope, eventsToAppend, "success");
|
|
2194
|
+
collector.recordVersions(scope, currentStreamVersion, appendResult.nextExpectedStreamVersion);
|
|
2195
|
+
return {
|
|
2196
|
+
...appendResult,
|
|
2197
|
+
newEvents: eventsToAppend,
|
|
2198
|
+
newState: state
|
|
2199
|
+
};
|
|
2200
|
+
});
|
|
2201
|
+
}), fromCommandHandlerRetryOptions(handleOptions && "retry" in handleOptions ? handleOptions.retry : options.retry));
|
|
2202
|
+
};
|
|
2203
|
+
const withSession$1 = (eventStore, callback) => {
|
|
2204
|
+
return (canCreateEventStoreSession(eventStore) ? eventStore : nulloSessionFactory(eventStore)).withSession(callback);
|
|
2205
|
+
};
|
|
1864
2206
|
const fromCommandHandlerRetryOptions = (retryOptions) => {
|
|
1865
2207
|
if (retryOptions === void 0) return NoRetries;
|
|
1866
2208
|
if ("onVersionConflict" in retryOptions) if (typeof retryOptions.onVersionConflict === "boolean") return CommandHandlerStreamVersionConflictRetryOptions;
|
|
@@ -1871,58 +2213,24 @@ const fromCommandHandlerRetryOptions = (retryOptions) => {
|
|
|
1871
2213
|
else return retryOptions.onVersionConflict;
|
|
1872
2214
|
return retryOptions;
|
|
1873
2215
|
};
|
|
1874
|
-
const
|
|
1875
|
-
|
|
1876
|
-
const
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
initialState,
|
|
1881
|
-
read: {
|
|
1882
|
-
schema: options.schema,
|
|
1883
|
-
...handleOptions,
|
|
1884
|
-
serialization: options.serialization,
|
|
1885
|
-
expectedStreamVersion: handleOptions?.expectedStreamVersion ?? "NO_CONCURRENCY_CHECK"
|
|
1886
|
-
}
|
|
1887
|
-
});
|
|
1888
|
-
const { currentStreamVersion, streamExists: _streamExists, ...restOfAggregationResult } = aggregationResult;
|
|
1889
|
-
let state = aggregationResult.state;
|
|
1890
|
-
const handlers = Array.isArray(handle) ? handle : [handle];
|
|
1891
|
-
let eventsToAppend = [];
|
|
1892
|
-
for (const handler of handlers) {
|
|
1893
|
-
const result = await handler(state);
|
|
1894
|
-
const newEvents = Array.isArray(result) ? result : [result];
|
|
1895
|
-
if (newEvents.length > 0) state = newEvents.reduce(evolve, state);
|
|
1896
|
-
eventsToAppend = [...eventsToAppend, ...newEvents];
|
|
1897
|
-
}
|
|
1898
|
-
if (eventsToAppend.length === 0) return {
|
|
1899
|
-
...restOfAggregationResult,
|
|
1900
|
-
newEvents: [],
|
|
1901
|
-
newState: state,
|
|
1902
|
-
nextExpectedStreamVersion: currentStreamVersion,
|
|
1903
|
-
createdNewStream: false
|
|
1904
|
-
};
|
|
1905
|
-
const expectedStreamVersion = handleOptions?.expectedStreamVersion ?? (aggregationResult.streamExists ? currentStreamVersion : "STREAM_DOES_NOT_EXIST");
|
|
1906
|
-
return {
|
|
1907
|
-
...await eventStore.appendToStream(streamName, eventsToAppend, {
|
|
1908
|
-
...handleOptions,
|
|
1909
|
-
expectedStreamVersion
|
|
1910
|
-
}),
|
|
1911
|
-
newEvents: eventsToAppend,
|
|
1912
|
-
newState: state
|
|
1913
|
-
};
|
|
1914
|
-
});
|
|
1915
|
-
}, fromCommandHandlerRetryOptions(handleOptions && "retry" in handleOptions ? handleOptions.retry : options.retry));
|
|
1916
|
-
const withSession$1 = (eventStore, callback) => {
|
|
1917
|
-
return (canCreateEventStoreSession(eventStore) ? eventStore : nulloSessionFactory(eventStore)).withSession(callback);
|
|
2216
|
+
const handlerNames = (handle) => {
|
|
2217
|
+
if (Array.isArray(handle)) {
|
|
2218
|
+
const names = handle.map((h) => h.name).filter((n) => !!n);
|
|
2219
|
+
return names.length > 0 ? names : void 0;
|
|
2220
|
+
}
|
|
2221
|
+
return handle.name || void 0;
|
|
1918
2222
|
};
|
|
1919
2223
|
|
|
1920
2224
|
//#endregion
|
|
1921
2225
|
//#region src/commandHandling/handleCommandWithDecider.ts
|
|
2226
|
+
const commandTypesOf = (commands) => Array.isArray(commands) ? commands.map((c) => c.type) : commands.type;
|
|
1922
2227
|
const DeciderCommandHandler = (options) => async (eventStore, id, commands, handleOptions) => {
|
|
1923
2228
|
const { decide, ...rest } = options;
|
|
1924
2229
|
const deciders = (Array.isArray(commands) ? commands : [commands]).map((command) => (state) => decide(command, state));
|
|
1925
|
-
return CommandHandler(rest)(eventStore, id, deciders,
|
|
2230
|
+
return CommandHandler(rest)(eventStore, id, deciders, {
|
|
2231
|
+
commandType: commandTypesOf(commands),
|
|
2232
|
+
...handleOptions
|
|
2233
|
+
});
|
|
1926
2234
|
};
|
|
1927
2235
|
|
|
1928
2236
|
//#endregion
|
|
@@ -2201,5 +2509,5 @@ const workflowProcessor = (options) => {
|
|
|
2201
2509
|
};
|
|
2202
2510
|
|
|
2203
2511
|
//#endregion
|
|
2204
|
-
export { AssertionError, CommandHandler, CommandHandlerStreamVersionConflictRetryOptions, ConcurrencyError, ConcurrencyInMemoryDatabaseError, DATABASE_REQUIRED_ERROR_MESSAGE, DeciderCommandHandler, DeciderSpecification, EmmettError, ExpectedVersionConflictError, GlobalStreamCaughtUpType, IllegalStateError, InMemoryEventStoreDefaultStreamVersion, InMemoryProjectionSpec, InProcessLock, JSONCodec, JSONReplacer, JSONReplacers, JSONReviver, JSONRevivers, JSONSerializer, MessageProcessor, MessageProcessorType, NO_CONCURRENCY_CHECK, NoRetries, NotFoundError, STREAM_DOES_NOT_EXIST, STREAM_EXISTS, 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, assertUnsignedBigInt, asyncAwaiter, asyncProjections, asyncRetry, bigInt, bigIntProcessorCheckpoint, canCreateEventStoreSession, caughtUpEventFrom, command, composeJSONReplacers, composeJSONRevivers, deepEquals, defaultProcessingMessageProcessingScope, defaultProcessorPartition, defaultProcessorVersion, defaultTag, delay, documentExists, downcastRecordedMessage, downcastRecordedMessages, emmettPrefix, event, eventInStream, 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, message, newEventsInStream, nulloSessionFactory, onShutdown, parseBigIntProcessorCheckpoint, parseDateFromUtcYYYYMMDD, projection, projections, projector, reactor, reduceAsync, sum, toNormalizedString, tryPublishMessagesAfterCommit, unknownTag, upcastRecordedMessage, upcastRecordedMessages, verifyThat, wasMessageHandled, workflowOutputHandler, workflowProcessor, workflowStreamName };
|
|
2512
|
+
export { AssertionError, CommandHandler, CommandHandlerStreamVersionConflictRetryOptions, ConcurrencyError, ConcurrencyInMemoryDatabaseError, DATABASE_REQUIRED_ERROR_MESSAGE, DeciderCommandHandler, DeciderSpecification, EmmettError, ExpectedVersionConflictError, GlobalStreamCaughtUpType, IllegalStateError, InMemoryEventStoreDefaultStreamVersion, InMemoryProjectionSpec, InProcessLock, JSONCodec, JSONReplacer, JSONReplacers, JSONReviver, JSONRevivers, JSONSerializer, MessageProcessor, MessageProcessorType, NO_CONCURRENCY_CHECK, NoRetries, NotFoundError, STREAM_DOES_NOT_EXIST, STREAM_EXISTS, 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, deepEquals, defaultProcessingMessageProcessingScope, defaultProcessorPartition, defaultProcessorVersion, defaultTag, delay, documentExists, downcastRecordedMessage, downcastRecordedMessages, emmettPrefix, event, eventInStream, 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, message, newEventsInStream, nulloSessionFactory, onShutdown, parseBigIntProcessorCheckpoint, parseDateFromUtcYYYYMMDD, projection, projections, projector, reactor, reduceAsync, sum, toNormalizedString, tryPublishMessagesAfterCommit, unknownTag, upcastRecordedMessage, upcastRecordedMessages, verifyThat, wasMessageHandled, workflowOutputHandler, workflowProcessor, workflowStreamName };
|
|
2205
2513
|
//# sourceMappingURL=index.js.map
|