-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Resolve references when initializing Domain (#419)
This commit moves resolving references, as well as validating domain constructs to domain initialization, not activation. This ensures they happen one time, at the beginning of domain setup. If they are in activation, the resolution would be triggered every time a domain context is activated, which would be every time the domain processes a request! This commit also has the following fixes: * Ensure Value Object field's class resolution works * All Events and Commands need to be associated with an Aggregate or a stream * Validation to ensure events are not associated with multiple event sourced aggregates * Allow Abstract events and commands to be defined without an Aggregate or a stream * Scope `setup_db` fixtures to Module level (Having them at `session` level was resulting in the wrong context being popped) * Move `fetch_element_cls_from_registry` under Domain object to avoid using `current_domain` * Pass `domain` during class resolution to avoid using `current_domain`
- Loading branch information
Showing
63 changed files
with
629 additions
and
330 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# Mutating Aggregates |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# Adding Rules and Behavior |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# Invariants |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# Raising Events |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,75 @@ | ||
# Events | ||
|
||
Most applications have a definite state - they reflect past user input and | ||
interactions in their current state. It is advantageous to model these past | ||
changes as a series of discrete events. Domain events happen to be those | ||
activities that domain experts care about and represent what happened as-is. | ||
|
||
In Protean, an `Event` is an immutable object that represents a significant | ||
occurrence or change in the domain. Events are raised by aggregates to signal | ||
that something noteworthy has happened, allowing other parts of the system to | ||
react - and sync - to these changes in a decoupled manner. | ||
|
||
Events have a few primary functions: | ||
|
||
1. **Events allows different components to communicate with each other.** | ||
|
||
Within a domain or across, events can be used as a mechanism to implement | ||
eventual consistency, in the same bounded context or across. This promotes | ||
loose coupling by decoupling the producer (e.g., an aggregate that raises | ||
an event) from the consumers (e.g., various components that handle the | ||
event). | ||
|
||
Such a design eliminates the need for two-phase commits (global | ||
transactions) across bounded contexts, optimizing performance at the level | ||
of each transaction. | ||
|
||
2. **Events act as API contracts.** | ||
|
||
Events define a clear and consistent structure for data that is shared | ||
between different components of the system. This promotes system-wide | ||
interoperability and integration between components. | ||
|
||
3. **Events help preserve context boundaries.** | ||
|
||
Events propagate information across bounded contexts, thus helping to | ||
sync changes throughout the application domain. This allows each domain | ||
to be modeled in the architecture pattern that is most appropriate for its | ||
use case. | ||
|
||
## Defining Events | ||
|
||
Event names should be descriptive and convey the specific change or occurrence | ||
in the domain clearly, ensuring that the purpose of the event is immediately | ||
understandable. Events are named as past-tense verbs to clearly indicate | ||
that an event has already occurred, such as `OrderPlaced` or `PaymentProcessed`. | ||
|
||
You can define an event with the `Domain.event` decorator: | ||
|
||
```python hl_lines="22 26 29-31 34-37" | ||
{! docs_src/guides/domain-definition/events/001.py !} | ||
``` | ||
|
||
Events are always connected to an Aggregate class, specified with the | ||
`aggregate_cls` param in the decorator. An exception to this rule is when the | ||
Event class has been marked _Abstract_. | ||
|
||
## Event Facts | ||
|
||
- Events should be named in past tense, because we observe domain events _after | ||
the fact_. `StockDepleted` is a better choice than the imperative | ||
`DepleteStock` as an event name. | ||
- An event is associated with an aggregate or a stream, specified with | ||
`aggregate_cls` or `stream` parameters to the decorator, as above. We will | ||
dive deeper into these parameters in the Processing Events section. | ||
<!-- FIXME Add link to events processing section --> | ||
- Events are essentially Data Transfer Objects (DTO)- they can only hold | ||
simple fields. | ||
- Events should only contain information directly relevant to the event. A | ||
receiver that needs more information should be listening to other pertinent | ||
events and add read-only structures to its own state to take decisions later. | ||
A receiver should not query the current state from the sender because the | ||
sender's state could have already mutated. | ||
|
||
## Immutability | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Start Here | ||
|
||
Explain the overall structure of guides and the path to follow. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
from enum import Enum | ||
|
||
from protean import Domain | ||
from protean.fields import String, Identifier | ||
|
||
domain = Domain(__file__) | ||
|
||
|
||
class UserStatus(Enum): | ||
ACTIVE = "ACTIVE" | ||
ARCHIVED = "ARCHIVED" | ||
|
||
|
||
@domain.event(aggregate_cls="User") | ||
class UserActivated: | ||
user_id = Identifier(required=True) | ||
|
||
|
||
@domain.event(aggregate_cls="User") | ||
class UserRenamed: | ||
user_id = Identifier(required=True) | ||
name = String(required=True, max_length=50) | ||
|
||
|
||
@domain.aggregate | ||
class User: | ||
name = String(max_length=50, required=True) | ||
email = String(required=True) | ||
status = String(choices=UserStatus) | ||
|
||
def activate(self) -> None: | ||
self.status = UserStatus.ACTIVE.value | ||
self.raise_(UserActivated(user_id=self.id)) | ||
|
||
def change_name(self, name: str) -> None: | ||
self.name = name | ||
self.raise_(UserRenamed(user_id=self.id, name=name)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.