python-cqrs 4.13.0__tar.gz → 4.15.0__tar.gz

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.
Files changed (105) hide show
  1. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/PKG-INFO +76 -26
  2. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/README.md +68 -25
  3. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/pyproject.toml +6 -1
  4. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/__init__.py +27 -1
  5. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/adapters/kafka.py +27 -6
  6. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/adapters/protocol.py +7 -0
  7. python_cqrs-4.15.0/src/cqrs/container/__init__.py +18 -0
  8. python_cqrs-4.15.0/src/cqrs/container/di.py +75 -0
  9. python_cqrs-4.15.0/src/cqrs/container/dishka.py +48 -0
  10. python_cqrs-4.15.0/src/cqrs/container/protocol.py +43 -0
  11. python_cqrs-4.15.0/src/cqrs/container/scope.py +321 -0
  12. python_cqrs-4.15.0/src/cqrs/deserializers/__init__.py +11 -0
  13. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/deserializers/exceptions.py +16 -0
  14. python_cqrs-4.15.0/src/cqrs/deserializers/protobuf.py +51 -0
  15. python_cqrs-4.15.0/src/cqrs/dispatcher/event.py +111 -0
  16. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/dispatcher/request.py +67 -46
  17. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/dispatcher/saga.py +8 -4
  18. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/dispatcher/streaming.py +70 -47
  19. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/events/bootstrap.py +9 -0
  20. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/events/event_emitter.py +106 -51
  21. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/mediator.py +114 -10
  22. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/message_brokers/amqp.py +10 -2
  23. python_cqrs-4.15.0/src/cqrs/message_brokers/kafka.py +45 -0
  24. python_cqrs-4.15.0/src/cqrs/message_brokers/protocol.py +74 -0
  25. python_cqrs-4.15.0/src/cqrs/outbox/map.py +103 -0
  26. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/outbox/mock.py +18 -2
  27. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/outbox/repository.py +4 -0
  28. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/outbox/sqlalchemy.py +39 -11
  29. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/producer.py +8 -0
  30. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/requests/bootstrap.py +51 -50
  31. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/saga/bootstrap.py +28 -32
  32. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/saga/compensation.py +77 -15
  33. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/saga/execution.py +141 -125
  34. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/saga/recovery.py +29 -10
  35. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/saga/saga.py +49 -19
  36. python_cqrs-4.15.0/src/cqrs/serializers/__init__.py +12 -0
  37. python_cqrs-4.15.0/src/cqrs/serializers/default.py +86 -0
  38. python_cqrs-4.15.0/src/cqrs/serializers/json.py +22 -0
  39. python_cqrs-4.15.0/src/cqrs/serializers/protobuf.py +48 -0
  40. python_cqrs-4.15.0/src/cqrs/serializers/protocol.py +21 -0
  41. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/python_cqrs.egg-info/PKG-INFO +76 -26
  42. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/python_cqrs.egg-info/SOURCES.txt +6 -0
  43. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/python_cqrs.egg-info/requires.txt +9 -0
  44. python_cqrs-4.13.0/src/cqrs/container/__init__.py +0 -3
  45. python_cqrs-4.13.0/src/cqrs/container/di.py +0 -26
  46. python_cqrs-4.13.0/src/cqrs/container/protocol.py +0 -20
  47. python_cqrs-4.13.0/src/cqrs/deserializers/__init__.py +0 -8
  48. python_cqrs-4.13.0/src/cqrs/dispatcher/event.py +0 -96
  49. python_cqrs-4.13.0/src/cqrs/message_brokers/kafka.py +0 -18
  50. python_cqrs-4.13.0/src/cqrs/message_brokers/protocol.py +0 -44
  51. python_cqrs-4.13.0/src/cqrs/outbox/map.py +0 -24
  52. python_cqrs-4.13.0/src/cqrs/serializers/__init__.py +0 -3
  53. python_cqrs-4.13.0/src/cqrs/serializers/default.py +0 -24
  54. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/LICENSE +0 -0
  55. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/setup.cfg +0 -0
  56. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/adapters/__init__.py +0 -0
  57. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/adapters/amqp.py +0 -0
  58. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/adapters/circuit_breaker.py +0 -0
  59. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/circuit_breaker.py +0 -0
  60. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/compressors/__init__.py +0 -0
  61. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/compressors/protocol.py +0 -0
  62. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/compressors/zlib.py +0 -0
  63. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/container/dependency_injector.py +0 -0
  64. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/deserializers/json.py +0 -0
  65. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/dispatcher/__init__.py +0 -0
  66. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/dispatcher/exceptions.py +0 -0
  67. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/dispatcher/models.py +0 -0
  68. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/events/__init__.py +0 -0
  69. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/events/event.py +0 -0
  70. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/events/event_handler.py +0 -0
  71. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/events/event_processor.py +0 -0
  72. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/events/fallback.py +0 -0
  73. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/events/map.py +0 -0
  74. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/generic_utils.py +0 -0
  75. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/message_brokers/__init__.py +0 -0
  76. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/message_brokers/devnull.py +0 -0
  77. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/middlewares/__init__.py +0 -0
  78. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/middlewares/base.py +0 -0
  79. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/middlewares/logging.py +0 -0
  80. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/outbox/__init__.py +0 -0
  81. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/requests/__init__.py +0 -0
  82. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/requests/cor_request_handler.py +0 -0
  83. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/requests/fallback.py +0 -0
  84. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/requests/map.py +0 -0
  85. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/requests/mermaid.py +0 -0
  86. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/requests/request.py +0 -0
  87. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/requests/request_handler.py +0 -0
  88. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/response.py +0 -0
  89. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/saga/__init__.py +0 -0
  90. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/saga/circuit_breaker.py +0 -0
  91. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/saga/fallback.py +0 -0
  92. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/saga/mermaid.py +0 -0
  93. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/saga/models.py +0 -0
  94. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/saga/step.py +0 -0
  95. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/saga/storage/__init__.py +0 -0
  96. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/saga/storage/enums.py +0 -0
  97. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/saga/storage/memory.py +0 -0
  98. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/saga/storage/models.py +0 -0
  99. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/saga/storage/protocol.py +0 -0
  100. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/saga/storage/sqlalchemy.py +0 -0
  101. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/saga/validation.py +0 -0
  102. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/sqlalchemy_types.py +0 -0
  103. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/cqrs/types.py +0 -0
  104. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/python_cqrs.egg-info/dependency_links.txt +0 -0
  105. {python_cqrs-4.13.0 → python_cqrs-4.15.0}/src/python_cqrs.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-cqrs
