python-cqrs 4.11.0__tar.gz → 4.12.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 (88) hide show
  1. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/PKG-INFO +1 -1
  2. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/pyproject.toml +11 -11
  3. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/events/event_emitter.py +44 -14
  4. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/python_cqrs.egg-info/PKG-INFO +1 -1
  5. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/LICENSE +0 -0
  6. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/README.md +0 -0
  7. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/setup.cfg +0 -0
  8. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/__init__.py +0 -0
  9. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/adapters/__init__.py +0 -0
  10. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/adapters/amqp.py +0 -0
  11. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/adapters/circuit_breaker.py +0 -0
  12. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/adapters/kafka.py +0 -0
  13. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/adapters/protocol.py +0 -0
  14. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/circuit_breaker.py +0 -0
  15. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/compressors/__init__.py +0 -0
  16. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/compressors/protocol.py +0 -0
  17. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/compressors/zlib.py +0 -0
  18. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/container/__init__.py +0 -0
  19. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/container/dependency_injector.py +0 -0
  20. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/container/di.py +0 -0
  21. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/container/protocol.py +0 -0
  22. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/deserializers/__init__.py +0 -0
  23. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/deserializers/exceptions.py +0 -0
  24. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/deserializers/json.py +0 -0
  25. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/dispatcher/__init__.py +0 -0
  26. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/dispatcher/event.py +0 -0
  27. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/dispatcher/exceptions.py +0 -0
  28. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/dispatcher/models.py +0 -0
  29. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/dispatcher/request.py +0 -0
  30. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/dispatcher/saga.py +0 -0
  31. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/dispatcher/streaming.py +0 -0
  32. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/events/__init__.py +0 -0
  33. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/events/bootstrap.py +0 -0
  34. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/events/event.py +0 -0
  35. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/events/event_handler.py +0 -0
  36. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/events/event_processor.py +0 -0
  37. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/events/fallback.py +0 -0
  38. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/events/map.py +0 -0
  39. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/generic_utils.py +0 -0
  40. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/mediator.py +0 -0
  41. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/message_brokers/__init__.py +0 -0
  42. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/message_brokers/amqp.py +0 -0
  43. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/message_brokers/devnull.py +0 -0
  44. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/message_brokers/kafka.py +0 -0
  45. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/message_brokers/protocol.py +0 -0
  46. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/middlewares/__init__.py +0 -0
  47. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/middlewares/base.py +0 -0
  48. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/middlewares/logging.py +0 -0
  49. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/outbox/__init__.py +0 -0
  50. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/outbox/map.py +0 -0
  51. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/outbox/mock.py +0 -0
  52. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/outbox/repository.py +0 -0
  53. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/outbox/sqlalchemy.py +0 -0
  54. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/producer.py +0 -0
  55. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/requests/__init__.py +0 -0
  56. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/requests/bootstrap.py +0 -0
  57. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/requests/cor_request_handler.py +0 -0
  58. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/requests/fallback.py +0 -0
  59. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/requests/map.py +0 -0
  60. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/requests/mermaid.py +0 -0
  61. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/requests/request.py +0 -0
  62. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/requests/request_handler.py +0 -0
  63. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/response.py +0 -0
  64. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/saga/__init__.py +0 -0
  65. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/saga/bootstrap.py +0 -0
  66. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/saga/circuit_breaker.py +0 -0
  67. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/saga/compensation.py +0 -0
  68. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/saga/execution.py +0 -0
  69. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/saga/fallback.py +0 -0
  70. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/saga/mermaid.py +0 -0
  71. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/saga/models.py +0 -0
  72. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/saga/recovery.py +0 -0
  73. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/saga/saga.py +0 -0
  74. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/saga/step.py +0 -0
  75. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/saga/storage/__init__.py +0 -0
  76. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/saga/storage/enums.py +0 -0
  77. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/saga/storage/memory.py +0 -0
  78. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/saga/storage/models.py +0 -0
  79. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/saga/storage/protocol.py +0 -0
  80. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/saga/storage/sqlalchemy.py +0 -0
  81. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/saga/validation.py +0 -0
  82. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/serializers/__init__.py +0 -0
  83. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/serializers/default.py +0 -0
  84. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/cqrs/types.py +0 -0
  85. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/python_cqrs.egg-info/SOURCES.txt +0 -0
  86. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/python_cqrs.egg-info/dependency_links.txt +0 -0
  87. {python_cqrs-4.11.0 → python_cqrs-4.12.0}/src/python_cqrs.egg-info/requires.txt +0 -0
  88. {python_cqrs-4.11.0 → python_cqrs-4.12.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.11.0
3
+ Version: 4.12.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>
@@ -4,8 +4,8 @@ requires = ["setuptools>=42", "wheel"]
4
4
 
5
5
  [project]
6
6
  authors = [
7
- {name = "Vadim Kozyrevskiy", email = "vadikko2@mail.ru"},
8
- {name = "Dmitry Kutlubaev", email = "kutlubaev00@mail.ru"}
7
+ { name = "Vadim Kozyrevskiy", email = "vadikko2@mail.ru" },
8
+ { name = "Dmitry Kutlubaev", email = "kutlubaev00@mail.ru" },
9
9
  ]
10
10
  classifiers = [
11
11
  "Development Status :: 4 - Beta",
@@ -14,7 +14,7 @@ classifiers = [
14
14
  "Programming Language :: Python :: 3.10",
15
15
  "Programming Language :: Python :: 3.11",
16
16
  "Programming Language :: Python :: 3.12",
17
- "Programming Language :: Python :: 3.13"
17
+ "Programming Language :: Python :: 3.13",
18
18
  ]
19
19
  dependencies = [
20
20
  "dataclass-wizard==0.*",
@@ -24,14 +24,14 @@ dependencies = [
24
24
  "pydantic==2.*",
25
25
  "sqlalchemy[asyncio]==2.0.*",
26
26
  "python-dotenv==1.*",
27
- "typing-extensions>=4.0"
27
+ "typing-extensions>=4.0",
28
28
  ]
29
29
  description = "Event-Driven Architecture Framework for Distributed Systems"
30
- maintainers = [{name = "Vadim Kozyrevskiy", email = "vadikko2@mail.ru"}]
30
+ 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.11.0"
34
+ version = "4.12.0"
35
35
 
36
36
  [project.optional-dependencies]
37
37
  aiobreaker = ["aiobreaker>=0.3.0"]
@@ -45,10 +45,10 @@ dev = [
45
45
  "pytest-cov>=4.0.0",
46
46
  "pytest-codspeed==4.2.0",
47
47
  # Tests
48
- "aio-pika==9.3.0", # from rabbit
49
- "aiokafka==0.10.0", # from kafka
50
- "retry-async==0.1.*", # from kafka
51
- "requests==2.*", # from aiokafka
48
+ "aio-pika==9.3.0", # from rabbit
49
+ "aiokafka==0.10.0", # from kafka
50
+ "retry-async==0.1.*", # from kafka
51
+ "requests==2.*", # from aiokafka
52
52
  "pytest~=7.4.2",
53
53
  "pytest-asyncio~=0.21.1",
54
54
  "pytest-env==0.6.2",
@@ -57,7 +57,7 @@ dev = [
57
57
  "asyncpg>=0.29.0",
58
58
  "redis>=5.0.0",
59
59
  # Circuit breaker for tests
60
- "aiobreaker>=0.3.0" # from aiobreaker
60
+ "aiobreaker>=0.3.0", # from aiobreaker
61
61
  ]
62
62
  examples = [
63
63
  "fastapi==0.109.*",
@@ -1,3 +1,4 @@
1
+ import asyncio
1
2
  import functools
2
3
  import logging
3
4
  import typing
@@ -169,22 +170,32 @@ class EventEmitter:
169
170
  type(event).__name__,
170
171
  )
171
172
  return ()
173
+
174
+ results = await asyncio.gather(
175
+ *(self._process_single_handler(event, item) for item in handlers_types),
176
+ return_exceptions=True,
177
+ )
178
+
172
179
  follow_ups: list[IEvent] = []
173
- for handler_item in handlers_types:
174
- if isinstance(handler_item, EventHandlerFallback):
175
- follow_ups.extend(
176
- await self._handle_with_fallback(event, handler_item),
180
+ for handler_item, res in zip(handlers_types, results):
181
+ if isinstance(res, Exception):
182
+ handler_name = (
183
+ handler_item.primary.__name__
184
+ if isinstance(handler_item, EventHandlerFallback)
185
+ else handler_item.__name__
177
186
  )
178
- continue
179
- handler_type = handler_item
180
- handler: _H = await self._container.resolve(handler_type)
181
- logger.debug(
182
- "Handling Event(%s) via event handler(%s)",
183
- type(event).__name__,
184
- handler_type.__name__,
185
- )
186
- await handler.handle(event)
187
- follow_ups.extend(list(handler.events))
187
+ logger.exception(
188
+ "Error occurred while processing domain event %s in handler %s: %s",
189
+ type(event).__name__,
190
+ handler_name,
191
+ res,
192
+ exc_info=res,
193
+ )
194
+ elif isinstance(res, BaseException):
195
+ raise res
196
+ else:
197
+ follow_ups.extend(res)
198
+
188
199
  return follow_ups
189
200
 
190
201
  @emit.register(INotificationEvent)
@@ -192,3 +203,22 @@ class EventEmitter:
192
203
  """Emit notification event: send to message broker; no follow-ups."""
193
204
  await self._send_to_broker(event)
194
205
  return ()
206
+
207
+ async def _process_single_handler(
208
+ self,
209
+ event: IDomainEvent,
210
+ handler_item: typing.Union[typing.Type[_H], EventHandlerFallback],
211
+ ) -> typing.Sequence[IEvent]:
212
+ """Process a single event handler and return its follow-up events."""
213
+ if isinstance(handler_item, EventHandlerFallback):
214
+ return await self._handle_with_fallback(event, handler_item)
215
+
216
+ handler_type = handler_item
217
+ handler: _H = await self._container.resolve(handler_type)
218
+ logger.debug(
219
+ "Handling Event(%s) via event handler(%s)",
220
+ type(event).__name__,
221
+ handler_type.__name__,
222
+ )
223
+ await handler.handle(event)
224
+ return list(handler.events)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-cqrs
3
- Version: 4.11.0
3
+ Version: 4.12.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>
File without changes
File without changes
File without changes