Skip to content

Commit 90a331d

Browse files
committed
Switch from cloudevents to cloudevents-pydantic package
Signed-off-by: Federico Busetti <[email protected]>
1 parent e07d725 commit 90a331d

File tree

12 files changed

+607
-649
lines changed

12 files changed

+607
-649
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ lint:
4848
poetry run ruff check .
4949

5050
fix:
51+
poetry run ruff format .
5152
poetry run ruff check . --fix
5253
poetry run ruff format .
5354

poetry.lock

Lines changed: 389 additions & 341 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ aiosqlite = ">=0.18.0"
2323
alembic = "^1.11.1"
2424
asgiref = "^3.7.2"
2525
celery = { version = "^5.3.1", extras = ["redis"] }
26-
cloudevents = "^1.9.0"
26+
cloudevents-pydantic = "^0.0.2"
2727
dependency-injector = { version = "^4.41.0", extras = ["pydantic"] }
2828
httpx = ">=0.23.0"
2929
opentelemetry-distro = { version = "*", extras = ["otlp"] }

src/domains/books/_gateway_interfaces.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
from collections.abc import Iterable, Mapping
22
from typing import Any, List, Literal, Protocol, Tuple, Union
33

4+
from cloudevents_pydantic.events import CloudEvent
5+
46
from domains.books._models import BookModel
5-
from domains.common.cloudevent_base import BaseEvent
67

78

89
class BookRepositoryInterface(Protocol):
@@ -18,4 +19,4 @@ async def find(
1819

1920

2021
class BookEventGatewayInterface(Protocol):
21-
async def emit(self, event: BaseEvent) -> None: ...
22+
async def emit(self, event: CloudEvent) -> None: ...

src/domains/books/_service.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ async def create_book(self, book: BookData) -> Book:
4848
book_cpu_intensive_task.delay(book_id=book.book_id)
4949

5050
await self._event_gateway.emit(
51-
BookCreatedV1(
51+
BookCreatedV1.event_factory(
5252
data=BookCreatedV1Data.model_validate(book_model, from_attributes=True)
5353
)
5454
)

src/domains/books/events.py

Lines changed: 65 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
1-
import typing
1+
from typing import Annotated, Literal
22

33
import pydantic
4-
from pydantic import ConfigDict
5-
6-
from domains.common.cloudevent_base import (
7-
BaseEvent,
8-
dataschema_field,
9-
type_field,
10-
)
4+
from cloudevents_pydantic.events import CloudEvent
5+
from cloudevents_pydantic.events.fields import metadata
6+
from cloudevents_pydantic.events.fields.types import URI, URIReference
7+
from pydantic import ConfigDict, Field
118

129

1310
class BookCreatedV1Data(pydantic.BaseModel):
@@ -16,22 +13,76 @@ class BookCreatedV1Data(pydantic.BaseModel):
1613
author_name: str
1714

1815

19-
class BookCreatedV1(BaseEvent):
20-
type: typing.Literal["book.created.v1"] = type_field("book.created.v1")
21-
dataschema: str = dataschema_field("book.created.v1")
16+
def _dataschema_url(value: str) -> str:
17+
return f"https://this_service/dataschemas/{value}"
18+
19+
20+
class BookCreatedV1(CloudEvent):
21+
source: Annotated[
22+
URIReference,
23+
Field(default="/book_service", validate_default=True),
24+
metadata.FieldSource,
25+
]
26+
type: Annotated[
27+
Literal["book.created.v1"], Field(default="book.created.v1"), metadata.FieldType
28+
]
29+
dataschema: Annotated[
30+
URI,
31+
Field(default=_dataschema_url("book.created.v1"), validate_default=True),
32+
metadata.FieldDataSchema,
33+
]
2234

2335
data: BookCreatedV1Data
2436

2537
# The first example is used to generate the OpenAPI documentation!
26-
# Examples ate good! Add examples!
38+
# Examples are good! Add examples!
2739
model_config = ConfigDict(
2840
json_schema_extra={
2941
"examples": [
3042
{
3143
"source": "this.service.url.here",
3244
"type": "book.created.v1",
33-
"dataschema": "book.created.v1/some_event",
34-
"datacontenttype": "text/xml",
45+
"dataschema": "/dataschemas/book.created.v1",
46+
"datacontenttype": "application/json",
47+
"subject": "123",
48+
"data": {"book_id": 0, "title": "string", "author_name": "string"},
49+
"id": "A234-1234-1234",
50+
"specversion": "1.0",
51+
"time": "2018-04-05T17:31:00Z",
52+
}
53+
]
54+
}
55+
)
56+
57+
58+
class BookUpdatedV1(CloudEvent):
59+
source: Annotated[
60+
URIReference,
61+
Field(default="/book_service", validate_default=True),
62+
metadata.FieldSource,
63+
]
64+
type: Annotated[
65+
Literal["book.updated.v1"], Field(default="book.updated.v1"), metadata.FieldType
66+
]
67+
dataschema: Annotated[
68+
URI,
69+
Field(default=_dataschema_url("book.updated.v1"), validate_default=True),
70+
metadata.FieldDataSchema,
71+
]
72+
73+
# This is just an example, too lazy to use a different data class
74+
data: BookCreatedV1Data
75+
76+
# The first example is used to generate the OpenAPI documentation!
77+
# Examples are good! Add examples!
78+
model_config = ConfigDict(
79+
json_schema_extra={
80+
"examples": [
81+
{
82+
"source": "this.service.url.here",
83+
"type": "book.updated.v1",
84+
"dataschema": "/dataschemas/book.updated.v1",
85+
"datacontenttype": "application/json",
3586
"subject": "123",
3687
"data": {"book_id": 0, "title": "string", "author_name": "string"},
3788
"id": "A234-1234-1234",

src/domains/common/README.md

Lines changed: 0 additions & 6 deletions
This file was deleted.

src/domains/common/__init__.py

Whitespace-only changes.

src/domains/common/cloudevent_base.py

Lines changed: 0 additions & 231 deletions
This file was deleted.

src/gateways/event.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1+
from cloudevents_pydantic.events import CloudEvent
12
from structlog import get_logger
23

3-
from domains.common.cloudevent_base import BaseEvent
4-
54

65
class NullEventGateway:
76
async def emit(
8-
self, event: BaseEvent
7+
self, event: CloudEvent
98
) -> None: # pragma: no cover # No need to test this
109
logger = get_logger()
1110
await logger.ainfo(

0 commit comments

Comments
 (0)