@kronos-ts/messaging 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/command-bus.d.ts +30 -0
- package/dist/command-bus.d.ts.map +1 -0
- package/dist/command-bus.js +2 -0
- package/dist/command-bus.js.map +1 -0
- package/dist/command-handler.d.ts +58 -0
- package/dist/command-handler.d.ts.map +1 -0
- package/dist/command-handler.js +12 -0
- package/dist/command-handler.js.map +1 -0
- package/dist/command-handling-module.d.ts +53 -0
- package/dist/command-handling-module.d.ts.map +1 -0
- package/dist/command-handling-module.js +130 -0
- package/dist/command-handling-module.js.map +1 -0
- package/dist/correlation-data.d.ts +79 -0
- package/dist/correlation-data.d.ts.map +1 -0
- package/dist/correlation-data.js +133 -0
- package/dist/correlation-data.js.map +1 -0
- package/dist/dead-letter-queue.d.ts +134 -0
- package/dist/dead-letter-queue.d.ts.map +1 -0
- package/dist/dead-letter-queue.js +176 -0
- package/dist/dead-letter-queue.js.map +1 -0
- package/dist/dead-lettering-handler.d.ts +42 -0
- package/dist/dead-lettering-handler.d.ts.map +1 -0
- package/dist/dead-lettering-handler.js +67 -0
- package/dist/dead-lettering-handler.js.map +1 -0
- package/dist/descriptor.d.ts +135 -0
- package/dist/descriptor.d.ts.map +1 -0
- package/dist/descriptor.js +36 -0
- package/dist/descriptor.js.map +1 -0
- package/dist/emit-update.d.ts +22 -0
- package/dist/emit-update.d.ts.map +1 -0
- package/dist/emit-update.js +23 -0
- package/dist/emit-update.js.map +1 -0
- package/dist/event-bus.d.ts +29 -0
- package/dist/event-bus.d.ts.map +1 -0
- package/dist/event-bus.js +22 -0
- package/dist/event-bus.js.map +1 -0
- package/dist/event-criteria.d.ts +87 -0
- package/dist/event-criteria.d.ts.map +1 -0
- package/dist/event-criteria.js +90 -0
- package/dist/event-criteria.js.map +1 -0
- package/dist/event-gateway.d.ts +19 -0
- package/dist/event-gateway.d.ts.map +1 -0
- package/dist/event-gateway.js +22 -0
- package/dist/event-gateway.js.map +1 -0
- package/dist/event-handler.d.ts +30 -0
- package/dist/event-handler.d.ts.map +1 -0
- package/dist/event-handler.js +18 -0
- package/dist/event-handler.js.map +1 -0
- package/dist/event-processor-builder.d.ts +148 -0
- package/dist/event-processor-builder.d.ts.map +1 -0
- package/dist/event-processor-builder.js +175 -0
- package/dist/event-processor-builder.js.map +1 -0
- package/dist/event-processor.d.ts +10 -0
- package/dist/event-processor.d.ts.map +1 -0
- package/dist/event-processor.js +2 -0
- package/dist/event-processor.js.map +1 -0
- package/dist/event-sink.d.ts +23 -0
- package/dist/event-sink.d.ts.map +1 -0
- package/dist/event-sink.js +2 -0
- package/dist/event-sink.js.map +1 -0
- package/dist/event-source.d.ts +98 -0
- package/dist/event-source.d.ts.map +1 -0
- package/dist/event-source.js +191 -0
- package/dist/event-source.js.map +1 -0
- package/dist/gateway.d.ts +68 -0
- package/dist/gateway.d.ts.map +1 -0
- package/dist/gateway.js +62 -0
- package/dist/gateway.js.map +1 -0
- package/dist/handler-enhancer.d.ts +53 -0
- package/dist/handler-enhancer.d.ts.map +1 -0
- package/dist/handler-enhancer.js +17 -0
- package/dist/handler-enhancer.js.map +1 -0
- package/dist/handler.d.ts +51 -0
- package/dist/handler.d.ts.map +1 -0
- package/dist/handler.js +26 -0
- package/dist/handler.js.map +1 -0
- package/dist/index.d.ts +53 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +103 -0
- package/dist/index.js.map +1 -0
- package/dist/intercepting-command-bus.d.ts +17 -0
- package/dist/intercepting-command-bus.d.ts.map +1 -0
- package/dist/intercepting-command-bus.js +54 -0
- package/dist/intercepting-command-bus.js.map +1 -0
- package/dist/intercepting-event-bus.d.ts +8 -0
- package/dist/intercepting-event-bus.d.ts.map +1 -0
- package/dist/intercepting-event-bus.js +22 -0
- package/dist/intercepting-event-bus.js.map +1 -0
- package/dist/intercepting-query-bus.d.ts +17 -0
- package/dist/intercepting-query-bus.d.ts.map +1 -0
- package/dist/intercepting-query-bus.js +68 -0
- package/dist/intercepting-query-bus.js.map +1 -0
- package/dist/interceptor.d.ts +46 -0
- package/dist/interceptor.d.ts.map +1 -0
- package/dist/interceptor.js +2 -0
- package/dist/interceptor.js.map +1 -0
- package/dist/message-monitor-registry.d.ts +28 -0
- package/dist/message-monitor-registry.d.ts.map +1 -0
- package/dist/message-monitor-registry.js +37 -0
- package/dist/message-monitor-registry.js.map +1 -0
- package/dist/message-monitor.d.ts +36 -0
- package/dist/message-monitor.d.ts.map +1 -0
- package/dist/message-monitor.js +39 -0
- package/dist/message-monitor.js.map +1 -0
- package/dist/message.d.ts +42 -0
- package/dist/message.d.ts.map +1 -0
- package/dist/message.js +2 -0
- package/dist/message.js.map +1 -0
- package/dist/processing-state.d.ts +115 -0
- package/dist/processing-state.d.ts.map +1 -0
- package/dist/processing-state.js +205 -0
- package/dist/processing-state.js.map +1 -0
- package/dist/processor-configuration.d.ts +51 -0
- package/dist/processor-configuration.d.ts.map +1 -0
- package/dist/processor-configuration.js +2 -0
- package/dist/processor-configuration.js.map +1 -0
- package/dist/query-bus.d.ts +51 -0
- package/dist/query-bus.d.ts.map +1 -0
- package/dist/query-bus.js +2 -0
- package/dist/query-bus.js.map +1 -0
- package/dist/query-handler.d.ts +35 -0
- package/dist/query-handler.d.ts.map +1 -0
- package/dist/query-handler.js +19 -0
- package/dist/query-handler.js.map +1 -0
- package/dist/query-handling-module.d.ts +24 -0
- package/dist/query-handling-module.d.ts.map +1 -0
- package/dist/query-handling-module.js +32 -0
- package/dist/query-handling-module.js.map +1 -0
- package/dist/replay-token.d.ts +31 -0
- package/dist/replay-token.d.ts.map +1 -0
- package/dist/replay-token.js +37 -0
- package/dist/replay-token.js.map +1 -0
- package/dist/retrying-command-bus.d.ts +32 -0
- package/dist/retrying-command-bus.d.ts.map +1 -0
- package/dist/retrying-command-bus.js +58 -0
- package/dist/retrying-command-bus.js.map +1 -0
- package/dist/routing-strategy.d.ts +30 -0
- package/dist/routing-strategy.d.ts.map +1 -0
- package/dist/routing-strategy.js +37 -0
- package/dist/routing-strategy.js.map +1 -0
- package/dist/segment.d.ts +72 -0
- package/dist/segment.d.ts.map +1 -0
- package/dist/segment.js +103 -0
- package/dist/segment.js.map +1 -0
- package/dist/send.d.ts +28 -0
- package/dist/send.d.ts.map +1 -0
- package/dist/send.js +36 -0
- package/dist/send.js.map +1 -0
- package/dist/serializer.d.ts +40 -0
- package/dist/serializer.d.ts.map +1 -0
- package/dist/serializer.js +90 -0
- package/dist/serializer.js.map +1 -0
- package/dist/simple-command-bus.d.ts +23 -0
- package/dist/simple-command-bus.d.ts.map +1 -0
- package/dist/simple-command-bus.js +49 -0
- package/dist/simple-command-bus.js.map +1 -0
- package/dist/simple-query-bus.d.ts +16 -0
- package/dist/simple-query-bus.d.ts.map +1 -0
- package/dist/simple-query-bus.js +122 -0
- package/dist/simple-query-bus.js.map +1 -0
- package/dist/span-factory.d.ts +58 -0
- package/dist/span-factory.d.ts.map +1 -0
- package/dist/span-factory.js +19 -0
- package/dist/span-factory.js.map +1 -0
- package/dist/streaming-event-processor.d.ts +65 -0
- package/dist/streaming-event-processor.d.ts.map +1 -0
- package/dist/streaming-event-processor.js +239 -0
- package/dist/streaming-event-processor.js.map +1 -0
- package/dist/subscribing-event-processor.d.ts +57 -0
- package/dist/subscribing-event-processor.d.ts.map +1 -0
- package/dist/subscribing-event-processor.js +100 -0
- package/dist/subscribing-event-processor.js.map +1 -0
- package/dist/subscription-query.d.ts +63 -0
- package/dist/subscription-query.d.ts.map +1 -0
- package/dist/subscription-query.js +119 -0
- package/dist/subscription-query.js.map +1 -0
- package/dist/token-store.d.ts +83 -0
- package/dist/token-store.d.ts.map +1 -0
- package/dist/token-store.js +112 -0
- package/dist/token-store.js.map +1 -0
- package/dist/tracing-command-bus.d.ts +16 -0
- package/dist/tracing-command-bus.d.ts.map +1 -0
- package/dist/tracing-command-bus.js +44 -0
- package/dist/tracing-command-bus.js.map +1 -0
- package/dist/tracing-handler-enhancer.d.ts +11 -0
- package/dist/tracing-handler-enhancer.d.ts.map +1 -0
- package/dist/tracing-handler-enhancer.js +27 -0
- package/dist/tracing-handler-enhancer.js.map +1 -0
- package/dist/tracking-event-processor.d.ts +72 -0
- package/dist/tracking-event-processor.d.ts.map +1 -0
- package/dist/tracking-event-processor.js +223 -0
- package/dist/tracking-event-processor.js.map +1 -0
- package/dist/tracking-token.d.ts +120 -0
- package/dist/tracking-token.d.ts.map +1 -0
- package/dist/tracking-token.js +132 -0
- package/dist/tracking-token.js.map +1 -0
- package/dist/transaction.d.ts +60 -0
- package/dist/transaction.d.ts.map +1 -0
- package/dist/transaction.js +74 -0
- package/dist/transaction.js.map +1 -0
- package/dist/unit-of-work.d.ts +41 -0
- package/dist/unit-of-work.d.ts.map +1 -0
- package/dist/unit-of-work.js +96 -0
- package/dist/unit-of-work.js.map +1 -0
- package/dist/upcaster.d.ts +91 -0
- package/dist/upcaster.d.ts.map +1 -0
- package/dist/upcaster.js +114 -0
- package/dist/upcaster.js.map +1 -0
- package/dist/with-namespace.d.ts +59 -0
- package/dist/with-namespace.d.ts.map +1 -0
- package/dist/with-namespace.js +42 -0
- package/dist/with-namespace.js.map +1 -0
- package/package.json +65 -0
- package/src/command-bus.ts +34 -0
- package/src/command-handler.ts +116 -0
- package/src/command-handling-module.ts +183 -0
- package/src/correlation-data.ts +169 -0
- package/src/dead-letter-queue.ts +330 -0
- package/src/dead-lettering-handler.ts +109 -0
- package/src/descriptor.ts +176 -0
- package/src/emit-update.ts +35 -0
- package/src/event-bus.ts +45 -0
- package/src/event-criteria.ts +141 -0
- package/src/event-gateway.ts +42 -0
- package/src/event-handler.ts +44 -0
- package/src/event-processor-builder.ts +246 -0
- package/src/event-processor.ts +9 -0
- package/src/event-sink.ts +23 -0
- package/src/event-source.ts +301 -0
- package/src/gateway.ts +144 -0
- package/src/handler-enhancer.ts +70 -0
- package/src/handler.ts +133 -0
- package/src/index.ts +356 -0
- package/src/intercepting-command-bus.ts +73 -0
- package/src/intercepting-event-bus.ts +29 -0
- package/src/intercepting-query-bus.ts +104 -0
- package/src/interceptor.ts +48 -0
- package/src/message-monitor-registry.ts +64 -0
- package/src/message-monitor.ts +68 -0
- package/src/message.ts +41 -0
- package/src/processing-state.ts +258 -0
- package/src/processor-configuration.ts +59 -0
- package/src/query-bus.ts +69 -0
- package/src/query-handler.ts +49 -0
- package/src/query-handling-module.ts +44 -0
- package/src/replay-token.ts +53 -0
- package/src/retrying-command-bus.ts +80 -0
- package/src/routing-strategy.ts +59 -0
- package/src/segment.ts +136 -0
- package/src/send.ts +44 -0
- package/src/serializer.ts +122 -0
- package/src/simple-command-bus.ts +59 -0
- package/src/simple-query-bus.ts +158 -0
- package/src/span-factory.ts +81 -0
- package/src/streaming-event-processor.ts +351 -0
- package/src/subscribing-event-processor.ts +169 -0
- package/src/subscription-query.ts +173 -0
- package/src/token-store.ts +211 -0
- package/src/tracing-command-bus.ts +52 -0
- package/src/tracing-handler-enhancer.ts +34 -0
- package/src/tracking-event-processor.ts +336 -0
- package/src/tracking-token.ts +231 -0
- package/src/transaction.ts +98 -0
- package/src/unit-of-work.ts +138 -0
- package/src/upcaster.ts +174 -0
- package/src/with-namespace.ts +75 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { EventHandlerDefinition } from "./event-handler.js";
|
|
2
|
+
import type { StreamableEventSource } from "./event-source.js";
|
|
3
|
+
import type { UoWRunner } from "./unit-of-work.js";
|
|
4
|
+
import type { TokenStore } from "./token-store.js";
|
|
5
|
+
import type { HandlerEnhancerDefinition } from "./handler-enhancer.js";
|
|
6
|
+
import type { CommandBus } from "./command-bus.js";
|
|
7
|
+
import type { QueryBus } from "./query-bus.js";
|
|
8
|
+
/**
|
|
9
|
+
* A tracking event processor that reads events from a streamable event source
|
|
10
|
+
* and delivers them to registered event handlers.
|
|
11
|
+
*
|
|
12
|
+
* Uses {@link StreamableEventSource.open} to get a persistent {@link MessageStream}.
|
|
13
|
+
* Each batch of events is processed within a UnitOfWork, enabling
|
|
14
|
+
* transactional event processing and coordinated token updates.
|
|
15
|
+
*
|
|
16
|
+
* Supports replay via {@link resetTokens} — the processor can be stopped,
|
|
17
|
+
* reset to a starting position, and restarted.
|
|
18
|
+
*/
|
|
19
|
+
export interface TrackingEventProcessor {
|
|
20
|
+
readonly name: string;
|
|
21
|
+
readonly running: boolean;
|
|
22
|
+
/** Current effective position in the event stream. */
|
|
23
|
+
readonly position: bigint;
|
|
24
|
+
/** Whether the processor is currently replaying events. */
|
|
25
|
+
readonly replaying: boolean;
|
|
26
|
+
start(): Promise<void>;
|
|
27
|
+
stop(): void;
|
|
28
|
+
/**
|
|
29
|
+
* Reset the processor to replay events from a starting position.
|
|
30
|
+
* The processor must be stopped before calling this.
|
|
31
|
+
*/
|
|
32
|
+
resetTokens(startPosition?: bigint, resetContext?: unknown): Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
export interface TrackingEventProcessorOptions {
|
|
35
|
+
name: string;
|
|
36
|
+
eventSource: StreamableEventSource;
|
|
37
|
+
eventHandlers: ReadonlyArray<EventHandlerDefinition>;
|
|
38
|
+
/** State manager injected into ALS at handler-invocation entry (D-44). */
|
|
39
|
+
stateManager?: unknown;
|
|
40
|
+
/** Command bus injected into ALS at handler-invocation entry (D-44). */
|
|
41
|
+
commandBus?: CommandBus;
|
|
42
|
+
/** Query bus injected into ALS at handler-invocation entry (D-44). */
|
|
43
|
+
queryBus?: QueryBus;
|
|
44
|
+
/** Optional per-event callback fired inside the UoW before handler invocation (e.g. monitoring). */
|
|
45
|
+
onEventDelivery?: () => void;
|
|
46
|
+
unitOfWorkRunner?: UoWRunner;
|
|
47
|
+
tokenStore?: TokenStore;
|
|
48
|
+
/** Polling interval when no events are available (ms). Default: 500. */
|
|
49
|
+
pollingIntervalMs?: number;
|
|
50
|
+
batchSize?: number;
|
|
51
|
+
errorHandler?: EventProcessingErrorHandler;
|
|
52
|
+
/** Optional handler enhancer applied to all event handlers at setup time. */
|
|
53
|
+
handlerEnhancer?: HandlerEnhancerDefinition;
|
|
54
|
+
/** Reset callback invoked from resetTokens(). */
|
|
55
|
+
onReset?: () => Promise<void> | void;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Determines what happens when an event handler fails.
|
|
59
|
+
*/
|
|
60
|
+
export interface EventProcessingErrorHandler {
|
|
61
|
+
handleError(error: unknown, eventName: string, position: bigint): void | Promise<void>;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Logs errors and continues processing. Default behavior.
|
|
65
|
+
*/
|
|
66
|
+
export declare function loggingErrorHandler(processorName: string): EventProcessingErrorHandler;
|
|
67
|
+
/**
|
|
68
|
+
* Rethrows errors, aborting the current batch and triggering rollback.
|
|
69
|
+
*/
|
|
70
|
+
export declare function propagatingErrorHandler(): EventProcessingErrorHandler;
|
|
71
|
+
export declare function createTrackingEventProcessor(options: TrackingEventProcessorOptions): TrackingEventProcessor;
|
|
72
|
+
//# sourceMappingURL=tracking-event-processor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracking-event-processor.d.ts","sourceRoot":"","sources":["../src/tracking-event-processor.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAA;AAChE,OAAO,KAAK,EAAE,qBAAqB,EAAiC,MAAM,mBAAmB,CAAA;AAC7F,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAElD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAWlD,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAA;AACtE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAK9C;;;;;;;;;;GAUG;AACH,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,sDAAsD;IACtD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,2DAA2D;IAC3D,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;IAC3B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACtB,IAAI,IAAI,IAAI,CAAA;IACZ;;;OAGG;IACH,WAAW,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC3E;AAED,MAAM,WAAW,6BAA6B;IAC5C,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,qBAAqB,CAAA;IAClC,aAAa,EAAE,aAAa,CAAC,sBAAsB,CAAC,CAAA;IACpD,0EAA0E;IAC1E,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,wEAAwE;IACxE,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,sEAAsE;IACtE,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,oGAAoG;IACpG,eAAe,CAAC,EAAE,MAAM,IAAI,CAAA;IAC5B,gBAAgB,CAAC,EAAE,SAAS,CAAA;IAC5B,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,wEAAwE;IACxE,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,YAAY,CAAC,EAAE,2BAA2B,CAAA;IAC1C,6EAA6E;IAC7E,eAAe,CAAC,EAAE,yBAAyB,CAAA;IAC3C,iDAAiD;IACjD,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;CACrC;AAED;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACvF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,aAAa,EAAE,MAAM,GAAG,2BAA2B,CAStF;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,2BAA2B,CAMrE;AAED,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,6BAA6B,GACrC,sBAAsB,CAkOxB"}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { emptyMetadata, qualifiedNameToString } from "@kronos-ts/common";
|
|
2
|
+
import { runInNewUoW } from "./unit-of-work.js";
|
|
3
|
+
import { globalSequenceToken, replayToken, isReplayToken, isReplaying, advanceToken, } from "./tracking-token.js";
|
|
4
|
+
import { REPLAY_STATE_KEY } from "./replay-token.js";
|
|
5
|
+
import { setResource, onPrepareCommit } from "./processing-state.js";
|
|
6
|
+
import { STATE_MANAGER_KEY } from "@kronos-ts/eventsourcing";
|
|
7
|
+
import { COMMAND_BUS_KEY } from "./send.js";
|
|
8
|
+
import { QUERY_BUS_KEY } from "./emit-update.js";
|
|
9
|
+
/**
|
|
10
|
+
* Logs errors and continues processing. Default behavior.
|
|
11
|
+
*/
|
|
12
|
+
export function loggingErrorHandler(processorName) {
|
|
13
|
+
return {
|
|
14
|
+
handleError(error, eventName, position) {
|
|
15
|
+
console.error(`Event processor "${processorName}": handler failed for "${eventName}" at position ${position}:`, error);
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Rethrows errors, aborting the current batch and triggering rollback.
|
|
21
|
+
*/
|
|
22
|
+
export function propagatingErrorHandler() {
|
|
23
|
+
return {
|
|
24
|
+
handleError(error) {
|
|
25
|
+
throw error;
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export function createTrackingEventProcessor(options) {
|
|
30
|
+
const { name, eventSource, eventHandlers, stateManager, commandBus, queryBus, onEventDelivery, unitOfWorkRunner = runInNewUoW, tokenStore, pollingIntervalMs = 500, batchSize = 100, errorHandler = loggingErrorHandler(name), handlerEnhancer, onReset, } = options;
|
|
31
|
+
const segment = 0;
|
|
32
|
+
const handlerMap = new Map();
|
|
33
|
+
for (const reg of eventHandlers) {
|
|
34
|
+
const eventName = qualifiedNameToString(reg.descriptor.name);
|
|
35
|
+
if (!handlerMap.has(eventName)) {
|
|
36
|
+
handlerMap.set(eventName, []);
|
|
37
|
+
}
|
|
38
|
+
const enhanced = handlerEnhancer
|
|
39
|
+
? {
|
|
40
|
+
...reg,
|
|
41
|
+
handler: handlerEnhancer.wrapHandler(reg.handler, {
|
|
42
|
+
messageType: "event",
|
|
43
|
+
messageName: eventName,
|
|
44
|
+
handlerGroup: name,
|
|
45
|
+
}),
|
|
46
|
+
}
|
|
47
|
+
: reg;
|
|
48
|
+
handlerMap.get(eventName).push(enhanced);
|
|
49
|
+
}
|
|
50
|
+
let token = globalSequenceToken(0n);
|
|
51
|
+
let isRunning = false;
|
|
52
|
+
let stream = null;
|
|
53
|
+
let pollTimer = null;
|
|
54
|
+
let processing = false;
|
|
55
|
+
async function initialize() {
|
|
56
|
+
if (tokenStore) {
|
|
57
|
+
await tokenStore.initializeSegments(name, 1);
|
|
58
|
+
const stored = await tokenStore.get(name, segment);
|
|
59
|
+
if (stored !== undefined) {
|
|
60
|
+
token = stored;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function openStream() {
|
|
65
|
+
stream = eventSource.open({ position: token.position() });
|
|
66
|
+
stream.setCallback(() => {
|
|
67
|
+
if (isRunning && !processing) {
|
|
68
|
+
scheduleImmediate();
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
async function poll() {
|
|
73
|
+
if (!isRunning || processing)
|
|
74
|
+
return;
|
|
75
|
+
processing = true;
|
|
76
|
+
try {
|
|
77
|
+
if (!stream) {
|
|
78
|
+
openStream();
|
|
79
|
+
}
|
|
80
|
+
// Check for stream errors — reopen if needed
|
|
81
|
+
if (stream.error()) {
|
|
82
|
+
console.error(`Event processor "${name}": stream error, reopening:`, stream.error());
|
|
83
|
+
stream.close();
|
|
84
|
+
stream = null;
|
|
85
|
+
openStream();
|
|
86
|
+
processing = false;
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const batch = [];
|
|
90
|
+
let event = stream.next();
|
|
91
|
+
while (event && batch.length < batchSize) {
|
|
92
|
+
batch.push(event);
|
|
93
|
+
if (batch.length < batchSize && stream.hasNextAvailable()) {
|
|
94
|
+
event = stream.next();
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (batch.length > 0) {
|
|
101
|
+
await processBatch(batch);
|
|
102
|
+
if (isRunning) {
|
|
103
|
+
if (stream.hasNextAvailable()) {
|
|
104
|
+
scheduleImmediate();
|
|
105
|
+
}
|
|
106
|
+
// else: stream callback will wake us when events arrive
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
// If replay is done and no more events, unwrap
|
|
111
|
+
if (isReplayToken(token)) {
|
|
112
|
+
token = globalSequenceToken(token.position());
|
|
113
|
+
if (tokenStore) {
|
|
114
|
+
await tokenStore.store(name, segment, token);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
// No events available — wait for callback or poll again after interval
|
|
118
|
+
if (isRunning) {
|
|
119
|
+
pollTimer = setTimeout(poll, pollingIntervalMs);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
catch (err) {
|
|
124
|
+
console.error(`Event processor "${name}" error during poll:`, err);
|
|
125
|
+
if (isRunning)
|
|
126
|
+
pollTimer = setTimeout(poll, pollingIntervalMs * 2);
|
|
127
|
+
}
|
|
128
|
+
finally {
|
|
129
|
+
processing = false;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
async function processBatch(batch) {
|
|
133
|
+
let batchEndToken = token;
|
|
134
|
+
await unitOfWorkRunner(emptyMetadata(), async () => {
|
|
135
|
+
for (const sequencedEvent of batch) {
|
|
136
|
+
setResource(REPLAY_STATE_KEY, { replaying: isReplaying(batchEndToken) });
|
|
137
|
+
await deliverEvent(sequencedEvent);
|
|
138
|
+
batchEndToken = advanceToken(batchEndToken, sequencedEvent.sequence + 1n);
|
|
139
|
+
}
|
|
140
|
+
if (tokenStore) {
|
|
141
|
+
onPrepareCommit(async () => {
|
|
142
|
+
await tokenStore.store(name, segment, batchEndToken);
|
|
143
|
+
await tokenStore.extendClaim(name, segment, name);
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
token = batchEndToken;
|
|
148
|
+
}
|
|
149
|
+
async function deliverEvent(sequencedEvent) {
|
|
150
|
+
const event = sequencedEvent.event;
|
|
151
|
+
const eventName = qualifiedNameToString(event.name);
|
|
152
|
+
const handlers = handlerMap.get(eventName);
|
|
153
|
+
if (!handlers || handlers.length === 0)
|
|
154
|
+
return;
|
|
155
|
+
// D-44 wiring: write framework components into ALS at per-event invocation entry.
|
|
156
|
+
if (stateManager !== undefined)
|
|
157
|
+
setResource(STATE_MANAGER_KEY, stateManager);
|
|
158
|
+
if (commandBus !== undefined)
|
|
159
|
+
setResource(COMMAND_BUS_KEY, commandBus);
|
|
160
|
+
if (queryBus !== undefined)
|
|
161
|
+
setResource(QUERY_BUS_KEY, queryBus);
|
|
162
|
+
// Optional per-event callback (e.g. monitoring hooks registered inside the UoW).
|
|
163
|
+
if (onEventDelivery)
|
|
164
|
+
onEventDelivery();
|
|
165
|
+
for (const reg of handlers) {
|
|
166
|
+
try {
|
|
167
|
+
await reg.handler(event.payload, event.metadata);
|
|
168
|
+
}
|
|
169
|
+
catch (err) {
|
|
170
|
+
await errorHandler.handleError(err, eventName, sequencedEvent.sequence);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
function scheduleImmediate() {
|
|
175
|
+
if (pollTimer !== null) {
|
|
176
|
+
clearTimeout(pollTimer);
|
|
177
|
+
}
|
|
178
|
+
pollTimer = setTimeout(poll, 0);
|
|
179
|
+
}
|
|
180
|
+
return {
|
|
181
|
+
get name() { return name; },
|
|
182
|
+
get running() { return isRunning; },
|
|
183
|
+
get position() { return token.position(); },
|
|
184
|
+
get replaying() { return isReplaying(token); },
|
|
185
|
+
async start() {
|
|
186
|
+
if (isRunning)
|
|
187
|
+
return;
|
|
188
|
+
await initialize();
|
|
189
|
+
isRunning = true;
|
|
190
|
+
poll();
|
|
191
|
+
},
|
|
192
|
+
stop() {
|
|
193
|
+
isRunning = false;
|
|
194
|
+
if (pollTimer !== null) {
|
|
195
|
+
clearTimeout(pollTimer);
|
|
196
|
+
pollTimer = null;
|
|
197
|
+
}
|
|
198
|
+
if (stream) {
|
|
199
|
+
stream.close();
|
|
200
|
+
stream = null;
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
async resetTokens(startPosition = 0n, resetContext) {
|
|
204
|
+
if (isRunning) {
|
|
205
|
+
throw new Error(`Processor "${name}" must be stopped before resetting tokens`);
|
|
206
|
+
}
|
|
207
|
+
const headPosition = await eventSource.getHeadPosition();
|
|
208
|
+
if (headPosition <= startPosition) {
|
|
209
|
+
token = globalSequenceToken(startPosition);
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
token = replayToken(globalSequenceToken(headPosition), globalSequenceToken(startPosition), resetContext);
|
|
213
|
+
}
|
|
214
|
+
if (tokenStore) {
|
|
215
|
+
await tokenStore.store(name, segment, token);
|
|
216
|
+
}
|
|
217
|
+
if (onReset) {
|
|
218
|
+
await onReset();
|
|
219
|
+
}
|
|
220
|
+
},
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
//# sourceMappingURL=tracking-event-processor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracking-event-processor.js","sourceRoot":"","sources":["../src/tracking-event-processor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A tracking token represents a processor's position in an event stream.
|
|
3
|
+
*
|
|
4
|
+
* This interface is extensible — event store implementations can define
|
|
5
|
+
* their own token types (e.g., a PostgreSQL extension might track
|
|
6
|
+
* commit timestamps alongside sequence positions).
|
|
7
|
+
*
|
|
8
|
+
* The framework ships two built-in implementations:
|
|
9
|
+
* - `GlobalSequenceToken` — for sequential event stores (in-memory, Axon Server)
|
|
10
|
+
* - `ReplayToken` — wraps any token to mark replay-in-progress state
|
|
11
|
+
*
|
|
12
|
+
* Tokens are immutable. All operations return new instances.
|
|
13
|
+
*/
|
|
14
|
+
export interface TrackingToken {
|
|
15
|
+
/**
|
|
16
|
+
* Discriminant for type narrowing and serialization.
|
|
17
|
+
* Each token implementation has a unique kind string.
|
|
18
|
+
*/
|
|
19
|
+
readonly kind: string;
|
|
20
|
+
/**
|
|
21
|
+
* The effective read position in the event stream.
|
|
22
|
+
* Used by the event source to know where to start reading.
|
|
23
|
+
*/
|
|
24
|
+
position(): bigint;
|
|
25
|
+
/**
|
|
26
|
+
* Does this token's position include all events covered by the other?
|
|
27
|
+
* Returns true if every event that `other` has seen, this token has also seen.
|
|
28
|
+
*
|
|
29
|
+
* Used for replay completion detection and segment merging.
|
|
30
|
+
*/
|
|
31
|
+
covers(other: TrackingToken): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Create a token representing the lower bound of this and another token.
|
|
34
|
+
* When opening a shared stream for multiple segments, use the lower bound
|
|
35
|
+
* to ensure no events are missed by any segment.
|
|
36
|
+
*/
|
|
37
|
+
lowerBound(other: TrackingToken): TrackingToken;
|
|
38
|
+
/**
|
|
39
|
+
* Create a token representing the upper bound of this and another token.
|
|
40
|
+
* Represents the furthest position — used for segment merging.
|
|
41
|
+
*/
|
|
42
|
+
upperBound(other: TrackingToken): TrackingToken;
|
|
43
|
+
/**
|
|
44
|
+
* Check if this token represents the same position as the other.
|
|
45
|
+
* Default: `this.covers(other) && other.covers(this)`.
|
|
46
|
+
*/
|
|
47
|
+
samePositionAs(other: TrackingToken): boolean;
|
|
48
|
+
}
|
|
49
|
+
export interface GlobalSequenceToken extends TrackingToken {
|
|
50
|
+
readonly kind: "global-sequence";
|
|
51
|
+
readonly sequence: bigint;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Creates a token for a global-sequence event store (monotonically increasing positions).
|
|
55
|
+
* This is the default token type for in-memory stores and Axon Server.
|
|
56
|
+
*/
|
|
57
|
+
export declare function globalSequenceToken(sequence: bigint): GlobalSequenceToken;
|
|
58
|
+
/**
|
|
59
|
+
* Sentinel token representing the beginning of the event stream.
|
|
60
|
+
* A processor starting with FIRST_TOKEN will read from position 0.
|
|
61
|
+
*/
|
|
62
|
+
export declare const FIRST_TOKEN: TrackingToken;
|
|
63
|
+
/**
|
|
64
|
+
* Sentinel token representing the tail of the event stream.
|
|
65
|
+
* A processor starting with LATEST_TOKEN will skip all existing events
|
|
66
|
+
* and only process new events appended after startup.
|
|
67
|
+
*/
|
|
68
|
+
export declare const LATEST_TOKEN: TrackingToken;
|
|
69
|
+
export interface ReplayToken extends TrackingToken {
|
|
70
|
+
readonly kind: "replay";
|
|
71
|
+
/** The wrapped token representing current progress during replay. */
|
|
72
|
+
readonly currentToken: TrackingToken;
|
|
73
|
+
/** The token representing the position when reset was triggered. Events before this are replayed. */
|
|
74
|
+
readonly tokenAtReset: TrackingToken;
|
|
75
|
+
/** Optional user-provided context (e.g., reason for the reset). */
|
|
76
|
+
readonly resetContext?: unknown;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Creates a replay token that wraps another token to mark replay-in-progress.
|
|
80
|
+
*
|
|
81
|
+
* During replay, events are re-delivered from `currentToken` up to `tokenAtReset`.
|
|
82
|
+
* Once `currentToken.covers(tokenAtReset)`, the replay is complete and the
|
|
83
|
+
* token unwraps to the current position.
|
|
84
|
+
*
|
|
85
|
+
* @param tokenAtReset The head position when reset was triggered
|
|
86
|
+
* @param currentToken Where replay is currently reading from
|
|
87
|
+
* @param resetContext Optional user-provided context
|
|
88
|
+
*/
|
|
89
|
+
export declare function replayToken(tokenAtReset: TrackingToken, currentToken: TrackingToken, resetContext?: unknown): ReplayToken;
|
|
90
|
+
export declare function isReplayToken(token: TrackingToken): token is ReplayToken;
|
|
91
|
+
export declare function isGlobalSequenceToken(token: TrackingToken): token is GlobalSequenceToken;
|
|
92
|
+
/**
|
|
93
|
+
* Advance a token to a new position. If the token is a ReplayToken and
|
|
94
|
+
* the new position covers the reset point, unwraps to a plain token.
|
|
95
|
+
*/
|
|
96
|
+
export declare function advanceToken(token: TrackingToken, newPosition: bigint): TrackingToken;
|
|
97
|
+
/**
|
|
98
|
+
* Check whether the given token represents a replay in progress.
|
|
99
|
+
* Returns true if the token is a ReplayToken AND the current position
|
|
100
|
+
* has not yet passed the reset position.
|
|
101
|
+
*
|
|
102
|
+
* A ReplayToken that has been fully replayed (current covers reset)
|
|
103
|
+
* would have been unwrapped by advanceToken — so any ReplayToken
|
|
104
|
+
* that still exists is mid-replay.
|
|
105
|
+
*/
|
|
106
|
+
export declare function isReplaying(token: TrackingToken): boolean;
|
|
107
|
+
/**
|
|
108
|
+
* Unwrap a token to its innermost non-replay token.
|
|
109
|
+
* If the token is not a ReplayToken, returns it unchanged.
|
|
110
|
+
*/
|
|
111
|
+
export declare function unwrapToken(token: TrackingToken): TrackingToken;
|
|
112
|
+
/**
|
|
113
|
+
* Check if an event at the given position was already processed before
|
|
114
|
+
* the reset (i.e., it's a replayed event, not a new one).
|
|
115
|
+
*
|
|
116
|
+
* Uses the token's `covers()` semantics: if the reset token covers
|
|
117
|
+
* the event position, then the event existed before the reset.
|
|
118
|
+
*/
|
|
119
|
+
export declare function wasProcessedBeforeReset(token: ReplayToken, eventPosition: bigint): boolean;
|
|
120
|
+
//# sourceMappingURL=tracking-token.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracking-token.d.ts","sourceRoot":"","sources":["../src/tracking-token.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IAErB;;;OAGG;IACH,QAAQ,IAAI,MAAM,CAAA;IAElB;;;;;OAKG;IACH,MAAM,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAA;IAErC;;;;OAIG;IACH,UAAU,CAAC,KAAK,EAAE,aAAa,GAAG,aAAa,CAAA;IAE/C;;;OAGG;IACH,UAAU,CAAC,KAAK,EAAE,aAAa,GAAG,aAAa,CAAA;IAE/C;;;OAGG;IACH,cAAc,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAA;CAC9C;AAMD,MAAM,WAAW,mBAAoB,SAAQ,aAAa;IACxD,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAA;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAC1B;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,mBAAmB,CAUzE;AAED;;;GAGG;AACH,eAAO,MAAM,WAAW,EAAE,aAAuC,CAAA;AAEjE;;;;GAIG;AACH,eAAO,MAAM,YAAY,EAAE,aAO1B,CAAA;AAMD,MAAM,WAAW,WAAY,SAAQ,aAAa;IAChD,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;IACvB,qEAAqE;IACrE,QAAQ,CAAC,YAAY,EAAE,aAAa,CAAA;IACpC,qGAAqG;IACrG,QAAQ,CAAC,YAAY,EAAE,aAAa,CAAA;IACpC,mEAAmE;IACnE,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAA;CAChC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CACzB,YAAY,EAAE,aAAa,EAC3B,YAAY,EAAE,aAAa,EAC3B,YAAY,CAAC,EAAE,OAAO,GACrB,WAAW,CA+Bb;AAMD,wBAAgB,aAAa,CAAC,KAAK,EAAE,aAAa,GAAG,KAAK,IAAI,WAAW,CAExE;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,aAAa,GAAG,KAAK,IAAI,mBAAmB,CAExF;AAMD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,GAAG,aAAa,CAcrF;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAEzD;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,aAAa,GAAG,aAAa,CAK/D;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAE1F"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a token for a global-sequence event store (monotonically increasing positions).
|
|
3
|
+
* This is the default token type for in-memory stores and Axon Server.
|
|
4
|
+
*/
|
|
5
|
+
export function globalSequenceToken(sequence) {
|
|
6
|
+
return {
|
|
7
|
+
kind: "global-sequence",
|
|
8
|
+
sequence,
|
|
9
|
+
position: () => sequence,
|
|
10
|
+
covers: (other) => sequence >= other.position(),
|
|
11
|
+
lowerBound: (other) => globalSequenceToken(sequence < other.position() ? sequence : other.position()),
|
|
12
|
+
upperBound: (other) => globalSequenceToken(sequence > other.position() ? sequence : other.position()),
|
|
13
|
+
samePositionAs: (other) => sequence === other.position(),
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Sentinel token representing the beginning of the event stream.
|
|
18
|
+
* A processor starting with FIRST_TOKEN will read from position 0.
|
|
19
|
+
*/
|
|
20
|
+
export const FIRST_TOKEN = globalSequenceToken(0n);
|
|
21
|
+
/**
|
|
22
|
+
* Sentinel token representing the tail of the event stream.
|
|
23
|
+
* A processor starting with LATEST_TOKEN will skip all existing events
|
|
24
|
+
* and only process new events appended after startup.
|
|
25
|
+
*/
|
|
26
|
+
export const LATEST_TOKEN = {
|
|
27
|
+
kind: "latest",
|
|
28
|
+
position: () => BigInt(Number.MAX_SAFE_INTEGER),
|
|
29
|
+
covers: () => true,
|
|
30
|
+
lowerBound: (other) => other,
|
|
31
|
+
upperBound: () => LATEST_TOKEN,
|
|
32
|
+
samePositionAs: (other) => other === LATEST_TOKEN || (other.kind === "latest"),
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Creates a replay token that wraps another token to mark replay-in-progress.
|
|
36
|
+
*
|
|
37
|
+
* During replay, events are re-delivered from `currentToken` up to `tokenAtReset`.
|
|
38
|
+
* Once `currentToken.covers(tokenAtReset)`, the replay is complete and the
|
|
39
|
+
* token unwraps to the current position.
|
|
40
|
+
*
|
|
41
|
+
* @param tokenAtReset The head position when reset was triggered
|
|
42
|
+
* @param currentToken Where replay is currently reading from
|
|
43
|
+
* @param resetContext Optional user-provided context
|
|
44
|
+
*/
|
|
45
|
+
export function replayToken(tokenAtReset, currentToken, resetContext) {
|
|
46
|
+
return {
|
|
47
|
+
kind: "replay",
|
|
48
|
+
currentToken,
|
|
49
|
+
tokenAtReset,
|
|
50
|
+
resetContext,
|
|
51
|
+
position: () => currentToken.position(),
|
|
52
|
+
covers: (other) => currentToken.covers(other),
|
|
53
|
+
lowerBound: (other) => {
|
|
54
|
+
const inner = currentToken.lowerBound(other);
|
|
55
|
+
// If the lower bound is still within replay range, keep the replay wrapper
|
|
56
|
+
if (!inner.covers(tokenAtReset)) {
|
|
57
|
+
return replayToken(tokenAtReset, inner, resetContext);
|
|
58
|
+
}
|
|
59
|
+
return inner;
|
|
60
|
+
},
|
|
61
|
+
upperBound: (other) => {
|
|
62
|
+
const inner = currentToken.upperBound(other);
|
|
63
|
+
// If the upper bound has passed the reset point, replay is done
|
|
64
|
+
if (inner.covers(tokenAtReset)) {
|
|
65
|
+
return inner;
|
|
66
|
+
}
|
|
67
|
+
return replayToken(tokenAtReset, inner, resetContext);
|
|
68
|
+
},
|
|
69
|
+
samePositionAs: (other) => currentToken.samePositionAs(other),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
// ---------------------------------------------------------------------------
|
|
73
|
+
// Type guards
|
|
74
|
+
// ---------------------------------------------------------------------------
|
|
75
|
+
export function isReplayToken(token) {
|
|
76
|
+
return token.kind === "replay";
|
|
77
|
+
}
|
|
78
|
+
export function isGlobalSequenceToken(token) {
|
|
79
|
+
return token.kind === "global-sequence";
|
|
80
|
+
}
|
|
81
|
+
// ---------------------------------------------------------------------------
|
|
82
|
+
// Token operations
|
|
83
|
+
// ---------------------------------------------------------------------------
|
|
84
|
+
/**
|
|
85
|
+
* Advance a token to a new position. If the token is a ReplayToken and
|
|
86
|
+
* the new position covers the reset point, unwraps to a plain token.
|
|
87
|
+
*/
|
|
88
|
+
export function advanceToken(token, newPosition) {
|
|
89
|
+
const advanced = globalSequenceToken(newPosition);
|
|
90
|
+
if (!isReplayToken(token)) {
|
|
91
|
+
return advanced;
|
|
92
|
+
}
|
|
93
|
+
// Check if replay is complete
|
|
94
|
+
if (advanced.covers(token.tokenAtReset)) {
|
|
95
|
+
return advanced;
|
|
96
|
+
}
|
|
97
|
+
// Still replaying — wrap the advanced position
|
|
98
|
+
return replayToken(token.tokenAtReset, advanced, token.resetContext);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Check whether the given token represents a replay in progress.
|
|
102
|
+
* Returns true if the token is a ReplayToken AND the current position
|
|
103
|
+
* has not yet passed the reset position.
|
|
104
|
+
*
|
|
105
|
+
* A ReplayToken that has been fully replayed (current covers reset)
|
|
106
|
+
* would have been unwrapped by advanceToken — so any ReplayToken
|
|
107
|
+
* that still exists is mid-replay.
|
|
108
|
+
*/
|
|
109
|
+
export function isReplaying(token) {
|
|
110
|
+
return isReplayToken(token);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Unwrap a token to its innermost non-replay token.
|
|
114
|
+
* If the token is not a ReplayToken, returns it unchanged.
|
|
115
|
+
*/
|
|
116
|
+
export function unwrapToken(token) {
|
|
117
|
+
if (isReplayToken(token)) {
|
|
118
|
+
return unwrapToken(token.currentToken);
|
|
119
|
+
}
|
|
120
|
+
return token;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Check if an event at the given position was already processed before
|
|
124
|
+
* the reset (i.e., it's a replayed event, not a new one).
|
|
125
|
+
*
|
|
126
|
+
* Uses the token's `covers()` semantics: if the reset token covers
|
|
127
|
+
* the event position, then the event existed before the reset.
|
|
128
|
+
*/
|
|
129
|
+
export function wasProcessedBeforeReset(token, eventPosition) {
|
|
130
|
+
return token.tokenAtReset.covers(globalSequenceToken(eventPosition));
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=tracking-token.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracking-token.js","sourceRoot":"","sources":["../src/tracking-token.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { type ResourceKey } from "@kronos-ts/common";
|
|
2
|
+
import type { UoWRunner } from "./unit-of-work.js";
|
|
3
|
+
/**
|
|
4
|
+
* Manages transaction lifecycle. Users provide an implementation
|
|
5
|
+
* for their specific database/ORM.
|
|
6
|
+
*
|
|
7
|
+
* The framework calls begin/commit/rollback — users never touch these directly.
|
|
8
|
+
*/
|
|
9
|
+
export interface TransactionManager<T = unknown> {
|
|
10
|
+
begin(): Promise<T>;
|
|
11
|
+
commit(tx: T): Promise<void>;
|
|
12
|
+
rollback(tx: T): Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* A no-op transaction manager for when no database transactions are needed.
|
|
16
|
+
*/
|
|
17
|
+
export declare function noTransactionManager(): TransactionManager<void>;
|
|
18
|
+
/** Resource key for storing the active transaction in the active UnitOfWork's ALS-backed resources. */
|
|
19
|
+
export declare const TRANSACTION_KEY: ResourceKey<unknown>;
|
|
20
|
+
/**
|
|
21
|
+
* Get the active transaction from the active UnitOfWork's ALS-backed resources.
|
|
22
|
+
* Returns undefined if no UnitOfWork is active or no transaction has been stored.
|
|
23
|
+
*
|
|
24
|
+
* ORM integrations use this to participate in the framework's transaction:
|
|
25
|
+
* ```
|
|
26
|
+
* const db = drizzle(pool, {
|
|
27
|
+
* transaction: () => getActiveTransaction(),
|
|
28
|
+
* })
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* Permissive undefined-return preserved (D-12 / D-23): callers outside a UoW
|
|
32
|
+
* get `undefined`, NOT a NoActiveUnitOfWork throw — this is an ORM escape hatch,
|
|
33
|
+
* not a framework-internal accessor.
|
|
34
|
+
*/
|
|
35
|
+
export declare function getActiveTransaction<T = unknown>(): T | undefined;
|
|
36
|
+
/**
|
|
37
|
+
* Wraps a delegate runner with transaction management. The transaction is:
|
|
38
|
+
* - Started before the delegate's action runs
|
|
39
|
+
* - Available via `getActiveTransaction()` throughout
|
|
40
|
+
* - Committed in the COMMIT phase
|
|
41
|
+
* - Rolled back on error
|
|
42
|
+
*
|
|
43
|
+
* The transaction is stored as a resource on the active UoW's ALS state,
|
|
44
|
+
* so all phases (PRE_INVOCATION through AFTER_COMMIT) and any code calling
|
|
45
|
+
* `getActiveTransaction()` inside the UoW see it.
|
|
46
|
+
*
|
|
47
|
+
* ```
|
|
48
|
+
* const txRunner = transactionalUnitOfWorkFactory(runInUoW, myTransactionManager)
|
|
49
|
+
* await txRunner(metadata, async () => { ... })
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
* Plan 03-04 (CTX-04 / D-34): rewritten as a composable runner wrapper.
|
|
53
|
+
* Previously took/returned `UnitOfWorkFactory`; the UoW interface and
|
|
54
|
+
* factory are gone, so this now takes/returns `UoWRunner`. The name is
|
|
55
|
+
* preserved despite the shape change — public docs and extension code
|
|
56
|
+
* import `transactionalUnitOfWorkFactory` by name. Phase 9 (Extension
|
|
57
|
+
* Migration) can rename if the kronos() app API warrants.
|
|
58
|
+
*/
|
|
59
|
+
export declare function transactionalUnitOfWorkFactory<T>(delegate: UoWRunner, txManager: TransactionManager<T>): UoWRunner;
|
|
60
|
+
//# sourceMappingURL=transaction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transaction.d.ts","sourceRoot":"","sources":["../src/transaction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAQjE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAElD;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB,CAAC,CAAC,GAAG,OAAO;IAC7C,KAAK,IAAI,OAAO,CAAC,CAAC,CAAC,CAAA;IACnB,MAAM,CAAC,EAAE,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5B,QAAQ,CAAC,EAAE,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC/B;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,kBAAkB,CAAC,IAAI,CAAC,CAM/D;AAED,uGAAuG;AACvG,eAAO,MAAM,eAAe,EAAE,WAAW,CAAC,OAAO,CAA8B,CAAA;AAE/E;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,GAAG,OAAO,KAAK,CAAC,GAAG,SAAS,CAIjE;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,8BAA8B,CAAC,CAAC,EAC9C,QAAQ,EAAE,SAAS,EACnB,SAAS,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAC/B,SAAS,CAcX"}
|