node-cqrs 1.0.0 → 1.1.0-alpha.1
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/CHANGELOG.md +30 -1
- package/README.md +115 -101
- package/dist/cjs/AbstractProjection.js +43 -18
- package/dist/cjs/AbstractProjection.js.map +1 -1
- package/dist/cjs/AggregateCommandHandler.js +27 -13
- package/dist/cjs/AggregateCommandHandler.js.map +1 -1
- package/dist/cjs/CqrsContainerBuilder.js +6 -1
- package/dist/cjs/CqrsContainerBuilder.js.map +1 -1
- package/dist/cjs/EventDispatchPipeline.js +12 -2
- package/dist/cjs/EventDispatchPipeline.js.map +1 -1
- package/dist/cjs/EventDispatcher.js +39 -10
- package/dist/cjs/EventDispatcher.js.map +1 -1
- package/dist/cjs/EventStore.js +7 -2
- package/dist/cjs/EventStore.js.map +1 -1
- package/dist/cjs/SagaEventHandler.js +54 -40
- package/dist/cjs/SagaEventHandler.js.map +1 -1
- package/dist/cjs/in-memory/InMemoryEventStorage.js +39 -24
- package/dist/cjs/in-memory/InMemoryEventStorage.js.map +1 -1
- package/dist/cjs/in-memory/InMemoryMessageBus.js +11 -5
- package/dist/cjs/in-memory/InMemoryMessageBus.js.map +1 -1
- package/dist/cjs/interfaces/IDispatchPipelineProcessor.js.map +1 -1
- package/dist/cjs/interfaces/IMessageMeta.js +3 -0
- package/dist/cjs/interfaces/IMessageMeta.js.map +1 -0
- package/dist/cjs/interfaces/IObservable.js.map +1 -1
- package/dist/cjs/interfaces/index.js +1 -0
- package/dist/cjs/interfaces/index.js.map +1 -1
- package/dist/cjs/mongodb/AbstractMongoAccessor.js +51 -0
- package/dist/cjs/mongodb/AbstractMongoAccessor.js.map +1 -0
- package/dist/cjs/mongodb/AbstractMongoObjectProjection.js +26 -0
- package/dist/cjs/mongodb/AbstractMongoObjectProjection.js.map +1 -0
- package/dist/cjs/mongodb/AbstractMongoView.js +57 -0
- package/dist/cjs/mongodb/AbstractMongoView.js.map +1 -0
- package/dist/cjs/mongodb/IContainer.js +3 -0
- package/dist/cjs/mongodb/IContainer.js.map +1 -0
- package/dist/cjs/mongodb/MongoEventLocker.js +104 -0
- package/dist/cjs/mongodb/MongoEventLocker.js.map +1 -0
- package/dist/cjs/mongodb/MongoEventStorage.js +200 -0
- package/dist/cjs/mongodb/MongoEventStorage.js.map +1 -0
- package/dist/cjs/mongodb/MongoObjectStorage.js +101 -0
- package/dist/cjs/mongodb/MongoObjectStorage.js.map +1 -0
- package/dist/cjs/mongodb/MongoObjectView.js +41 -0
- package/dist/cjs/mongodb/MongoObjectView.js.map +1 -0
- package/dist/cjs/mongodb/MongoProjectionDataParams.js +3 -0
- package/dist/cjs/mongodb/MongoProjectionDataParams.js.map +1 -0
- package/dist/cjs/mongodb/MongoViewLocker.js +136 -0
- package/dist/cjs/mongodb/MongoViewLocker.js.map +1 -0
- package/dist/cjs/mongodb/index.js +28 -0
- package/dist/cjs/mongodb/index.js.map +1 -0
- package/dist/cjs/mongodb/registerExitCleanup.js +28 -0
- package/dist/cjs/mongodb/registerExitCleanup.js.map +1 -0
- package/dist/cjs/mongodb/utils/getEventId.js +14 -0
- package/dist/cjs/mongodb/utils/getEventId.js.map +1 -0
- package/dist/cjs/mongodb/utils/index.js +18 -0
- package/dist/cjs/mongodb/utils/index.js.map +1 -0
- package/dist/cjs/rabbitmq/RabbitMqCommandBus.js +21 -8
- package/dist/cjs/rabbitmq/RabbitMqCommandBus.js.map +1 -1
- package/dist/cjs/rabbitmq/RabbitMqEventBus.js +2 -2
- package/dist/cjs/rabbitmq/RabbitMqEventBus.js.map +1 -1
- package/dist/cjs/rabbitmq/RabbitMqGateway.js +89 -64
- package/dist/cjs/rabbitmq/RabbitMqGateway.js.map +1 -1
- package/dist/cjs/redis/AbstractRedisAccessor.js +51 -0
- package/dist/cjs/redis/AbstractRedisAccessor.js.map +1 -0
- package/dist/cjs/redis/AbstractRedisProjection.js +26 -0
- package/dist/cjs/redis/AbstractRedisProjection.js.map +1 -0
- package/dist/cjs/redis/IContainer.js +3 -0
- package/dist/cjs/redis/IContainer.js.map +1 -0
- package/dist/cjs/redis/RedisEventLocker.js +96 -0
- package/dist/cjs/redis/RedisEventLocker.js.map +1 -0
- package/dist/cjs/redis/RedisObjectStorage.js +125 -0
- package/dist/cjs/redis/RedisObjectStorage.js.map +1 -0
- package/dist/cjs/redis/RedisProjectionDataParams.js +3 -0
- package/dist/cjs/redis/RedisProjectionDataParams.js.map +1 -0
- package/dist/cjs/redis/RedisView.js +81 -0
- package/dist/cjs/redis/RedisView.js.map +1 -0
- package/dist/cjs/redis/RedisViewLocker.js +111 -0
- package/dist/cjs/redis/RedisViewLocker.js.map +1 -0
- package/dist/cjs/redis/index.js +30 -0
- package/dist/cjs/redis/index.js.map +1 -0
- package/dist/cjs/redis/utils/getEventId.js +14 -0
- package/dist/cjs/redis/utils/getEventId.js.map +1 -0
- package/dist/cjs/redis/utils/index.js +18 -0
- package/dist/cjs/redis/utils/index.js.map +1 -0
- package/dist/cjs/sqlite/AbstractSqliteView.js.map +1 -1
- package/dist/cjs/sqlite/SqliteEventStorage.js +215 -0
- package/dist/cjs/sqlite/SqliteEventStorage.js.map +1 -0
- package/dist/cjs/sqlite/SqliteObjectStorage.js +6 -6
- package/dist/cjs/sqlite/SqliteObjectStorage.js.map +1 -1
- package/dist/cjs/sqlite/SqliteObjectView.js.map +1 -1
- package/dist/cjs/sqlite/index.js +1 -0
- package/dist/cjs/sqlite/index.js.map +1 -1
- package/dist/cjs/sqlite/utils/bufferToGuid.js +9 -0
- package/dist/cjs/sqlite/utils/bufferToGuid.js.map +1 -0
- package/dist/cjs/sqlite/utils/getEventId.js +2 -5
- package/dist/cjs/sqlite/utils/getEventId.js.map +1 -1
- package/dist/cjs/sqlite/utils/guid.js +1 -1
- package/dist/cjs/sqlite/utils/guid.js.map +1 -1
- package/dist/cjs/sqlite/utils/index.js +1 -0
- package/dist/cjs/sqlite/utils/index.js.map +1 -1
- package/dist/cjs/telemetry/index.js +20 -0
- package/dist/cjs/telemetry/index.js.map +1 -0
- package/dist/cjs/telemetry/recordSpanError.js +19 -0
- package/dist/cjs/telemetry/recordSpanError.js.map +1 -0
- package/dist/cjs/telemetry/spanAttributes.js +26 -0
- package/dist/cjs/telemetry/spanAttributes.js.map +1 -0
- package/dist/cjs/telemetry/spanContext.js +25 -0
- package/dist/cjs/telemetry/spanContext.js.map +1 -0
- package/dist/cjs/utils/MapAssertable.js +25 -1
- package/dist/cjs/utils/MapAssertable.js.map +1 -1
- package/dist/esm/AbstractProjection.js +32 -7
- package/dist/esm/AbstractProjection.js.map +1 -1
- package/dist/esm/AggregateCommandHandler.js +22 -8
- package/dist/esm/AggregateCommandHandler.js.map +1 -1
- package/dist/esm/CqrsContainerBuilder.js +6 -1
- package/dist/esm/CqrsContainerBuilder.js.map +1 -1
- package/dist/esm/EventDispatchPipeline.js +12 -2
- package/dist/esm/EventDispatchPipeline.js.map +1 -1
- package/dist/esm/EventDispatcher.js +33 -4
- package/dist/esm/EventDispatcher.js.map +1 -1
- package/dist/esm/EventStore.js +7 -2
- package/dist/esm/EventStore.js.map +1 -1
- package/dist/esm/SagaEventHandler.js +42 -28
- package/dist/esm/SagaEventHandler.js.map +1 -1
- package/dist/esm/in-memory/InMemoryEventStorage.js +25 -10
- package/dist/esm/in-memory/InMemoryEventStorage.js.map +1 -1
- package/dist/esm/in-memory/InMemoryMessageBus.js +11 -5
- package/dist/esm/in-memory/InMemoryMessageBus.js.map +1 -1
- package/dist/esm/interfaces/IDispatchPipelineProcessor.js.map +1 -1
- package/dist/esm/interfaces/IMessageMeta.js +2 -0
- package/dist/esm/interfaces/IMessageMeta.js.map +1 -0
- package/dist/esm/interfaces/IObservable.js.map +1 -1
- package/dist/esm/interfaces/index.js +1 -0
- package/dist/esm/interfaces/index.js.map +1 -1
- package/dist/esm/mongodb/AbstractMongoAccessor.js +47 -0
- package/dist/esm/mongodb/AbstractMongoAccessor.js.map +1 -0
- package/dist/esm/mongodb/AbstractMongoObjectProjection.js +22 -0
- package/dist/esm/mongodb/AbstractMongoObjectProjection.js.map +1 -0
- package/dist/esm/mongodb/AbstractMongoView.js +53 -0
- package/dist/esm/mongodb/AbstractMongoView.js.map +1 -0
- package/dist/esm/mongodb/IContainer.js +2 -0
- package/dist/esm/mongodb/IContainer.js.map +1 -0
- package/dist/esm/mongodb/MongoEventLocker.js +100 -0
- package/dist/esm/mongodb/MongoEventLocker.js.map +1 -0
- package/dist/esm/mongodb/MongoEventStorage.js +196 -0
- package/dist/esm/mongodb/MongoEventStorage.js.map +1 -0
- package/dist/esm/mongodb/MongoObjectStorage.js +97 -0
- package/dist/esm/mongodb/MongoObjectStorage.js.map +1 -0
- package/dist/esm/mongodb/MongoObjectView.js +37 -0
- package/dist/esm/mongodb/MongoObjectView.js.map +1 -0
- package/dist/esm/mongodb/MongoProjectionDataParams.js +2 -0
- package/dist/esm/mongodb/MongoProjectionDataParams.js.map +1 -0
- package/dist/esm/mongodb/MongoViewLocker.js +132 -0
- package/dist/esm/mongodb/MongoViewLocker.js.map +1 -0
- package/dist/esm/mongodb/index.js +12 -0
- package/dist/esm/mongodb/index.js.map +1 -0
- package/dist/esm/mongodb/registerExitCleanup.js +24 -0
- package/dist/esm/mongodb/registerExitCleanup.js.map +1 -0
- package/dist/esm/mongodb/utils/getEventId.js +10 -0
- package/dist/esm/mongodb/utils/getEventId.js.map +1 -0
- package/dist/esm/mongodb/utils/index.js +2 -0
- package/dist/esm/mongodb/utils/index.js.map +1 -0
- package/dist/esm/rabbitmq/RabbitMqCommandBus.js +21 -8
- package/dist/esm/rabbitmq/RabbitMqCommandBus.js.map +1 -1
- package/dist/esm/rabbitmq/RabbitMqEventBus.js +2 -2
- package/dist/esm/rabbitmq/RabbitMqEventBus.js.map +1 -1
- package/dist/esm/rabbitmq/RabbitMqGateway.js +69 -44
- package/dist/esm/rabbitmq/RabbitMqGateway.js.map +1 -1
- package/dist/esm/redis/AbstractRedisAccessor.js +47 -0
- package/dist/esm/redis/AbstractRedisAccessor.js.map +1 -0
- package/dist/esm/redis/AbstractRedisProjection.js +22 -0
- package/dist/esm/redis/AbstractRedisProjection.js.map +1 -0
- package/dist/esm/redis/IContainer.js +2 -0
- package/dist/esm/redis/IContainer.js.map +1 -0
- package/dist/esm/redis/RedisEventLocker.js +92 -0
- package/dist/esm/redis/RedisEventLocker.js.map +1 -0
- package/dist/esm/redis/RedisObjectStorage.js +121 -0
- package/dist/esm/redis/RedisObjectStorage.js.map +1 -0
- package/dist/esm/redis/RedisProjectionDataParams.js +2 -0
- package/dist/esm/redis/RedisProjectionDataParams.js.map +1 -0
- package/dist/esm/redis/RedisView.js +77 -0
- package/dist/esm/redis/RedisView.js.map +1 -0
- package/dist/esm/redis/RedisViewLocker.js +107 -0
- package/dist/esm/redis/RedisViewLocker.js.map +1 -0
- package/dist/esm/redis/index.js +14 -0
- package/dist/esm/redis/index.js.map +1 -0
- package/dist/esm/redis/utils/getEventId.js +10 -0
- package/dist/esm/redis/utils/getEventId.js.map +1 -0
- package/dist/esm/redis/utils/index.js +2 -0
- package/dist/esm/redis/utils/index.js.map +1 -0
- package/dist/esm/sqlite/AbstractSqliteView.js.map +1 -1
- package/dist/esm/sqlite/SqliteEventStorage.js +211 -0
- package/dist/esm/sqlite/SqliteEventStorage.js.map +1 -0
- package/dist/esm/sqlite/SqliteObjectStorage.js +7 -7
- package/dist/esm/sqlite/SqliteObjectStorage.js.map +1 -1
- package/dist/esm/sqlite/SqliteObjectView.js.map +1 -1
- package/dist/esm/sqlite/index.js +1 -0
- package/dist/esm/sqlite/index.js.map +1 -1
- package/dist/esm/sqlite/utils/bufferToGuid.js +5 -0
- package/dist/esm/sqlite/utils/bufferToGuid.js.map +1 -0
- package/dist/esm/sqlite/utils/getEventId.js +2 -2
- package/dist/esm/sqlite/utils/getEventId.js.map +1 -1
- package/dist/esm/sqlite/utils/guid.js +1 -1
- package/dist/esm/sqlite/utils/guid.js.map +1 -1
- package/dist/esm/sqlite/utils/index.js +1 -0
- package/dist/esm/sqlite/utils/index.js.map +1 -1
- package/dist/esm/telemetry/index.js +4 -0
- package/dist/esm/telemetry/index.js.map +1 -0
- package/dist/esm/telemetry/recordSpanError.js +16 -0
- package/dist/esm/telemetry/recordSpanError.js.map +1 -0
- package/dist/esm/telemetry/spanAttributes.js +23 -0
- package/dist/esm/telemetry/spanAttributes.js.map +1 -0
- package/dist/esm/telemetry/spanContext.js +22 -0
- package/dist/esm/telemetry/spanContext.js.map +1 -0
- package/dist/esm/utils/MapAssertable.js +25 -1
- package/dist/esm/utils/MapAssertable.js.map +1 -1
- package/dist/types/AbstractProjection.d.ts +3 -1
- package/dist/types/AggregateCommandHandler.d.ts +3 -3
- package/dist/types/EventDispatchPipeline.d.ts +3 -1
- package/dist/types/EventDispatcher.d.ts +9 -1
- package/dist/types/EventStore.d.ts +4 -2
- package/dist/types/SagaEventHandler.d.ts +3 -3
- package/dist/types/in-memory/InMemoryEventStorage.d.ts +2 -1
- package/dist/types/in-memory/InMemoryMessageBus.d.ts +3 -3
- package/dist/types/interfaces/ICommandBus.d.ts +3 -2
- package/dist/types/interfaces/IContainer.d.ts +7 -0
- package/dist/types/interfaces/IDispatchPipelineProcessor.d.ts +2 -0
- package/dist/types/interfaces/IEventDispatcher.d.ts +3 -0
- package/dist/types/interfaces/IMessageMeta.d.ts +4 -0
- package/dist/types/interfaces/IObservable.d.ts +2 -1
- package/dist/types/interfaces/index.d.ts +1 -0
- package/dist/types/mongodb/AbstractMongoAccessor.d.ts +26 -0
- package/dist/types/mongodb/AbstractMongoObjectProjection.d.ts +8 -0
- package/dist/types/mongodb/AbstractMongoView.d.ts +25 -0
- package/dist/types/mongodb/IContainer.d.ts +11 -0
- package/dist/types/mongodb/MongoEventLocker.d.ts +47 -0
- package/dist/types/mongodb/MongoEventStorage.d.ts +27 -0
- package/dist/types/mongodb/MongoObjectStorage.d.ts +26 -0
- package/dist/types/mongodb/MongoObjectView.d.ts +16 -0
- package/dist/types/mongodb/MongoProjectionDataParams.d.ts +14 -0
- package/dist/types/mongodb/MongoViewLocker.d.ts +43 -0
- package/dist/types/mongodb/index.d.ts +11 -0
- package/dist/types/mongodb/registerExitCleanup.d.ts +10 -0
- package/dist/types/mongodb/utils/getEventId.d.ts +5 -0
- package/dist/types/mongodb/utils/index.d.ts +1 -0
- package/dist/types/rabbitmq/IContainer.d.ts +2 -2
- package/dist/types/rabbitmq/RabbitMqCommandBus.d.ts +5 -4
- package/dist/types/rabbitmq/RabbitMqEventBus.d.ts +2 -2
- package/dist/types/rabbitmq/RabbitMqGateway.d.ts +4 -4
- package/dist/types/redis/AbstractRedisAccessor.d.ts +26 -0
- package/dist/types/redis/AbstractRedisProjection.d.ts +8 -0
- package/dist/types/redis/IContainer.d.ts +7 -0
- package/dist/types/redis/RedisEventLocker.d.ts +36 -0
- package/dist/types/redis/RedisObjectStorage.d.ts +26 -0
- package/dist/types/redis/RedisProjectionDataParams.d.ts +21 -0
- package/dist/types/redis/RedisView.d.ts +33 -0
- package/dist/types/redis/RedisViewLocker.d.ts +35 -0
- package/dist/types/redis/index.d.ts +13 -0
- package/dist/types/redis/utils/getEventId.d.ts +5 -0
- package/dist/types/redis/utils/index.d.ts +1 -0
- package/dist/types/sqlite/AbstractSqliteView.d.ts +2 -2
- package/dist/types/sqlite/SqliteEventStorage.d.ts +18 -0
- package/dist/types/sqlite/SqliteObjectStorage.d.ts +7 -7
- package/dist/types/sqlite/SqliteObjectView.d.ts +7 -7
- package/dist/types/sqlite/index.d.ts +1 -0
- package/dist/types/sqlite/utils/bufferToGuid.d.ts +4 -0
- package/dist/types/sqlite/utils/getEventId.d.ts +1 -1
- package/dist/types/sqlite/utils/guid.d.ts +2 -1
- package/dist/types/sqlite/utils/index.d.ts +1 -0
- package/dist/types/telemetry/index.d.ts +3 -0
- package/dist/types/telemetry/recordSpanError.d.ts +6 -0
- package/dist/types/telemetry/spanAttributes.d.ts +14 -0
- package/dist/types/telemetry/spanContext.d.ts +12 -0
- package/dist/types/utils/MapAssertable.d.ts +8 -0
- package/package.json +43 -13
package/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,23 @@
|
|
|
1
|
-
# [1.0.
|
|
1
|
+
# [1.1.0-alpha.1](https://github.com/snatalenko/node-cqrs/compare/v1.1.0-alpha.0...v1.1.0-alpha.1) (2026-03-24)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* MongoDb-backed view model (`MongoObjectView`, `AbstractMongoObjectProjection`) ([4995bfe](https://github.com/snatalenko/node-cqrs/commit/4995bfe2daf53372d3e7e36d59ee103219ad6a35))
|
|
7
|
+
|
|
8
|
+
### Changes
|
|
9
|
+
|
|
10
|
+
* Use `Identifier` as id type in redis and sqlite views ([dfbe964](https://github.com/snatalenko/node-cqrs/commit/dfbe9648a8ea8e7e5550aa40e0094ca8af1758ef))
|
|
11
|
+
* Add default queueName for RabbitMqCommandBus ([ee4b5a1](https://github.com/snatalenko/node-cqrs/commit/ee4b5a170e44db6227e76d2ffb1695b6dfaef6e4))
|
|
12
|
+
* Add error handling and drain functionality to event publishing process ([d23ea62](https://github.com/snatalenko/node-cqrs/commit/d23ea621c8a71e2cda4baaf091166534c4f5af2e))
|
|
13
|
+
|
|
14
|
+
### Documentation
|
|
15
|
+
|
|
16
|
+
* Add detailed documentation for redis and mongodb modules ([72e66f5](https://github.com/snatalenko/node-cqrs/commit/72e66f5508a6df6c0a4a341e752cfab76830478a))
|
|
17
|
+
* Detailed sqlite and rabbitmq instructions ([dd242fd](https://github.com/snatalenko/node-cqrs/commit/dd242fd73018bcfa0583ab1ddd12518c4f3a4777))
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# [1.1.0-alpha.0](https://github.com/snatalenko/node-cqrs/compare/v0.17.0...v1.1.0-alpha.0) (2026-03-21)
|
|
2
21
|
|
|
3
22
|
|
|
4
23
|
### Features
|
|
@@ -8,7 +27,12 @@
|
|
|
8
27
|
* Support selective restore event loading ([3a74da6](https://github.com/snatalenko/node-cqrs/commit/3a74da6807a0250bff0e05ae57f922922d8847be))
|
|
9
28
|
* Multi-saga correlation via `message.sagaOrigins` + simplified ISaga (mutate/handle) with AbstractSaga state support ([ae67594](https://github.com/snatalenko/node-cqrs/commit/ae675944faa2b01aefed23d7c0e456e2581f066f))
|
|
10
29
|
* Re-process commands on concurrency errors in EventStorage ([8a60560](https://github.com/snatalenko/node-cqrs/commit/8a60560b1e3dc7bff85217851a12c503730a9e19))
|
|
30
|
+
* Integrate OpenTelemetry for command and event tracing ([b03997f](https://github.com/snatalenko/node-cqrs/commit/b03997f17b0e88cccaeca6ca599ad5d43457390a))
|
|
31
|
+
* RabbitMQ trace context propagation via W3C TraceContext AMQP headers ([1db354a](https://github.com/snatalenko/node-cqrs/commit/1db354af099cfe9c3884d0ea46087da1610e73da))
|
|
11
32
|
* Add RabbitMQ command bus implementation and enhance MQ configuration options ([a565c59](https://github.com/snatalenko/node-cqrs/commit/a565c59f87fa46f2279781329ebacf55b1245805))
|
|
33
|
+
* Redis-backed projection views with distributed locking (experimental) ([8ff0f1e](https://github.com/snatalenko/node-cqrs/commit/8ff0f1e14a6fdcd676d549a9d4c7ad2d2ce7cd4c))
|
|
34
|
+
* SqliteEventStorage ([ffaf766](https://github.com/snatalenko/node-cqrs/commit/ffaf7669139e797488c50332cac94a234738cc62))
|
|
35
|
+
* MongoDB-backed event storage ([53fb5e1](https://github.com/snatalenko/node-cqrs/commit/53fb5e1c0d7a027f9afebf88f8d3d516d06c3c48))
|
|
12
36
|
|
|
13
37
|
### Changes
|
|
14
38
|
|
|
@@ -31,6 +55,8 @@
|
|
|
31
55
|
* Add option for queue expiration ([7073832](https://github.com/snatalenko/node-cqrs/commit/7073832aa5287f5786d6f8f06d4ad67698ac3f19))
|
|
32
56
|
* Add option to disable handler timeout on rabbitmq subscription ([dd76d5e](https://github.com/snatalenko/node-cqrs/commit/dd76d5e9c728739620ba7d4399108db97293772f))
|
|
33
57
|
* Pass event meta through projection chain, allow skipping last event update for internal-origin events ([dd36395](https://github.com/snatalenko/node-cqrs/commit/dd36395a2ad4be712df0a81e60514701ec7e03b8))
|
|
58
|
+
* Remove "md5" from peer dependencies ([87600bc](https://github.com/snatalenko/node-cqrs/commit/87600bc5a857b0e251ceed37d99cc5cf66f61ee5))
|
|
59
|
+
* Expose `restorePromises` on DI container for tracking async projection restoring processes ([ebdaa2c](https://github.com/snatalenko/node-cqrs/commit/ebdaa2ca4ff6d1088deba5d4069d7a027be65107))
|
|
34
60
|
|
|
35
61
|
### Fixes
|
|
36
62
|
|
|
@@ -40,6 +66,7 @@
|
|
|
40
66
|
* Failing synchronous event handler may prevent execution of other handlers ([fb026e5](https://github.com/snatalenko/node-cqrs/commit/fb026e5263f13c05e8e6999ff0162700551f587c))
|
|
41
67
|
* All errors being ignored with concurrency resolution set to 'ignore' ([0cb10bc](https://github.com/snatalenko/node-cqrs/commit/0cb10bcaef5ec76050b14caf6d5ad710a005b6d0))
|
|
42
68
|
* Avoid finalization of already finalized MQ messages ([a9a1ea6](https://github.com/snatalenko/node-cqrs/commit/a9a1ea63fc85ba8cd6b09e2c2330636e22639b2c))
|
|
69
|
+
* Defer aggregate cache pre-warm to avoid orphaned async operations on command error ([677ed29](https://github.com/snatalenko/node-cqrs/commit/677ed29cd6dab5f80b021ee90ad1dd8c3586fcd3))
|
|
43
70
|
|
|
44
71
|
### Documentation
|
|
45
72
|
|
|
@@ -47,6 +74,8 @@
|
|
|
47
74
|
* Add CONTRIBUTING.md symlinks for coding agents ([878f25f](https://github.com/snatalenko/node-cqrs/commit/878f25fd99ff4884045ea4d8b2cb739f3e2bf5ff))
|
|
48
75
|
* Update package description and keywords ([15ef847](https://github.com/snatalenko/node-cqrs/commit/15ef847b4b7dc7007f38423580704604901fc588))
|
|
49
76
|
* Add AbstractWorkerProjection description to readme.md ([dd3952c](https://github.com/snatalenko/node-cqrs/commit/dd3952cc79d8a5762cd5b5bc320429ac9d0e7403))
|
|
77
|
+
* Remove readme code samples in favor of runnable ./examples/ ([73417c3](https://github.com/snatalenko/node-cqrs/commit/73417c3b997f2d838b02dd0b91f05e0a6001e556))
|
|
78
|
+
* Rearrange examples to use same aggregate and projection implementation ([5325901](https://github.com/snatalenko/node-cqrs/commit/532590143fd29a205b6eb3fd4d6c686b17956835))
|
|
50
79
|
|
|
51
80
|
### Tests
|
|
52
81
|
|
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ node-cqrs
|
|
|
12
12
|
Infrastructure-agnostic building blocks for CQRS/ES, inspired by Lokad.CQRS.
|
|
13
13
|
|
|
14
14
|
CQRS/ES can be simple in a single process - minimal code, no framework:
|
|
15
|
-
[examples/user-domain
|
|
15
|
+
[examples/user-domain-framework-free](examples/user-domain-framework-free/index.ts).
|
|
16
16
|
This library handles the "boring but hard" parts required in distributed environments:
|
|
17
17
|
|
|
18
18
|
- safer async command + event handling (per-aggregate FIFO, shared restore, fewer footguns)
|
|
@@ -33,20 +33,21 @@ Built around ES6/TypeScript classes and dependency injection - swap implementati
|
|
|
33
33
|
- [Installation](#installation)
|
|
34
34
|
- [ContainerBuilder](#containerbuilder)
|
|
35
35
|
- [Commands](#commands)
|
|
36
|
-
- [
|
|
36
|
+
- [Write Model (Aggregates)](#write-model-aggregates)
|
|
37
37
|
- [AbstractAggregate](#abstractaggregate)
|
|
38
38
|
- [Aggregate State](#aggregate-state)
|
|
39
39
|
- [External Dependencies](#external-dependencies)
|
|
40
|
-
- [Projections and Views
|
|
40
|
+
- [Read Model (Projections and Views)](#read-model-projections-and-views)
|
|
41
41
|
- [AbstractProjection](#abstractprojection)
|
|
42
42
|
- [View restoring on start](#view-restoring-on-start)
|
|
43
43
|
- [Accessing views](#accessing-views)
|
|
44
44
|
- [Sagas](#sagas)
|
|
45
|
-
- [Infrastructure
|
|
46
|
-
- [
|
|
47
|
-
- [
|
|
48
|
-
- [
|
|
49
|
-
- [
|
|
45
|
+
- [Infrastructure Modules](#infrastructure-modules)
|
|
46
|
+
- [Event Storage](#event-storage)
|
|
47
|
+
- [Read Model](#read-model)
|
|
48
|
+
- [Message Buses](#message-buses)
|
|
49
|
+
- [Other](#other)
|
|
50
|
+
- [OpenTelemetry](#opentelemetry)
|
|
50
51
|
- [Examples](#examples)
|
|
51
52
|
|
|
52
53
|
|
|
@@ -72,15 +73,15 @@ interface IMessage<TPayload = any> {
|
|
|
72
73
|
|
|
73
74
|
Domain logic lives in three building blocks:
|
|
74
75
|
|
|
75
|
-
- **[Aggregates](#
|
|
76
|
-
- **[Projections](#projections-and-views
|
|
76
|
+
- **[Aggregates](#write-model-aggregates)** - handle commands and emit events
|
|
77
|
+
- **[Projections](#read-model-projections-and-views)** - consume events and update views
|
|
77
78
|
- **[Sagas](#sagas)** - manage processes by reacting to events and enqueueing follow-up commands
|
|
78
79
|
|
|
79
80
|
Message delivery is handled by the following components, in order:
|
|
80
81
|
|
|
81
82
|
- **[Command Bus](src/in-memory/InMemoryMessageBus.ts)** - routes commands to handlers
|
|
82
83
|
- **[Aggregate Command Handler](src/AggregateCommandHandler.ts)** - restores aggregate state and executes commands
|
|
83
|
-
- **[Event Store](src/EventStore.ts)**
|
|
84
|
+
- **[Event Store](src/EventStore.ts)** - runs the event dispatch pipeline (e.g. encoding, persistence), then publishes events to the event bus for delivery to all subscribers
|
|
84
85
|
- **[Saga Event Handler](src/SagaEventHandler.ts)** - restores saga state and applies events
|
|
85
86
|
|
|
86
87
|
> `src/`, `tests/`, and `examples/` are good entry points - the codebase is intentionally small and readable.
|
|
@@ -94,13 +95,6 @@ npm install node-cqrs
|
|
|
94
95
|
|
|
95
96
|
Node.js 16+ and browsers are supported.
|
|
96
97
|
|
|
97
|
-
Optional peer dependencies:
|
|
98
|
-
|
|
99
|
-
| Module | Packages |
|
|
100
|
-
|--------|----------|
|
|
101
|
-
| SQLite | `better-sqlite3`, `md5` |
|
|
102
|
-
| RabbitMQ | `amqplib` |
|
|
103
|
-
| Worker threads | `comlink` |
|
|
104
98
|
|
|
105
99
|
|
|
106
100
|
## ContainerBuilder
|
|
@@ -154,10 +148,10 @@ commandBus.send('signupUser', undefined, { payload: { profile, password } });
|
|
|
154
148
|
commandBus.send({ type: 'signupUser', payload: { profile, password } });
|
|
155
149
|
```
|
|
156
150
|
|
|
157
|
-
Commands are handled by [Aggregates](#
|
|
151
|
+
Commands are handled by [Aggregates](#write-model-aggregates) and may also be enqueued by [Sagas](#sagas).
|
|
158
152
|
|
|
159
153
|
|
|
160
|
-
##
|
|
154
|
+
## Write Model (Aggregates)
|
|
161
155
|
|
|
162
156
|
Aggregates handle commands, validate business rules, and emit events.
|
|
163
157
|
Minimal contract ([IAggregate](src/interfaces/IAggregate.ts)):
|
|
@@ -249,7 +243,7 @@ builder.registerAggregate(UserAggregate);
|
|
|
249
243
|
```
|
|
250
244
|
|
|
251
245
|
|
|
252
|
-
## Projections and Views
|
|
246
|
+
## Read Model (Projections and Views)
|
|
253
247
|
|
|
254
248
|
Projections listen to events and update views.
|
|
255
249
|
Minimal contract ([IProjection](src/interfaces/IProjection.ts)):
|
|
@@ -274,14 +268,18 @@ interface IProjection<TView> extends IObserver {
|
|
|
274
268
|
Same name-matching rule as AbstractAggregate - `userCreated()` handles the `userCreated` event:
|
|
275
269
|
|
|
276
270
|
```ts
|
|
277
|
-
class UsersProjection extends AbstractProjection<Map<string, {
|
|
271
|
+
class UsersProjection extends AbstractProjection<Map<string, {
|
|
272
|
+
username: string
|
|
273
|
+
}>> {
|
|
278
274
|
constructor() {
|
|
279
275
|
super();
|
|
280
276
|
this.view = new Map();
|
|
281
277
|
}
|
|
282
278
|
|
|
283
279
|
userCreated(event: IEvent<UserCreatedEventPayload>) {
|
|
284
|
-
this.view.set(event.aggregateId
|
|
280
|
+
this.view.set(event.aggregateId, {
|
|
281
|
+
username: event.payload.username
|
|
282
|
+
});
|
|
285
283
|
}
|
|
286
284
|
}
|
|
287
285
|
```
|
|
@@ -295,7 +293,8 @@ For persistent views and safe restarts, implement [IViewLocker](src/interfaces/I
|
|
|
295
293
|
### Accessing views
|
|
296
294
|
|
|
297
295
|
```ts
|
|
298
|
-
|
|
296
|
+
// optional interface for container typing
|
|
297
|
+
interface IMyContainer extends IContainer {
|
|
299
298
|
usersView: UsersView;
|
|
300
299
|
}
|
|
301
300
|
|
|
@@ -321,7 +320,9 @@ Sagas coordinate multi-step processes by reacting to events and enqueueing follo
|
|
|
321
320
|
```ts
|
|
322
321
|
class WelcomeEmailSaga extends AbstractSaga {
|
|
323
322
|
userSignedUp(event) {
|
|
324
|
-
this.enqueue('sendWelcomeEmail', undefined, {
|
|
323
|
+
this.enqueue('sendWelcomeEmail', undefined, {
|
|
324
|
+
email: event.payload.email
|
|
325
|
+
});
|
|
325
326
|
}
|
|
326
327
|
}
|
|
327
328
|
|
|
@@ -391,114 +392,127 @@ interface ISaga {
|
|
|
391
392
|
```
|
|
392
393
|
|
|
393
394
|
|
|
394
|
-
## Infrastructure
|
|
395
|
+
## Infrastructure Modules
|
|
395
396
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
| In-memory | `node-cqrs` | Tests and local development |
|
|
399
|
-
| SQLite | `node-cqrs/sqlite` | Persistent views with catch-up |
|
|
400
|
-
| RabbitMQ | `node-cqrs/rabbitmq` | Cross-process event distribution |
|
|
401
|
-
| Workers | `node-cqrs/workers` | CPU-heavy projections in worker threads |
|
|
397
|
+
Swap implementations by registering different classes in the DI container.
|
|
398
|
+
All modules below implement the same interfaces - pick what fits your deployment.
|
|
402
399
|
|
|
403
|
-
###
|
|
400
|
+
### Event Storage
|
|
404
401
|
|
|
405
|
-
|
|
406
|
-
- [InMemoryMessageBus](src/in-memory/InMemoryMessageBus.ts) - event/command bus
|
|
407
|
-
- [InMemoryView](src/in-memory/InMemoryView.ts) - in-memory view with locking support
|
|
402
|
+
Where aggregate events are persisted and replayed from.
|
|
408
403
|
|
|
409
|
-
|
|
404
|
+
| Implementation | Import | Peer deps | Notes |
|
|
405
|
+
| ---------------------- | ------------------- | ---------------- | --------------------------------------------------------------------------------- |
|
|
406
|
+
| `InMemoryEventStorage` | `node-cqrs` | - | Dev/test only; data lost on restart ([example](examples/user-domain-ts/index.ts)) |
|
|
407
|
+
| `SqliteEventStorage` | `node-cqrs/sqlite` | `better-sqlite3` | Embedded, single-process ([example](examples/sqlite/index.ts)) |
|
|
408
|
+
| `MongoEventStorage` | `node-cqrs/mongodb` | `mongodb` | Distributed, multi-process ([example](examples/mongodb-eventstore/index.ts)) |
|
|
410
409
|
|
|
411
|
-
|
|
412
|
-
import { AbstractSqliteView, SqliteObjectView } from 'node-cqrs/sqlite';
|
|
413
|
-
```
|
|
410
|
+
### Read Model
|
|
414
411
|
|
|
415
|
-
|
|
416
|
-
|
|
412
|
+
Where projections store and query their read-side state.
|
|
413
|
+
Each persistent backend provides the same layered set of building blocks:
|
|
417
414
|
|
|
418
|
-
|
|
415
|
+
| Layer | Purpose |
|
|
416
|
+
| ------------------- | ------------------------------------------------------------------------------------------------ |
|
|
417
|
+
| **Object storage** | Key/value CRUD with optimistic concurrency |
|
|
418
|
+
| **View locker** | Prevents concurrent schema-migration rebuilds - only one process rebuilds at a time; others wait |
|
|
419
|
+
| **Event locker** | Per-event deduplication and last-projected checkpoint |
|
|
420
|
+
| **Composite view** | Combines the above into a single view object |
|
|
421
|
+
| **Base projection** | Wires locking, checkpointing, and error handling automatically |
|
|
419
422
|
|
|
420
|
-
|
|
421
|
-
import { RabbitMqEventBus, RabbitMqCommandBus, RabbitMqGateway } from 'node-cqrs/rabbitmq';
|
|
422
|
-
```
|
|
423
|
+
#### In-memory
|
|
423
424
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
425
|
+
| Class | Notes |
|
|
426
|
+
| -------------- | -------------------------------------------------------------- |
|
|
427
|
+
| `InMemoryLock` | Simple in-process lock |
|
|
428
|
+
| `InMemoryView` | Simple `Map`-backed view; restores from events on each restart |
|
|
427
429
|
|
|
428
|
-
|
|
430
|
+
#### SQLite (`node-cqrs/sqlite`, peer dep: `better-sqlite3`)
|
|
429
431
|
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
432
|
+
| Class | Role |
|
|
433
|
+
| -------------------------------- | -------------------------------------------------------------------------------------- |
|
|
434
|
+
| `SqliteObjectStorage` | Key/value object storage with version-based concurrency |
|
|
435
|
+
| `SqliteViewLocker` | Prevents concurrent schema-migration rebuilds via SQLite row lock |
|
|
436
|
+
| `SqliteEventLocker` | Event deduplication and last-event checkpoint |
|
|
437
|
+
| `AbstractSqliteView` | Base class for relational (non-object) SQLite views with view and event locks embedded |
|
|
438
|
+
| `SqliteObjectView` | Composite view combining the above |
|
|
439
|
+
| `AbstractSqliteObjectProjection` | Base projection wired to `SqliteObjectView` |
|
|
433
440
|
|
|
434
|
-
|
|
441
|
+
See [src/sqlite](src/sqlite) for additional documentation, and [examples/sqlite](examples/sqlite/index.ts) for runnable project examples
|
|
435
442
|
|
|
436
|
-
|
|
437
|
-
1. A real projection inside a worker thread (handles events, mutates the view).
|
|
438
|
-
2. A proxy projection in the main thread (forwards calls to the worker and exposes the remote view).
|
|
443
|
+
#### MongoDB (`node-cqrs/mongodb`, peer dep: `mongodb`)
|
|
439
444
|
|
|
440
|
-
|
|
445
|
+
> **Experimental** - not yet validated in production. APIs may change in minor versions.
|
|
441
446
|
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
447
|
+
| Class | Role |
|
|
448
|
+
| ------------------------------- | --------------------------------------------------------------------------------- |
|
|
449
|
+
| `MongoObjectStorage` | Document storage with version-based optimistic concurrency |
|
|
450
|
+
| `MongoViewLocker` | Prevents concurrent schema-migration rebuilds; auto-prolongs lock via token + TTL |
|
|
451
|
+
| `MongoEventLocker` | Event deduplication and last-event checkpoint |
|
|
452
|
+
| `AbstractMongoView` | Base class combining `MongoViewLocker` + `MongoEventLocker` |
|
|
453
|
+
| `MongoObjectView` | Composite view combining the above |
|
|
454
|
+
| `AbstractMongoObjectProjection` | Base projection wired to `MongoObjectView` |
|
|
446
455
|
|
|
447
|
-
|
|
456
|
+
See [src/mongodb](src/mongodb) for additional documentation, and [examples/mongodb-views](examples/mongodb-views/index.ts) for runnable projection examples.
|
|
448
457
|
|
|
449
|
-
|
|
450
|
-
const { AbstractWorkerProjection } = require('node-cqrs/workers');
|
|
458
|
+
#### Redis (`node-cqrs/redis`, peer dep: `ioredis`)
|
|
451
459
|
|
|
452
|
-
|
|
453
|
-
counter = 0;
|
|
454
|
-
increment() { this.counter += 1; }
|
|
455
|
-
getCounter() { return this.counter; }
|
|
456
|
-
}
|
|
460
|
+
> **Experimental** - not yet validated in production. APIs may change in minor versions.
|
|
457
461
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
+
| Class | Role |
|
|
463
|
+
| ------------------------- | ----------------------------------------------------------------------------- |
|
|
464
|
+
| `RedisObjectStorage` | Key/value object storage backed by Redis hashes |
|
|
465
|
+
| `RedisViewLocker` | Prevents concurrent schema-migration rebuilds; auto-prolongs lock via PEXPIRE |
|
|
466
|
+
| `RedisEventLocker` | Event deduplication and last-event checkpoint |
|
|
467
|
+
| `RedisView` | Composite view combining the above |
|
|
468
|
+
| `AbstractRedisProjection` | Base projection wired to `RedisView` |
|
|
462
469
|
|
|
463
|
-
|
|
464
|
-
super({ view: new CounterView() });
|
|
465
|
-
}
|
|
470
|
+
See [src/redis](src/redis) for additional documentation, and [examples/redis](examples/redis/index.ts) for runnable projection examples.
|
|
466
471
|
|
|
467
|
-
|
|
468
|
-
this.view.increment();
|
|
469
|
-
}
|
|
470
|
-
}
|
|
472
|
+
### Message Buses
|
|
471
473
|
|
|
472
|
-
|
|
473
|
-
module.exports = CounterProjection;
|
|
474
|
-
```
|
|
474
|
+
How commands and events move between producers and consumers.
|
|
475
475
|
|
|
476
|
-
|
|
476
|
+
| Implementation | Import | Peer deps | Notes |
|
|
477
|
+
| -------------------- | -------------------- | --------- | ------------------------------------------------------------------------------------------------ |
|
|
478
|
+
| `InMemoryMessageBus` | `node-cqrs` | - | Single-process; used as both command and event bus ([example](examples/user-domain-ts/index.ts)) |
|
|
479
|
+
| `RabbitMqEventBus` | `node-cqrs/rabbitmq` | `amqplib` | Fanout delivery to all subscribers ([instructions](src/rabbitmq)) |
|
|
480
|
+
| `RabbitMqCommandBus` | `node-cqrs/rabbitmq` | `amqplib` | Point-to-point via durable queue ([instructions](src/rabbitmq)) |
|
|
477
481
|
|
|
478
|
-
|
|
479
|
-
const CounterProjection = require('./CounterProjection.cjs');
|
|
480
|
-
const { ContainerBuilder } = require('node-cqrs');
|
|
482
|
+
### Other
|
|
481
483
|
|
|
482
|
-
|
|
483
|
-
|
|
484
|
+
| Implementation | Import | Notes |
|
|
485
|
+
| -------------------------- | ------------------- | ------------------------------------------------------------- |
|
|
486
|
+
| `InMemorySnapshotStorage` | `node-cqrs` | Aggregate snapshot cache in memory, resets on process restart |
|
|
487
|
+
| `AbstractWorkerProjection` | `node-cqrs/workers` | Run projections in worker threads ([instructions](src/workers), [example](examples/workers-projection/index.cjs)) |
|
|
488
|
+
|
|
489
|
+
> **Experimental** — the Workers module is new and has not been validated in production. APIs may change in minor versions.
|
|
490
|
+
|
|
491
|
+
## OpenTelemetry
|
|
492
|
+
|
|
493
|
+
Optional distributed tracing via [OpenTelemetry](https://opentelemetry.io/). Requires `@opentelemetry/api` peer dependency. Register a `tracerFactory` in the container to enable automatic span creation across CQRS components:
|
|
494
|
+
|
|
495
|
+
```ts
|
|
496
|
+
import { trace } from '@opentelemetry/api';
|
|
484
497
|
|
|
485
|
-
|
|
486
|
-
await eventStore.dispatch([{ id: '1', type: 'somethingHappened', payload: {} }]);
|
|
487
|
-
const counter = await counterView.getCounter();
|
|
498
|
+
builder.register(() => (name: string) => trace.getTracer(`cqrs.${name}`)).as('tracerFactory');
|
|
488
499
|
```
|
|
489
500
|
|
|
490
|
-
|
|
491
|
-
If you need a custom proxy projection, you can still use `workerProxyFactory(...)` directly (advanced usage).
|
|
501
|
+
See [examples/telemetry/index.ts](examples/telemetry/index.ts) for a full working example.
|
|
492
502
|
|
|
493
503
|
|
|
494
504
|
## Examples
|
|
495
505
|
|
|
496
|
-
- [examples/user-domain
|
|
497
|
-
- [examples/user-domain
|
|
498
|
-
- [examples/user-domain
|
|
499
|
-
- [examples/
|
|
500
|
-
- [examples/sagas
|
|
506
|
+
- [examples/user-domain-framework-free](examples/user-domain-framework-free/index.ts) - minimal, no-framework CQRS/ES in one file
|
|
507
|
+
- [examples/user-domain-ts](examples/user-domain-ts) - TypeScript with DI container
|
|
508
|
+
- [examples/user-domain-cjs](examples/user-domain-cjs) - CommonJS
|
|
509
|
+
- [examples/redis](examples/redis/index.ts) - Redis-backed persistent projection
|
|
510
|
+
- [examples/sagas-simple](examples/sagas-simple/index.ts) - simple saga
|
|
511
|
+
- [examples/sagas-overlaps](examples/sagas-overlaps/index.ts) - overlapping sagas, multi-step flow
|
|
501
512
|
- [examples/browser](examples/browser) - browser smoke test
|
|
502
|
-
- [examples/workers
|
|
513
|
+
- [examples/workers-projection](examples/workers-projection) - worker thread projection
|
|
514
|
+
- [examples/mongodb-eventstore](examples/mongodb-eventstore/index.ts) - MongoDB event storage with DI container and manual wiring
|
|
515
|
+
- [examples/mongodb-views](examples/mongodb-views/index.ts) - MongoDB-backed projection views with object storage and locking
|
|
516
|
+
- [examples/telemetry](examples/telemetry/index.ts) - OpenTelemetry tracing with multiple exporters
|
|
503
517
|
|
|
504
518
|
TS examples can be run with NodeJS 24+ without transpiling.
|
|
@@ -3,8 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.AbstractProjection = void 0;
|
|
4
4
|
const Event_ts_1 = require("./Event.js");
|
|
5
5
|
const InMemoryView_ts_1 = require("./in-memory/InMemoryView.js");
|
|
6
|
-
const index_ts_1 = require("./
|
|
7
|
-
const index_ts_2 = require("./
|
|
6
|
+
const index_ts_1 = require("./telemetry/index.js");
|
|
7
|
+
const index_ts_2 = require("./interfaces/index.js");
|
|
8
|
+
const index_ts_3 = require("./utils/index.js");
|
|
8
9
|
/**
|
|
9
10
|
* Base class for Projection definition
|
|
10
11
|
*/
|
|
@@ -14,12 +15,14 @@ class AbstractProjection {
|
|
|
14
15
|
* If not overridden, event types will be inferred from handler methods defined on the Projection class.
|
|
15
16
|
*/
|
|
16
17
|
static get handles() {
|
|
17
|
-
return (0,
|
|
18
|
+
return (0, index_ts_3.getMessageHandlerNames)(this);
|
|
18
19
|
}
|
|
19
20
|
#view;
|
|
20
21
|
#viewLocker;
|
|
21
22
|
#eventLocker;
|
|
22
23
|
_logger;
|
|
24
|
+
#serviceName;
|
|
25
|
+
#tracer;
|
|
23
26
|
/**
|
|
24
27
|
* The default view associated with the projection.
|
|
25
28
|
* Can optionally implement IViewLocker and/or IEventLocker.
|
|
@@ -36,7 +39,7 @@ class AbstractProjection {
|
|
|
36
39
|
*/
|
|
37
40
|
get _viewLocker() {
|
|
38
41
|
if (this.#viewLocker === undefined)
|
|
39
|
-
this.#viewLocker = (0,
|
|
42
|
+
this.#viewLocker = (0, index_ts_2.isViewLocker)(this.view) ? this.view : null;
|
|
40
43
|
return this.#viewLocker;
|
|
41
44
|
}
|
|
42
45
|
set _viewLocker(value) {
|
|
@@ -47,19 +50,21 @@ class AbstractProjection {
|
|
|
47
50
|
*/
|
|
48
51
|
get _eventLocker() {
|
|
49
52
|
if (this.#eventLocker === undefined)
|
|
50
|
-
this.#eventLocker = (0,
|
|
53
|
+
this.#eventLocker = (0, index_ts_2.isEventLocker)(this.view) ? this.view : null;
|
|
51
54
|
return this.#eventLocker;
|
|
52
55
|
}
|
|
53
56
|
set _eventLocker(value) {
|
|
54
57
|
this.#eventLocker = value;
|
|
55
58
|
}
|
|
56
|
-
constructor({ view, viewLocker, eventLocker, logger } = {}) {
|
|
57
|
-
(0,
|
|
59
|
+
constructor({ view, viewLocker, eventLocker, tracerFactory, logger } = {}) {
|
|
60
|
+
(0, index_ts_3.validateHandlers)(this);
|
|
58
61
|
this.#view = view;
|
|
59
62
|
this.#viewLocker = viewLocker;
|
|
60
63
|
this.#eventLocker = eventLocker;
|
|
64
|
+
this.#serviceName = (0, index_ts_3.getClassName)(this);
|
|
65
|
+
this.#tracer = tracerFactory?.(this.#serviceName);
|
|
61
66
|
this._logger = logger && 'child' in logger ?
|
|
62
|
-
logger.child({ service: (0,
|
|
67
|
+
logger.child({ service: (0, index_ts_3.getClassName)(this) }) :
|
|
63
68
|
logger;
|
|
64
69
|
}
|
|
65
70
|
/**
|
|
@@ -67,7 +72,7 @@ class AbstractProjection {
|
|
|
67
72
|
* and restore view state from not yet projected events
|
|
68
73
|
*/
|
|
69
74
|
subscribe(eventStore) {
|
|
70
|
-
(0,
|
|
75
|
+
(0, index_ts_3.subscribe)(eventStore, this, {
|
|
71
76
|
masterHandler: this.project
|
|
72
77
|
});
|
|
73
78
|
}
|
|
@@ -78,7 +83,17 @@ class AbstractProjection {
|
|
|
78
83
|
await this._viewLocker.once('ready');
|
|
79
84
|
this._logger?.debug(`view is ready, processing ${(0, Event_ts_1.describe)(event)}`);
|
|
80
85
|
}
|
|
81
|
-
|
|
86
|
+
const span = this.#tracer?.startSpan(`${this.#serviceName}.project ${event.type}`, (0, index_ts_1.spanAttributes)('projection', event, ['type', 'aggregateId']), (0, index_ts_1.spanContext)(meta));
|
|
87
|
+
try {
|
|
88
|
+
await this._project(event, meta);
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
(0, index_ts_1.recordSpanError)(span, error);
|
|
92
|
+
throw error;
|
|
93
|
+
}
|
|
94
|
+
finally {
|
|
95
|
+
span?.end();
|
|
96
|
+
}
|
|
82
97
|
}
|
|
83
98
|
/**
|
|
84
99
|
* Determines whether an event should be recorded as the last projected event (restore checkpoint).
|
|
@@ -90,7 +105,7 @@ class AbstractProjection {
|
|
|
90
105
|
}
|
|
91
106
|
/** Pass event to projection event handler, without awaiting for restore operation to complete */
|
|
92
107
|
async _project(event, meta) {
|
|
93
|
-
const handler = (0,
|
|
108
|
+
const handler = (0, index_ts_3.getHandler)(this, event.type);
|
|
94
109
|
if (!handler)
|
|
95
110
|
throw new Error(`'${event.type}' handler is not defined or not a function`);
|
|
96
111
|
if (this._eventLocker) {
|
|
@@ -112,15 +127,25 @@ class AbstractProjection {
|
|
|
112
127
|
* won't be performed by another projection instance.
|
|
113
128
|
* */
|
|
114
129
|
async restore(eventStore) {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
this.
|
|
130
|
+
const span = this.#tracer?.startSpan(`${this.#serviceName}.restore`);
|
|
131
|
+
try {
|
|
132
|
+
if (this._viewLocker)
|
|
133
|
+
await this._viewLocker.lock();
|
|
134
|
+
await this._restore(eventStore);
|
|
135
|
+
if (this._viewLocker)
|
|
136
|
+
this._viewLocker.unlock();
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
(0, index_ts_1.recordSpanError)(span, error);
|
|
140
|
+
throw error;
|
|
141
|
+
}
|
|
142
|
+
finally {
|
|
143
|
+
span?.end();
|
|
144
|
+
}
|
|
120
145
|
}
|
|
121
146
|
/** Restore view state from not-yet-projected events */
|
|
122
147
|
async _restore(eventStore) {
|
|
123
|
-
(0,
|
|
148
|
+
(0, index_ts_3.assertFunction)(eventStore?.getEventsByTypes, 'eventStore.getEventsByTypes');
|
|
124
149
|
let lastEvent;
|
|
125
150
|
if (this._eventLocker) {
|
|
126
151
|
this._logger?.debug('retrieving last event projected');
|
|
@@ -154,7 +179,7 @@ class AbstractProjection {
|
|
|
154
179
|
_onRestoringError(error, event) {
|
|
155
180
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
156
181
|
this._logger?.error(`view restoring has failed (view remains locked): ${errorMessage}`, {
|
|
157
|
-
service: (0,
|
|
182
|
+
service: (0, index_ts_3.getClassName)(this),
|
|
158
183
|
event,
|
|
159
184
|
error
|
|
160
185
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AbstractProjection.js","sourceRoot":"","sources":["../../src/AbstractProjection.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"AbstractProjection.js","sourceRoot":"","sources":["../../src/AbstractProjection.ts"],"names":[],"mappings":"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"}
|