3
- Version: 4.13.0
3
+ Version: 4.15.0
4
4
  Summary: Event-Driven Architecture Framework for Distributed Systems
5
5
  Author-email: Vadim Kozyrevskiy <vadikko2@mail.ru>, Dmitry Kutlubaev <kutlubaev00@mail.ru>
6
6
  Maintainer-email: Vadim Kozyrevskiy <vadikko2@mail.ru>
@@ -48,6 +48,8 @@ Requires-Dist: asyncmy==0.2.9; extra == "dev"
48
48
  Requires-Dist: asyncpg>=0.29.0; extra == "dev"
49
49
  Requires-Dist: redis>=5.0.0; extra == "dev"
50
50
  Requires-Dist: aiobreaker>=0.3.0; extra == "dev"
51
+ Requires-Dist: dishka>=1.0; extra == "dev"
52
+ Requires-Dist: protobuf>=4.25.8; extra == "dev"
51
53
  Provides-Extra: examples
52
54
  Requires-Dist: fastapi==0.109.*; extra == "examples"
53
55
  Requires-Dist: faststream[kafka]==0.5.28; extra == "examples"
@@ -56,13 +58,18 @@ Requires-Dist: uvicorn==0.32.0; extra == "examples"
56
58
  Requires-Dist: aiohttp==3.14.3; extra == "examples"
57
59
  Requires-Dist: protobuf>=4.25.8; extra == "examples"
58
60
  Requires-Dist: aiosqlite>=0.20.0; extra == "examples"
61
+ Requires-Dist: dishka>=1.0; extra == "examples"
59
62
  Provides-Extra: kafka
60
63
  Requires-Dist: aiokafka==0.10.0; extra == "kafka"
61
64
  Requires-Dist: retry-async==0.1.*; extra == "kafka"
65
+ Provides-Extra: protobuf
66
+ Requires-Dist: protobuf>=4.25.8; extra == "protobuf"
62
67
  Provides-Extra: rabbit
63
68
  Requires-Dist: aio-pika==9.3.0; extra == "rabbit"
64
69
  Provides-Extra: sqlalchemy
65
70
  Requires-Dist: sqlalchemy[asyncio]==2.0.*; extra == "sqlalchemy"
71
+ Provides-Extra: dishka
72
+ Requires-Dist: dishka>=1.0; extra == "dishka"
66
73
  Dynamic: license-file
67
74
 
68
75
  <div align="center">
