Skip to content

Commit

Permalink
Update docs
Browse files Browse the repository at this point in the history
Signed-off-by: Federico Busetti <729029+febus982@users.noreply.github.com>
  • Loading branch information
febus982 committed Sep 28, 2024
1 parent 81a317b commit 02699d6
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 25 deletions.
18 changes: 18 additions & 0 deletions docs/event_class.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ When you create event types in your app you will want to make sure to follow the
be kept up to date and make sure their validation, serialization and deserialization rules
will be compliant with the [CloudEvents spec](https://github.com/cloudevents/spec/tree/main).

/// tab | class Syntax
```python
from typing import TypedDict, Literal
from cloudevents_pydantic.events import CloudEvent, field_types
Expand All @@ -121,6 +122,23 @@ event = OrderCreated.event_factory(
data={"a_str": "a nice string", "an_int": 1},
)
```
///

/// tab | inline Syntax
```python
from typing import TypedDict, Literal
from cloudevents_pydantic.events import CloudEvent, field_types

class OrderCreated(CloudEvent):
data: TypedDict("OrderCreatedData", {"a_str": field_types.String, "an_int": field_types.Integer})
type: Literal["order_created"] = "order_created"
source: field_types.String = "order_service"

event = OrderCreated.event_factory(
data={"a_str": "a nice string", "an_int": 1},
)
```
///

/// admonition | Use subclasses
type: warning
Expand Down
91 changes: 66 additions & 25 deletions docs/protocol_bindings/http_binding.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,14 @@ def do_something():
/// admonition | Why you have to reuse the same object?
type: tip

When the HTTPHandler instance is created it creates internally a Pydantic `TypeAdapter`
for the event class, to handle efficiently event batches. This is an expensive operation.
Check the [Pydantic documentation](https://docs.pydantic.dev/latest/concepts/performance/#typeadapter-instantiated-once)
about this.
When the HTTPHandler instance is created it creates internally instances of Pydantic `TypeAdapter`
for the event class, to handle efficiently event serialization and discriminated unions. This is
an expensive operation. Check the [Pydantic documentation](https://docs.pydantic.dev/latest/concepts/performance/#typeadapter-instantiated-once) about this.
///

## Serialize a JSON event
## Deserialize a JSON event

HTTP serialization returns header and body to be used in a HTTP request.
HTTP deserialization parses the body to reconstruct the event.

/// tab | Custom Event class
```python
Expand All @@ -55,20 +54,15 @@ from cloudevents_pydantic.bindings.http import HTTPHandler
class OrderCreated(CloudEvent):
...

minimal_attributes = {
"type": "order_created",
"source": "https://example.com/event-producer",
"id": "b96267e2-87be-4f7a-b87c-82f64360d954",
"specversion": "1.0",
}
single_event_json = '{"data":null,"source":"https://example.com/event-producer","id":"b96267e2-87be-4f7a-b87c-82f64360d954","type":"com.example.string","specversion":"1.0","time":"2022-07-16T12:03:20.519216+04:00","subject":null,"datacontenttype":null,"dataschema":null}'
batch_event_json = '[{"data":null,"source":"https://example.com/event-producer","id":"b96267e2-87be-4f7a-b87c-82f64360d954","type":"com.example.string","specversion":"1.0","time":"2022-07-16T12:03:20.519216+04:00","subject":null,"datacontenttype":null,"dataschema":null}]'

http_handler = HTTPHandler(OrderCreated)
event = OrderCreated.event_factory(**minimal_attributes)

# Single event
headers, body = http_handler.to_json(event)
event = http_handler.from_json(single_event_json)
# Batch (list) of events
headers, body = http_handler.to_json_batch([event])
batch_of_events = http_handler.from_json_batch(batch_event_json)
```
///

Expand All @@ -88,15 +82,57 @@ http_handler = HTTPHandler()
event = CloudEvent.event_factory(**minimal_attributes)

# Single event
json_string = http_handler.to_json(event)
event = http_handler.to_json(event)
# Batch (list) of events
json_batch_string = http_handler.to_json_batch([event])
batch_of_events = http_handler.to_json_batch([event])
```
///

## Deserialize a JSON event
/// details | Use discriminated Unions to handle multiple Event classes
type: warning

HTTP deserialization parses the body to reconstruct the event.
You'll want to use [discriminated unions](https://docs.pydantic.dev/latest/concepts/unions/#discriminated-unions)
as event class and use a single `HTTPHandler` for multiple Event classes to be more efficient on validation
and to produce a correct schema.

```python
from typing import Annotated, Literal, Union

from pydantic import Field
from typing_extensions import TypedDict

from cloudevents_pydantic.bindings.http import HTTPHandler
from cloudevents_pydantic.events import CloudEvent


class OrderCreatedEvent(CloudEvent):
data: TypedDict("OrderCreatedData", {"order_id": str})
type: Literal["order_created"]


class CustomerCreatedEvent(CloudEvent):
data: TypedDict("CustomerCreatedData", {"customer_id": str})
type: Literal["customer_created"]


Event = Annotated[
Union[OrderCreatedEvent, CustomerCreatedEvent],
Field(discriminator="type"),
]

http_handler = HTTPHandler(Event)

customer_event_json = '{"data":{"customer_id":"123"},"source":"customer_service","id":"123","type":"customer_created","specversion":"1.0","time":null,"subject":null,"datacontenttype":null,"dataschema":null}'

print(type(http_handler.from_json(customer_event_json)))
# <class '__main__.CustomerCreatedEvent'>
```
///


## Serialize a JSON event

HTTP serialization returns header and body to be used in a HTTP request.

/// tab | Custom Event class
```python
Expand All @@ -106,15 +142,20 @@ from cloudevents_pydantic.bindings.http import HTTPHandler
class OrderCreated(CloudEvent):
...

single_event_json = '{"data":null,"source":"https://example.com/event-producer","id":"b96267e2-87be-4f7a-b87c-82f64360d954","type":"com.example.string","specversion":"1.0","time":"2022-07-16T12:03:20.519216+04:00","subject":null,"datacontenttype":null,"dataschema":null}'
batch_event_json = '[{"data":null,"source":"https://example.com/event-producer","id":"b96267e2-87be-4f7a-b87c-82f64360d954","type":"com.example.string","specversion":"1.0","time":"2022-07-16T12:03:20.519216+04:00","subject":null,"datacontenttype":null,"dataschema":null}]'
minimal_attributes = {
"type": "order_created",
"source": "https://example.com/event-producer",
"id": "b96267e2-87be-4f7a-b87c-82f64360d954",
"specversion": "1.0",
}

http_handler = HTTPHandler(OrderCreated)
event = OrderCreated.event_factory(**minimal_attributes)

# Single event
event = http_handler.from_json(single_event_json)
headers, body = http_handler.to_json(event)
# Batch (list) of events
batch_of_events = http_handler.from_json_batch(batch_event_json)
headers, body = http_handler.to_json_batch([event])
```
///

Expand All @@ -134,8 +175,8 @@ http_handler = HTTPHandler()
event = CloudEvent.event_factory(**minimal_attributes)

# Single event
event = http_handler.to_json(event)
json_string = http_handler.to_json(event)
# Batch (list) of events
batch_of_events = http_handler.to_json_batch([event])
json_batch_string = http_handler.to_json_batch([event])
```
///

0 comments on commit 02699d6

Please sign in to comment.