python-cqrs 0.0.17__tar.gz → 0.0.18__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.
- {python_cqrs-0.0.17/src/python_cqrs.egg-info → python_cqrs-0.0.18}/PKG-INFO +1 -1
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/pyproject.toml +1 -1
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/dispatcher/dispatcher.py +4 -2
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/events/event.py +2 -2
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/events/map.py +4 -2
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/mediator.py +3 -1
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/middlewares/base.py +1 -1
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/outbox/repository.py +17 -4
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/outbox/sqlalchemy.py +12 -8
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/requests/map.py +1 -7
- {python_cqrs-0.0.17 → python_cqrs-0.0.18/src/python_cqrs.egg-info}/PKG-INFO +1 -1
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/LICENSE +0 -0
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/README.md +0 -0
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/setup.cfg +0 -0
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/__init__.py +0 -0
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/adapters/__init__.py +0 -0
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/adapters/amqp.py +0 -0
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/adapters/kafka.py +0 -0
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/compressors/__init__.py +0 -0
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/compressors/protocol.py +0 -0
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/compressors/zlib.py +0 -0
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/container/__init__.py +0 -0
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/container/di.py +0 -0
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/container/protocol.py +0 -0
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/dispatcher/__init__.py +0 -0
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/events/__init__.py +0 -0
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/events/bootstrap.py +0 -0
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/events/event_emitter.py +0 -0
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/events/event_handler.py +0 -0
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/message_brokers/__init__.py +0 -0
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/message_brokers/amqp.py +0 -0
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/message_brokers/devnull.py +0 -0
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/message_brokers/kafka.py +0 -0
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/message_brokers/protocol.py +0 -0
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/middlewares/__init__.py +0 -0
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/middlewares/logging.py +0 -0
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/outbox/__init__.py +0 -0
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/outbox/producer.py +0 -0
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/outbox/protocol.py +0 -0
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/requests/__init__.py +0 -0
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/requests/bootstrap.py +0 -0
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/requests/request.py +0 -0
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/requests/request_handler.py +0 -0
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/response.py +0 -0
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/python_cqrs.egg-info/SOURCES.txt +0 -0
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/python_cqrs.egg-info/dependency_links.txt +0 -0
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/python_cqrs.egg-info/requires.txt +0 -0
- {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/python_cqrs.egg-info/top_level.txt +0 -0
|
@@ -13,12 +13,14 @@ from cqrs import (
|
|
|
13
13
|
|
|
14
14
|
logger = logging.getLogger("cqrs")
|
|
15
15
|
|
|
16
|
+
Resp = typing.TypeVar("Resp", res.Response, None, contravariant=True)
|
|
17
|
+
|
|
16
18
|
|
|
17
19
|
class RequestHandlerDoesNotExist(Exception): ...
|
|
18
20
|
|
|
19
21
|
|
|
20
|
-
class RequestDispatchResult(pydantic.BaseModel):
|
|
21
|
-
response:
|
|
22
|
+
class RequestDispatchResult(pydantic.BaseModel, typing.Generic[Resp]):
|
|
23
|
+
response: Resp = pydantic.Field(default=None)
|
|
22
24
|
events: typing.List[cqrs_events.Event] = pydantic.Field(default_factory=list)
|
|
23
25
|
|
|
24
26
|
|
|
@@ -15,7 +15,7 @@ class DomainEvent(Event, frozen=True):
|
|
|
15
15
|
"""
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
_P = typing.TypeVar("_P")
|
|
18
|
+
_P = typing.TypeVar("_P", object, None, contravariant=True)
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
class NotificationEvent(Event, frozen=True):
|
|
@@ -82,7 +82,7 @@ class ECSTEvent(Event, typing.Generic[_P], frozen=True):
|
|
|
82
82
|
event_name: typing.Text
|
|
83
83
|
event_type: typing.ClassVar = "ecst_event"
|
|
84
84
|
|
|
85
|
-
payload: _P
|
|
85
|
+
payload: _P = pydantic.Field(default=None)
|
|
86
86
|
|
|
87
87
|
model_config = pydantic.ConfigDict(from_attributes=True)
|
|
88
88
|
|
|
@@ -3,14 +3,16 @@ import typing
|
|
|
3
3
|
from cqrs.events import event, event_handler
|
|
4
4
|
|
|
5
5
|
_KT = typing.TypeVar("_KT", bound=typing.Type[event.Event])
|
|
6
|
-
_VT = typing.List[
|
|
6
|
+
_VT: typing.TypeAlias = typing.List[
|
|
7
|
+
typing.Type[event_handler.EventHandler[event.Event]]
|
|
8
|
+
]
|
|
7
9
|
|
|
8
10
|
|
|
9
11
|
class EventMap(typing.Dict[_KT, _VT]):
|
|
10
12
|
def bind(
|
|
11
13
|
self,
|
|
12
14
|
event_type: _KT,
|
|
13
|
-
handler_type: typing.Type[event_handler.EventHandler
|
|
15
|
+
handler_type: typing.Type[event_handler.EventHandler],
|
|
14
16
|
) -> None:
|
|
15
17
|
if event_type not in self:
|
|
16
18
|
self[event_type] = [handler_type]
|
|
@@ -9,6 +9,8 @@ from cqrs import (
|
|
|
9
9
|
response,
|
|
10
10
|
)
|
|
11
11
|
|
|
12
|
+
Resp = typing.TypeVar("Resp", response.Response, None, contravariant=True)
|
|
13
|
+
|
|
12
14
|
|
|
13
15
|
class RequestMediator:
|
|
14
16
|
"""
|
|
@@ -56,7 +58,7 @@ class RequestMediator:
|
|
|
56
58
|
middleware_chain=middleware_chain, # type: ignore
|
|
57
59
|
)
|
|
58
60
|
|
|
59
|
-
async def send(self, request: requests.Request) ->
|
|
61
|
+
async def send(self, request: requests.Request) -> Resp:
|
|
60
62
|
dispatch_result = await self._dispatcher.dispatch(request)
|
|
61
63
|
|
|
62
64
|
if dispatch_result.events:
|
|
@@ -4,7 +4,7 @@ import typing
|
|
|
4
4
|
from cqrs import requests, response
|
|
5
5
|
|
|
6
6
|
Req = typing.TypeVar("Req", bound=requests.Request, contravariant=True)
|
|
7
|
-
Res = typing.TypeVar("Res", response.Response, None,
|
|
7
|
+
Res = typing.TypeVar("Res", response.Response, None, contravariant=True)
|
|
8
8
|
HandleType = typing.Callable[[Req], typing.Awaitable[Res]]
|
|
9
9
|
|
|
10
10
|
|
|
@@ -6,7 +6,7 @@ import uuid
|
|
|
6
6
|
import cqrs
|
|
7
7
|
from cqrs.events import event as ev
|
|
8
8
|
|
|
9
|
-
Event
|
|
9
|
+
Event = typing.TypeVar("Event", ev.NotificationEvent, ev.ECSTEvent, contravariant=True)
|
|
10
10
|
Session = typing.TypeVar("Session")
|
|
11
11
|
|
|
12
12
|
|
|
@@ -17,7 +17,11 @@ class EventStatus(enum.StrEnum):
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
class OutboxedEventRepository(abc.ABC, typing.Generic[Session]):
|
|
20
|
-
def __init__(
|
|
20
|
+
def __init__(
|
|
21
|
+
self,
|
|
22
|
+
session_factory: typing.Callable[[], Session],
|
|
23
|
+
compressor: cqrs.Compressor | None = None,
|
|
24
|
+
):
|
|
21
25
|
self._session_factory = session_factory
|
|
22
26
|
self._compressor = compressor
|
|
23
27
|
|
|
@@ -38,11 +42,20 @@ class OutboxedEventRepository(abc.ABC, typing.Generic[Session]):
|
|
|
38
42
|
"""Get one event from the repository."""
|
|
39
43
|
|
|
40
44
|
@abc.abstractmethod
|
|
41
|
-
async def get_many(
|
|
45
|
+
async def get_many(
|
|
46
|
+
self,
|
|
47
|
+
session: Session,
|
|
48
|
+
batch_size: int = 100,
|
|
49
|
+
) -> typing.List[Event]:
|
|
42
50
|
"""Get many events from the repository."""
|
|
43
51
|
|
|
44
52
|
@abc.abstractmethod
|
|
45
|
-
async def update_status(
|
|
53
|
+
async def update_status(
|
|
54
|
+
self,
|
|
55
|
+
session: Session,
|
|
56
|
+
event_id: uuid.UUID,
|
|
57
|
+
new_status: EventStatus,
|
|
58
|
+
):
|
|
46
59
|
"""Update the event status"""
|
|
47
60
|
|
|
48
61
|
@abc.abstractmethod
|
|
@@ -175,7 +175,10 @@ class SqlAlchemyOutboxedEventRepository(
|
|
|
175
175
|
repository.OutboxedEventRepository[sql_session.AsyncSession],
|
|
176
176
|
):
|
|
177
177
|
EVENT_CLASS_MAPPING: typing.ClassVar[
|
|
178
|
-
typing.Dict[
|
|
178
|
+
typing.Dict[
|
|
179
|
+
EventType,
|
|
180
|
+
typing.Type[ev.NotificationEvent] | typing.Type[ev.ECSTEvent],
|
|
181
|
+
]
|
|
179
182
|
] = {
|
|
180
183
|
EventType.NOTIFICATION_EVENT: ev.NotificationEvent,
|
|
181
184
|
EventType.ECST_EVENT: ev.ECSTEvent,
|
|
@@ -198,14 +201,15 @@ class SqlAlchemyOutboxedEventRepository(
|
|
|
198
201
|
|
|
199
202
|
def _process_events(self, model: OutboxModel) -> repository.Event:
|
|
200
203
|
event_dict = model.row_to_dict()
|
|
201
|
-
event_dict["payload"]
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
204
|
+
if event_dict["payload"] is not None:
|
|
205
|
+
event_dict["payload"] = orjson.loads(
|
|
206
|
+
self._compressor.decompress(event_dict["payload"])
|
|
207
|
+
if self._compressor
|
|
208
|
+
else event_dict["payload"],
|
|
209
|
+
)
|
|
206
210
|
return self.EVENT_CLASS_MAPPING[event_dict["event_type"]].model_validate(
|
|
207
211
|
event_dict,
|
|
208
|
-
)
|
|
212
|
+
) # type: ignore
|
|
209
213
|
|
|
210
214
|
async def get_many(
|
|
211
215
|
self,
|
|
@@ -250,7 +254,7 @@ class SqlAlchemyOutboxedEventRepository(
|
|
|
250
254
|
else event_dict["payload"],
|
|
251
255
|
)
|
|
252
256
|
|
|
253
|
-
return self.
|
|
257
|
+
return self._process_events(event)
|
|
254
258
|
|
|
255
259
|
async def update_status(
|
|
256
260
|
self,
|
|
@@ -1,15 +1,9 @@
|
|
|
1
1
|
import typing
|
|
2
2
|
|
|
3
|
-
from cqrs import response
|
|
4
3
|
from cqrs.requests import request, request_handler
|
|
5
4
|
|
|
6
5
|
_KT = typing.TypeVar("_KT", bound=typing.Type[request.Request])
|
|
7
|
-
_VT = typing.TypeVar(
|
|
8
|
-
"_VT",
|
|
9
|
-
bound=typing.Type[
|
|
10
|
-
request_handler.RequestHandler[request.Request, response.Response]
|
|
11
|
-
],
|
|
12
|
-
)
|
|
6
|
+
_VT = typing.TypeVar("_VT", bound=typing.Type[request_handler.RequestHandler])
|
|
13
7
|
|
|
14
8
|
|
|
15
9
|
class RequestMap(typing.Dict[_KT, _VT]):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|