@@ -117,6 +124,7 @@ Dynamic: license-file
117
124
  - [Request Handlers](#request-handlers)
118
125
  - [Mapping](#mapping)
119
126
  - [DI container](#di-container)
127
+ - [Scoped dependencies](#scoped-dependencies)
120
128
  - [Bootstrap](#bootstrap)
121
129
  - [Saga Pattern](#saga-pattern)
122
130
  - [Producing Notification Events](#producing-notification-events)
@@ -264,7 +272,7 @@ class CustomResponse(cqrs.IResponse):
264
272
  return cls(result=kwargs["result"], status=kwargs["status"])
265
273
  ```
266
274
 
267
- A complete example can be found in [request_response_types.py](https://github.com/vadikko2/python-cqrs/blob/master/examples/request_response_types.py)
275
+ A complete example can be found in [request_response_types.py](https://github.com/vadikko2/python-cqrs/blob/master/examples/events/request_response_types.py)
268
276
 
269
277
  ## Request Handlers
270
278
 
@@ -297,7 +305,7 @@ class JoinMeetingCommandHandler(RequestHandler[JoinMeetingCommand, None]):
297
305
  ```
298
306
 
299
307
  A complete example can be found in
300
- the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/request_handler.py)
308
+ the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/events/request_handler.py)
301
309
 
302
310
  ### Query handler
303
311
 
@@ -327,7 +335,7 @@ class ReadMeetingQueryHandler(RequestHandler[ReadMeetingQuery, ReadMeetingQueryR
327
335
  ```
328
336
 
329
337
  A complete example can be found in
330
- the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/request_handler.py)
338
+ the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/events/request_handler.py)
331
339
 
332
340
  ### Streaming Request Handler
333
341
 
@@ -363,7 +371,7 @@ class ProcessFilesCommandHandler(StreamingRequestHandler[ProcessFilesCommand, Fi
363
371
  ```
364
372
 
365
373
  A complete example can be found in
366
- the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/streaming_handler_parallel_events.py)
374
+ the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/streaming/streaming_handler_parallel_events.py)
367
375
 
368
376
  ### Chain of Responsibility Request Handler
369
377
 
@@ -426,7 +434,7 @@ def payment_mapper(mapper: cqrs.RequestMap) -> None:
426
434
  ```
427
435
 
428
436
  A complete example can be found in
429
- the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/cor_request_handler.py)
437
+ the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/cor/cor_request_handler.py)
430
438
 
431
439
  #### Mermaid Diagram Generation
432
440
 
@@ -446,7 +454,7 @@ sequence_diagram = generator.sequence()
446
454
  class_diagram = generator.class_diagram()
447
455
  ```
448
456
 
449
- Complete example: [CoR Mermaid Diagrams](https://github.com/vadikko2/python-cqrs/blob/master/examples/cor_mermaid.py)
457
+ Complete example: [CoR Mermaid Diagrams](https://github.com/vadikko2/python-cqrs/blob/master/examples/cor/cor_mermaid.py)
450
458
 
451
459
  ## Mapping
452
460
 
@@ -507,7 +515,11 @@ def saga_mapper(mapper: cqrs.SagaMap) -> None:
507
515
  Use the following example to set up dependency injection in your command, query and event handlers. This will make
508
516
  dependency management simpler.
509
517
 
510
- The package supports two DI container libraries:
518
+ The package supports three DI container libraries:
519
+
520
+ - [`di`](#di-library) (default)
521
+ - [`dependency-injector`](#dependency-injector-library)
522
+ - [dishka](https://github.com/reagento/dishka) via `DishkaCQRSContainer` (`pip install python-cqrs[dishka]`)
511
523
 
512
524
  ### di library
513
525
 
@@ -536,7 +548,7 @@ def setup_di() -> di.Container:
536
548
  ```
537
549
 
538
550
  A complete example can be found in
539
- the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/dependency_injection.py)
551
+ the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/di/di_basic.py)
540
552
 
541
553
  ### dependency-injector library
542
554
 
@@ -552,7 +564,8 @@ class ApplicationContainer(containers.DeclarativeContainer):
552
564
  service = providers.Factory(ServiceImplementation)
553
565
 
554
566
  # Create CQRS container adapter
555
- cqrs_container = DependencyInjectorCQRSContainer(ApplicationContainer())
567
+ cqrs_container = DependencyInjectorCQRSContainer()
568
+ cqrs_container.attach_external_container(ApplicationContainer())
556
569
 
557
570
  # Use with bootstrap
558
571
  mediator = bootstrap.bootstrap(
@@ -563,8 +576,32 @@ mediator = bootstrap.bootstrap(
563
576
  ```
564
577
 
565
578
  Complete examples can be found in:
566
- - [Simple example](https://github.com/vadikko2/python-cqrs/blob/master/examples/dependency_injector_integration_simple_example.py)
567
- - [Practical example with FastAPI](https://github.com/vadikko2/python-cqrs/blob/master/examples/dependency_injector_integration_practical_example.py)
579
+ - [Simple example](https://github.com/vadikko2/python-cqrs/blob/master/examples/di/dependency_injector_simple.py)
580
+ - [Practical example with FastAPI](https://github.com/vadikko2/python-cqrs/blob/master/examples/di/dependency_injector_practical.py)
581
+
582
+ ### Scoped dependencies
583
+
584
+ By default, the container opens and closes a scope **inside** `resolve()`. A generator such as `async def session() -> AsyncIterator[AsyncSession]` therefore finishes **before** `handle`, which is why people inject factories.
585
+
586
+ Pass `scope_strategy=ScopeStrategy.SEND` and that session lives until `mediator.send()` returns — including domain-event handlers that run afterwards.
587
+
588
+ If you do not use generator providers, leave the default `ScopeStrategy.NONE` and change nothing.
589
+
590
+ ```python
591
+ mediator = bootstrap.bootstrap(
592
+ di_container=container,
593
+ commands_mapper=commands_mapper,
594
+ scope_strategy=cqrs.ScopeStrategy.SEND,
595
+ )
596
+ ```
597
+
598
+ Copy-paste SQLAlchemy session + outbox under one SEND scope: the [Tutorial](https://mkdocs.python-cqrs.dev/scoped_dependencies/tutorial/) (`examples/di/scoped_dependencies_sqlalchemy.py`). Minimal `di` UoW: `examples/di/scoped_dependencies_di.py`.
599
+
600
+ - **SEND** — one UoW per `send()` (command, fallback, and domain events).
601
+ - **HANDLER** — a fresh UoW per handler, including fallback (the primary rolls back first).
602
+ - **NONE** — legacy one-shot resolve; the default.
603
+
604
+ `di`'s `scope="request"` is provider lifetime, not a CQRS scope — that is only `scope_strategy=`. Docs: [Scoped Dependencies](https://mkdocs.python-cqrs.dev/scoped_dependencies/).
568
605
 
569
606
  ## Bootstrap
570
607
 
@@ -729,6 +766,7 @@ await recover_saga(
729
766
  context_builder=OrderContext,
730
767
  container=di_container, # Same container used in bootstrap
731
768
  storage=storage,
769
+ scope_strategy=cqrs.ScopeStrategy.SEND, # Match the original run
732
770
  )
733
771
 
734
772
  # Access execution history (SagaLog) for monitoring and debugging
@@ -761,7 +799,7 @@ sequence_diagram = generator.sequence()
761
799
  class_diagram = generator.class_diagram()
762
800
  ```
763
801
 
764
- Complete example: [Saga Mermaid Diagrams](https://github.com/vadikko2/python-cqrs/blob/master/examples/saga_mermaid.py)
802
+ Complete example: [Saga Mermaid Diagrams](https://github.com/vadikko2/python-cqrs/blob/master/examples/saga/saga_mermaid.py)
765
803
 
766
804
  ## Producing Notification Events
767
805
 
@@ -801,7 +839,7 @@ class JoinMeetingCommandHandler(cqrs.RequestHandler[JoinMeetingCommand, None]):
801
839
  ```
802
840
 
803
841
  A complete example can be found in
804
- the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/event_producing.py)
842
+ the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/events/event_producing.py)
805
843
 
806
844
  After processing the command/request, if there are any Notification/ECST events,
807
845
  the EventEmitter is invoked to produce the events via the message broker.
@@ -872,10 +910,10 @@ class JoinMeetingCommandHandler(cqrs.RequestHandler[JoinMeetingCommand, None]):
872
910
  ```
873
911
 
874
912
  A complete example can be found in
875
- the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/save_events_into_outbox.py)
913
+ the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/outbox/save_events_into_outbox.py)
876
914
 
877
915
  A runnable FastAPI flow (route → command → transactional outbox → publisher stub) is in
878
- [fastapi_outbox.py](https://github.com/vadikko2/python-cqrs/blob/master/examples/fastapi_outbox.py)
916
+ [fastapi_outbox.py](https://github.com/vadikko2/python-cqrs/blob/master/examples/outbox/fastapi_outbox.py)
879
917
 
880
918
  > [!TIP]
881
919
  > The Outbox table is named `outbox` by default. To rename it, or to attach the model to your own declarative
@@ -888,9 +926,10 @@ A runnable FastAPI flow (route → command → transactional outbox → publishe
888
926
  > [Database Support](https://mkdocs.python-cqrs.dev/outbox/databases/) docs for the DDL, the Alembic recipe and
889
927
  > how to register a native type for your own database.
890
928
  > [!TIP]
891
- > If you use the protobuf events you should specify `OutboxedEventRepository`
892
- > by [protobuf serialize](https://github.com/vadikko2/python-cqrs/blob/master/src/cqrs/serializers/protobuf.py). A complete example can be found in
893
- the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/save_proto_events_into_outbox.py)
929
+ > For Protobuf events, implement `proto()` / `from_proto()` and register a
930
+ > `ProtobufEventSerializer` on an `OutboxedEventMap`. JSON stays the default —
931
+ > see [Protobuf messaging](#protobuf-messaging) and the full guide:
932
+ > [Protobuf Integration](https://mkdocs.python-cqrs.dev/protobuf/).
894
933
 
895
934
  ## Producing Events from Outbox to Kafka
896
935
 
@@ -929,7 +968,7 @@ async with session_factory() as session:
929
968
  ```
930
969
 
931
970
  A complete example can be found in
932
- the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/kafka_outboxed_event_producing.py)
971
+ the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/outbox/kafka_outboxed_event_producing.py)
933
972
 
934
973
  ## Transaction log tailing
935
974
 
@@ -972,7 +1011,7 @@ class UserJoinedEventHandler(cqrs.EventHandler[UserJoined]):
972
1011
  ```
973
1012
 
974
1013
  A complete example can be found in
975
- the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/domain_event_handler.py)
1014
+ the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/events/domain_event_handler.py)
976
1015
 
977
1016
  ### Parallel Event Processing
978
1017
 
@@ -1003,6 +1042,7 @@ mediator = bootstrap.bootstrap_streaming(
1003
1042
  > - Set `max_concurrent_event_handlers` to limit the number of simultaneously running event handlers
1004
1043
  > - Set `concurrent_event_handle_enable=False` to disable parallel processing and process events sequentially
1005
1044
  > - The default value for `max_concurrent_event_handlers` is `10` for `StreamingRequestMediator` and `1` for `RequestMediator`
1045
+ > - `ScopeStrategy.SEND` always uses sequential events (`concurrent=None` → `False`). Passing `concurrent_event_handle_enable=True` with `SEND` raises `ValueError`; use `HANDLER` or `NONE` for parallel events.
1006
1046
 
1007
1047
  ## Integration with presentation layers
1008
1048
 
@@ -1040,10 +1080,10 @@ async def join_metting(
1040
1080
  ```
1041
1081
 
1042
1082
  A complete example can be found in
1043
- the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/fastapi_integration.py)
1083
+ the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/events/fastapi_integration.py)
1044
1084
 
1045
1085
  End-to-end command + outbox sample (business row and outbox event in one transaction, plus a publisher stub):
1046
- [fastapi_outbox.py](https://github.com/vadikko2/python-cqrs/blob/master/examples/fastapi_outbox.py)
1086
+ [fastapi_outbox.py](https://github.com/vadikko2/python-cqrs/blob/master/examples/outbox/fastapi_outbox.py)
1047
1087
 
1048
1088
  ### Kafka events consuming
1049
1089
 
@@ -1091,7 +1131,7 @@ async def hello_world_event_handler(
1091
1131
  ```
1092
1132
 
1093
1133
  A complete example can be found in
1094
- the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/kafka_event_consuming.py)
1134
+ the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/events/kafka_event_consuming.py)
1095
1135
 
1096
1136
  ### FastAPI SSE Streaming
1097
1137
 
@@ -1112,7 +1152,7 @@ def streaming_mediator_factory() -> cqrs.StreamingRequestMediator:
1112
1152
  domain_events_mapper=domain_events_mapper,
1113
1153
  message_broker=broker,
1114
1154
  max_concurrent_event_handlers=3,
1115
- concurrent_event_handle_enable=True,
1155
+ concurrent_event_handle_enable=True, # HANDLER/NONE only; SEND forbids this
1116
1156
  )
1117
1157
 
1118
1158
  @app.post("/process-files")
@@ -1139,7 +1179,9 @@ async def process_files_stream(
1139
1179
  ```
1140
1180
 
1141
1181
  A complete example can be found in
1142
- the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/fastapi_sse_streaming.py)
1182
+ the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/streaming/fastapi_sse_streaming.py)
1183
+
1184
+ If the client disconnects, close the iterator (`aclose()` / `async with aclosing(...)`) so a `SEND` UoW is not held until GC.
1143
1185
 
1144
1186
  ## Protobuf messaging
1145
1187
 
@@ -1189,6 +1231,14 @@ class UserJoinedNotificationEvent(cqrs.NotificationEvent[UserJoinedPayload]):
1189
1231
  )
1190
1232
  ```
1191
1233
 
1234
+ JSON remains the default. Opt-in Protobuf wiring (`ProtobufEventSerializer` on an
1235
+ `OutboxedEventMap`, `Message.payload_bytes`, consume via `ProtobufDeserializer`) is
1236
+ documented in the full guide:
1237
+ [Protobuf Integration](https://mkdocs.python-cqrs.dev/protobuf/).
1238
+ Runnable example:
1239
+ [protobuf_outbox.py](https://github.com/vadikko2/python-cqrs/blob/master/examples/outbox/protobuf_outbox.py)
1240
+ (`pip install "python-cqrs[protobuf]"`).
1241
+
1192
1242
  ## Contributing
1193
1243
 
1194
1244
  Contributions are welcome. To develop locally:
@@ -50,6 +50,7 @@
50
50
  - [Request Handlers](#request-handlers)
51
51
  - [Mapping](#mapping)
52
52
  - [DI container](#di-container)
53
+ - [Scoped dependencies](#scoped-dependencies)
53
54
  - [Bootstrap](#bootstrap)
54
55
  - [Saga Pattern](#saga-pattern)
55
56
  - [Producing Notification Events](#producing-notification-events)
@@ -197,7 +198,7 @@ class CustomResponse(cqrs.IResponse):
197
198
  return cls(result=kwargs["result"], status=kwargs["status"])
198
199
  ```
199
200
 
200
- A complete example can be found in [request_response_types.py](https://github.com/vadikko2/python-cqrs/blob/master/examples/request_response_types.py)
201
+ A complete example can be found in [request_response_types.py](https://github.com/vadikko2/python-cqrs/blob/master/examples/events/request_response_types.py)
201
202
 
202
203
  ## Request Handlers
203
204
 
@@ -230,7 +231,7 @@ class JoinMeetingCommandHandler(RequestHandler[JoinMeetingCommand, None]):
230
231
  ```
231
232
 
232
233
  A complete example can be found in
233
- the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/request_handler.py)
234
+ the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/events/request_handler.py)
234
235
 
235
236
  ### Query handler
236
237
 
@@ -260,7 +261,7 @@ class ReadMeetingQueryHandler(RequestHandler[ReadMeetingQuery, ReadMeetingQueryR
260
261
  ```
261
262
 
262
263
  A complete example can be found in
263
- the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/request_handler.py)
264
+ the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/events/request_handler.py)
264
265
 
265
266
  ### Streaming Request Handler
266
267
 
@@ -296,7 +297,7 @@ class ProcessFilesCommandHandler(StreamingRequestHandler[ProcessFilesCommand, Fi
296
297
  ```
297
298
 
298
299
  A complete example can be found in
299
- the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/streaming_handler_parallel_events.py)
300
+ the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/streaming/streaming_handler_parallel_events.py)
300
301
 
301
302
  ### Chain of Responsibility Request Handler
302
303
 
@@ -359,7 +360,7 @@ def payment_mapper(mapper: cqrs.RequestMap) -> None:
359
360
  ```
360
361
 
361
362
  A complete example can be found in
362
- the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/cor_request_handler.py)
363
+ the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/cor/cor_request_handler.py)
363
364
 
364
365
  #### Mermaid Diagram Generation
365
366
 
@@ -379,7 +380,7 @@ sequence_diagram = generator.sequence()
379
380
  class_diagram = generator.class_diagram()
380
381
  ```
381
382
 
382
- Complete example: [CoR Mermaid Diagrams](https://github.com/vadikko2/python-cqrs/blob/master/examples/cor_mermaid.py)
383
+ Complete example: [CoR Mermaid Diagrams](https://github.com/vadikko2/python-cqrs/blob/master/examples/cor/cor_mermaid.py)
383
384
 
384
385
  ## Mapping
385
386
 
@@ -440,7 +441,11 @@ def saga_mapper(mapper: cqrs.SagaMap) -> None:
440
441
  Use the following example to set up dependency injection in your command, query and event handlers. This will make
441
442
  dependency management simpler.
442
443
 
443
- The package supports two DI container libraries:
444
+ The package supports three DI container libraries:
445
+
446
+ - [`di`](#di-library) (default)
447
+ - [`dependency-injector`](#dependency-injector-library)
448
+ - [dishka](https://github.com/reagento/dishka) via `DishkaCQRSContainer` (`pip install python-cqrs[dishka]`)
444
449
 
445
450
  ### di library
446
451
 
@@ -469,7 +474,7 @@ def setup_di() -> di.Container:
469
474
  ```
470
475
 
471
476
  A complete example can be found in
472
- the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/dependency_injection.py)
477
+ the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/di/di_basic.py)
473
478
 
474
479
  ### dependency-injector library
475
480
 
@@ -485,7 +490,8 @@ class ApplicationContainer(containers.DeclarativeContainer):
485
490
  service = providers.Factory(ServiceImplementation)
486
491
 
487
492
  # Create CQRS container adapter
488
- cqrs_container = DependencyInjectorCQRSContainer(ApplicationContainer())
493
+ cqrs_container = DependencyInjectorCQRSContainer()
494
+ cqrs_container.attach_external_container(ApplicationContainer())
489
495
 
490
496
  # Use with bootstrap
491
497
  mediator = bootstrap.bootstrap(
@@ -496,8 +502,32 @@ mediator = bootstrap.bootstrap(
496
502
  ```
497
503
 
498
504
  Complete examples can be found in:
499
- - [Simple example](https://github.com/vadikko2/python-cqrs/blob/master/examples/dependency_injector_integration_simple_example.py)
500
- - [Practical example with FastAPI](https://github.com/vadikko2/python-cqrs/blob/master/examples/dependency_injector_integration_practical_example.py)
505
+ - [Simple example](https://github.com/vadikko2/python-cqrs/blob/master/examples/di/dependency_injector_simple.py)
506
+ - [Practical example with FastAPI](https://github.com/vadikko2/python-cqrs/blob/master/examples/di/dependency_injector_practical.py)
507
+
508
+ ### Scoped dependencies
509
+
510
+ By default, the container opens and closes a scope **inside** `resolve()`. A generator such as `async def session() -> AsyncIterator[AsyncSession]` therefore finishes **before** `handle`, which is why people inject factories.
511
+
512
+ Pass `scope_strategy=ScopeStrategy.SEND` and that session lives until `mediator.send()` returns — including domain-event handlers that run afterwards.
513
+
514
+ If you do not use generator providers, leave the default `ScopeStrategy.NONE` and change nothing.
515
+
516
+ ```python
517
+ mediator = bootstrap.bootstrap(
518
+ di_container=container,
519
+ commands_mapper=commands_mapper,
520
+ scope_strategy=cqrs.ScopeStrategy.SEND,
521
+ )
522
+ ```
523
+
524
+ Copy-paste SQLAlchemy session + outbox under one SEND scope: the [Tutorial](https://mkdocs.python-cqrs.dev/scoped_dependencies/tutorial/) (`examples/di/scoped_dependencies_sqlalchemy.py`). Minimal `di` UoW: `examples/di/scoped_dependencies_di.py`.
525
+
526
+ - **SEND** — one UoW per `send()` (command, fallback, and domain events).
527
+ - **HANDLER** — a fresh UoW per handler, including fallback (the primary rolls back first).
528
+ - **NONE** — legacy one-shot resolve; the default.
529
+
530
+ `di`'s `scope="request"` is provider lifetime, not a CQRS scope — that is only `scope_strategy=`. Docs: [Scoped Dependencies](https://mkdocs.python-cqrs.dev/scoped_dependencies/).
501
531
 
502
532
  ## Bootstrap
503
533
 
@@ -662,6 +692,7 @@ await recover_saga(
662
692
  context_builder=OrderContext,
663
693
  container=di_container, # Same container used in bootstrap
664
694
  storage=storage,
695
+ scope_strategy=cqrs.ScopeStrategy.SEND, # Match the original run
665
696
  )
666
697
 
667
698
  # Access execution history (SagaLog) for monitoring and debugging
@@ -694,7 +725,7 @@ sequence_diagram = generator.sequence()
694
725
  class_diagram = generator.class_diagram()
695
726
  ```
696
727
 
697
- Complete example: [Saga Mermaid Diagrams](https://github.com/vadikko2/python-cqrs/blob/master/examples/saga_mermaid.py)
728
+ Complete example: [Saga Mermaid Diagrams](https://github.com/vadikko2/python-cqrs/blob/master/examples/saga/saga_mermaid.py)
698
729
 
699
730
  ## Producing Notification Events
700
731
 
@@ -734,7 +765,7 @@ class JoinMeetingCommandHandler(cqrs.RequestHandler[JoinMeetingCommand, None]):
734
765
  ```
735
766
 
736
767
  A complete example can be found in
737
- the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/event_producing.py)
768
+ the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/events/event_producing.py)
738
769
 
739
770
  After processing the command/request, if there are any Notification/ECST events,
740
771
  the EventEmitter is invoked to produce the events via the message broker.
@@ -805,10 +836,10 @@ class JoinMeetingCommandHandler(cqrs.RequestHandler[JoinMeetingCommand, None]):
805
836
  ```
806
837
 
807
838
  A complete example can be found in
808
- the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/save_events_into_outbox.py)
839
+ the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/outbox/save_events_into_outbox.py)
809
840
 
810
841
  A runnable FastAPI flow (route → command → transactional outbox → publisher stub) is in
811
- [fastapi_outbox.py](https://github.com/vadikko2/python-cqrs/blob/master/examples/fastapi_outbox.py)
842
+ [fastapi_outbox.py](https://github.com/vadikko2/python-cqrs/blob/master/examples/outbox/fastapi_outbox.py)
812
843
 
813
844
  > [!TIP]
814
845
  > The Outbox table is named `outbox` by default. To rename it, or to attach the model to your own declarative
@@ -821,9 +852,10 @@ A runnable FastAPI flow (route → command → transactional outbox → publishe
821
852
  > [Database Support](https://mkdocs.python-cqrs.dev/outbox/databases/) docs for the DDL, the Alembic recipe and
822
853
  > how to register a native type for your own database.
823
854
  > [!TIP]
824
- > If you use the protobuf events you should specify `OutboxedEventRepository`
825
- > by [protobuf serialize](https://github.com/vadikko2/python-cqrs/blob/master/src/cqrs/serializers/protobuf.py). A complete example can be found in
826
- the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/save_proto_events_into_outbox.py)
855
+ > For Protobuf events, implement `proto()` / `from_proto()` and register a
856
+ > `ProtobufEventSerializer` on an `OutboxedEventMap`. JSON stays the default —
857
+ > see [Protobuf messaging](#protobuf-messaging) and the full guide:
858
+ > [Protobuf Integration](https://mkdocs.python-cqrs.dev/protobuf/).
827
859
 
828
860
  ## Producing Events from Outbox to Kafka
829
861
 
@@ -862,7 +894,7 @@ async with session_factory() as session:
862
894
  ```
863
895
 
864
896
  A complete example can be found in
865
- the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/kafka_outboxed_event_producing.py)
897
+ the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/outbox/kafka_outboxed_event_producing.py)
866
898
 
867
899
  ## Transaction log tailing
868
900
 
@@ -905,7 +937,7 @@ class UserJoinedEventHandler(cqrs.EventHandler[UserJoined]):
905
937
  ```
906
938
 
907
939
  A complete example can be found in
908
- the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/domain_event_handler.py)
940
+ the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/events/domain_event_handler.py)
909
941
 
910
942
  ### Parallel Event Processing
911
943
 
@@ -936,6 +968,7 @@ mediator = bootstrap.bootstrap_streaming(
936
968
  > - Set `max_concurrent_event_handlers` to limit the number of simultaneously running event handlers
937
969
  > - Set `concurrent_event_handle_enable=False` to disable parallel processing and process events sequentially
938
970
  > - The default value for `max_concurrent_event_handlers` is `10` for `StreamingRequestMediator` and `1` for `RequestMediator`
971
+ > - `ScopeStrategy.SEND` always uses sequential events (`concurrent=None` → `False`). Passing `concurrent_event_handle_enable=True` with `SEND` raises `ValueError`; use `HANDLER` or `NONE` for parallel events.
939
972
 
940
973
  ## Integration with presentation layers
941
974
 
@@ -973,10 +1006,10 @@ async def join_metting(
973
1006
  ```
974
1007
 
975
1008
  A complete example can be found in
976
- the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/fastapi_integration.py)
1009
+ the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/events/fastapi_integration.py)
977
1010
 
978
1011
  End-to-end command + outbox sample (business row and outbox event in one transaction, plus a publisher stub):
979
- [fastapi_outbox.py](https://github.com/vadikko2/python-cqrs/blob/master/examples/fastapi_outbox.py)
1012
+ [fastapi_outbox.py](https://github.com/vadikko2/python-cqrs/blob/master/examples/outbox/fastapi_outbox.py)
980
1013
 
981
1014
  ### Kafka events consuming
982
1015
 
@@ -1024,7 +1057,7 @@ async def hello_world_event_handler(
1024
1057
  ```
1025
1058
 
1026
1059
  A complete example can be found in
1027
- the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/kafka_event_consuming.py)
1060
+ the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/events/kafka_event_consuming.py)
1028
1061
 
1029
1062
  ### FastAPI SSE Streaming
1030
1063
 
@@ -1045,7 +1078,7 @@ def streaming_mediator_factory() -> cqrs.StreamingRequestMediator:
1045
1078
  domain_events_mapper=domain_events_mapper,
1046
1079
  message_broker=broker,
1047
1080
  max_concurrent_event_handlers=3,
1048
- concurrent_event_handle_enable=True,
1081
+ concurrent_event_handle_enable=True, # HANDLER/NONE only; SEND forbids this
1049
1082
  )
1050
1083
 
1051
1084
  @app.post("/process-files")
@@ -1072,7 +1105,9 @@ async def process_files_stream(
1072
1105
  ```
1073
1106
 
1074
1107
  A complete example can be found in
1075
- the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/fastapi_sse_streaming.py)
1108
+ the [documentation](https://github.com/vadikko2/python-cqrs/blob/master/examples/streaming/fastapi_sse_streaming.py)
1109
+
1110
+ If the client disconnects, close the iterator (`aclose()` / `async with aclosing(...)`) so a `SEND` UoW is not held until GC.
1076
1111
 
1077
1112
  ## Protobuf messaging
1078
1113
 
@@ -1122,6 +1157,14 @@ class UserJoinedNotificationEvent(cqrs.NotificationEvent[UserJoinedPayload]):
1122
1157
  )
1123
1158
  ```
1124
1159
 
1160
+ JSON remains the default. Opt-in Protobuf wiring (`ProtobufEventSerializer` on an
1161
+ `OutboxedEventMap`, `Message.payload_bytes`, consume via `ProtobufDeserializer`) is
1162
+ documented in the full guide:
1163
+ [Protobuf Integration](https://mkdocs.python-cqrs.dev/protobuf/).
1164
+ Runnable example:
1165
+ [protobuf_outbox.py](https://github.com/vadikko2/python-cqrs/blob/master/examples/outbox/protobuf_outbox.py)
1166
+ (`pip install "python-cqrs[protobuf]"`).
1167
+
1125
1168
  ## Contributing
1126
1169
 
1127
1170
  Contributions are welcome. To develop locally:
@@ -31,7 +31,7 @@ maintainers = [{ name = "Vadim Kozyrevskiy", email = "vadikko2@mail.ru" }]
31
31
  name = "python-cqrs"
32
32
  readme = "README.md"
33
33
  requires-python = ">=3.10"
34
- version = "4.13.0"
34
+ version = "4.15.0"
35
35
 
36
36
  [project.optional-dependencies]
37
37
  aiobreaker = ["aiobreaker>=0.3.0"]
@@ -59,6 +59,8 @@ dev = [
59
59
  "redis>=5.0.0",
60
60
  # Circuit breaker for tests
61
61
  "aiobreaker>=0.3.0", # from aiobreaker
62
+ "dishka>=1.0", # scoped-deps dishka adapter tests / examples
63
+ "protobuf>=4.25.8", # protobuf codec / deserializer unit tests
62
64
  ]
63
65
  examples = [
64
66
  "fastapi==0.109.*",
@@ -68,10 +70,13 @@ examples = [
68
70
  "aiohttp==3.14.3",
69
71
  "protobuf>=4.25.8",
70
72
  "aiosqlite>=0.20.0",
73
+ "dishka>=1.0",
71
74
  ]
72
75
  kafka = ["aiokafka==0.10.0", "retry-async==0.1.*"]
76
+ protobuf = ["protobuf>=4.25.8"]
73
77
  rabbit = ["aio-pika==9.3.0"]
74
78
  sqlalchemy = ["sqlalchemy[asyncio]==2.0.*"]
79
+ dishka = ["dishka>=1.0"]
75
80
 
76
81
  [project.urls]
77
82
  Documentation = "https://mkdocs.python-cqrs.dev/"
@@ -1,6 +1,13 @@
1
1
  from cqrs.compressors import Compressor, ZlibCompressor
2
2
  from cqrs.container.di import DIContainer
3
- from cqrs.container.protocol import Container
3
+ from cqrs.container.protocol import Container, SupportsScope
4
+ from cqrs.container.scope import (
5
+ ScopeAwareContainer,
6
+ ScopeStrategy,
7
+ bind_scope,
8
+ current_container,
9
+ enter_scope,
10
+ )
4
11
  from cqrs.circuit_breaker import ICircuitBreaker
5
12
  from cqrs.events import EventMap
6
13
  from cqrs.events.fallback import EventHandlerFallback
@@ -37,6 +44,13 @@ from cqrs.outbox.sqlalchemy import (
37
44
  SqlAlchemyOutboxedEventRepository,
38
45
  )
39
46
  from cqrs.producer import EventProducer
47
+ from cqrs.deserializers import DeserializeProtobufError, ProtobufDeserializer
48
+ from cqrs.serializers import (
49
+ EventCodec,
50
+ EventSerializer,
51
+ JsonEventSerializer,
52
+ ProtobufEventSerializer,
53
+ )
40
54
  from cqrs.requests.fallback import RequestHandlerFallback
41
55
  from cqrs.requests.map import RequestMap, SagaMap
42
56
  from cqrs.requests.mermaid import CoRMermaid
@@ -104,8 +118,20 @@ __all__ = (
104
118
  "OutboxedEventRepository",
105
119
  "SqlAlchemyOutboxedEventRepository",
106
120
  "EventProducer",
121
+ "EventSerializer",
122
+ "EventCodec",
123
+ "JsonEventSerializer",
124
+ "ProtobufEventSerializer",
125
+ "ProtobufDeserializer",
126
+ "DeserializeProtobufError",
107
127
  "Container",
128
+ "SupportsScope",
108
129
  "DIContainer",
130
+ "ScopeAwareContainer",
131
+ "ScopeStrategy",
132
+ "bind_scope",
133
+ "current_container",
134
+ "enter_scope",
109
135
  "Compressor",
110
136
  "ZlibCompressor",
111
137
  "rebind_outbox_model",