@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/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) return;
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) return { lastCheckpoint };
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) await hooks.onStart(context);
1078
- if (startFrom && startFrom !== "CURRENT") return startFrom;
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) return "BEGINNING";
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
- return await processingScope(async (context) => {
1097
- const messagesAboveCheckpoint = messages.filter((message) => !wasMessageHandled(message, lastCheckpoint));
1098
- const upcastedMessages = messagesAboveCheckpoint.map((message) => upcastRecordedMessage(message, options.messageOptions?.schema?.versioning)).filter((upcasted) => !canHandle || canHandle.includes(upcasted.type));
1099
- const stopMessageIndex = isCustomBatch && stopAfter ? upcastedMessages.findIndex(stopAfter) : -1;
1100
- const unhandledMessages = stopMessageIndex !== -1 ? upcastedMessages.slice(0, stopMessageIndex + 1) : upcastedMessages;
1101
- const batchResult = await eachBatch(unhandledMessages, context);
1102
- const messageProcessingResult = batchResult?.type === "STOP" ? batchResult : stopMessageIndex !== -1 ? {
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
- reason: "Stop condition reached",
1105
- lastSuccessfulMessage: unhandledMessages[stopMessageIndex]
1106
- } : batchResult;
1107
- const isStop = messageProcessingResult && messageProcessingResult.type === "STOP";
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
- const assertDefined = (value, message) => {
1376
- assertOk(value, message instanceof Error ? message.message : message);
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 CommandHandler = (options) => async (store, id, handle, handleOptions) => asyncRetry(async () => {
1875
- return await withSession$1(store, async ({ eventStore }) => {
1876
- const { evolve, initialState } = options;
1877
- const streamName = (options.mapToStreamId ?? ((id) => id))(id);
1878
- const aggregationResult = await eventStore.aggregateStream(streamName, {
1879
- evolve,
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, handleOptions);
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