-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
rewrite split stream docs & small changes in other places
- Loading branch information
1 parent
770a6f1
commit 4f4bc3a
Showing
11 changed files
with
109 additions
and
97 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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
# Repository | ||
|
||
A `repository` takes care of storing and loading the `aggregates`. | ||
He is also responsible for building [messages](event_bus.md) from the events | ||
He is also responsible for building [messages](message.md) from the events | ||
and optionally dispatching them to the event bus. | ||
|
||
## Create a repository | ||
|
@@ -63,7 +63,7 @@ $repository = $repositoryManager->get(Profile::class); | |
!!! warning | ||
|
||
If you use the event bus, you should be aware that the events are dispatched synchronously. | ||
You may encounter "at least once" problems. | ||
You may encounter [at least once](https://softwaremill.com/message-delivery-and-deduplication-strategies/) problems. | ||
|
||
!!! note | ||
|
||
|
@@ -138,6 +138,10 @@ $repository = $repositoryManager->get(Profile::class); | |
|
||
You can find out more about message decorator [here](message_decorator.md). | ||
|
||
!!! tip | ||
|
||
If you have multiple decorators, you can use the `ChainMessageDecorator` to chain them. | ||
|
||
## Use the repository | ||
|
||
Each `repository` has three methods that are responsible for loading an `aggregate`, | ||
|
@@ -159,9 +163,17 @@ $profile = Profile::create($id, '[email protected]'); | |
/** @var Repository $repository */ | ||
$repository->save($profile); | ||
``` | ||
!!! note | ||
!!! Warning | ||
|
||
All events are written to the database with one transaction in order to ensure data consistency. | ||
If an exception occurs during the save process, | ||
the transaction is rolled back and the aggregate is not valid anymore. | ||
You can not save the aggregate again and you need to load it again. | ||
|
||
!!! note | ||
|
||
Due to the nature of the aggregate having a playhead, | ||
we have a unique constraint that ensures that no race condition happens here. | ||
|
||
### Load an aggregate | ||
|
||
|
@@ -254,3 +266,5 @@ class ProfileRepository | |
* [How to work with the store](store.md) | ||
* [How to use snapshots](snapshots.md) | ||
* [How to split streams](split_stream.md) | ||
* [How to use the event bus](event_bus.md) | ||
* [How to create messages](message.md) |
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 |
---|---|---|
@@ -1,45 +1,86 @@ | ||
# Splitting the eventstream | ||
# Split Stream | ||
|
||
In some cases the business has rules which implies an restart of the event stream for an aggregate since the past events | ||
are not relevant for the current state. For example a user decides to end his active subscription and the business rules | ||
says if the user start a new subscription all past events should not be considered anymore. Another case could be a | ||
banking scenario. There the business decides to save the current state every quarter for each banking account. | ||
In some cases the business has rules which implies a restart of the event stream for an aggregate | ||
since the past events are not relevant for the current state. | ||
A bank is often used as an example. A bank account has hundreds of transactions, | ||
but every bank makes a balance report at the end of the year. | ||
In this step the current account balance is persisted. | ||
This event is perfect to split the stream and start aggregating from this point. | ||
|
||
Not only that some businesses requires such an action it also increases the performance for aggregate which would have a | ||
really long event stream. | ||
Not only that some businesses requires such an action | ||
it also increases the performance for aggregate which would have a really long event stream. | ||
|
||
## Flagging an event to split the stream | ||
In the background the library will mark all past events as archived | ||
and will not load them anymore for building the aggregate. | ||
It will only load the events from the split event and onwards. | ||
But subscriptions will still receive all events. | ||
So you can create projections which are based on the full event stream. | ||
|
||
To use this feature you need to add the `SplitStreamDecorator`. You will also need events which will trigger this | ||
action. For that you can use the `#[SplitStream]` attribute. We decided that we are not literallty splitting the stream, | ||
instead we are marking all past events as archived as soon as this event is saved. Then the past events will not be | ||
loaded anymore for building the aggregate. This means that all needed data has to be present in these events which | ||
should trigger the event split. | ||
!!! tip | ||
|
||
To split the stream is often a better solution than using snapshots. | ||
|
||
## Configuration | ||
|
||
To use this feature you need to add the `SplitStreamDecorator` in the repository manager. | ||
|
||
```php | ||
use Patchlevel\EventSourcing\Metadata\AggregateRoot\AggregateRootRegistry; | ||
use Patchlevel\EventSourcing\Metadata\Event\EventMetadataFactory; | ||
use Patchlevel\EventSourcing\Repository\DefaultRepositoryManager; | ||
use Patchlevel\EventSourcing\Repository\MessageDecorator\SplitStreamDecorator; | ||
use Patchlevel\EventSourcing\Store\Store; | ||
|
||
/** | ||
* @var AggregateRootRegistry $aggregateRootRegistry | ||
* @var Store $store | ||
* @var EventMetadataFactory $eventMetadataFactory | ||
*/ | ||
$repositoryManager = new DefaultRepositoryManager( | ||
$aggregateRootRegistry, | ||
$store, | ||
null, | ||
null, | ||
new SplitStreamDecorator($eventMetadataFactory), | ||
); | ||
``` | ||
!!! note | ||
|
||
You can find out more about decorator [here](./message_decorator.md). | ||
|
||
!!! tip | ||
|
||
You can use multiple decorators with the `ChainMessageDecorator`. | ||
|
||
## Usage | ||
|
||
To use this feature you need to mark the event which should split the stream. | ||
For that you can use the `#[SplitStream]` attribute. | ||
|
||
```php | ||
use Patchlevel\EventSourcing\Attribute\Event; | ||
use Patchlevel\EventSourcing\Attribute\SplitStream; | ||
use Patchlevel\EventSourcing\Serializer\Normalizer\IdNormalizer; | ||
|
||
#[Event('bank_account.month_passed')] | ||
#[Event('bank_account.balance_reported')] | ||
#[SplitStream] | ||
final class MonthPassed | ||
final class BalanceReported | ||
{ | ||
public function __construct( | ||
#[IdNormalizer] | ||
public AccountId $accountId, | ||
public string $name, | ||
public BankAccountId $bankAccountId, | ||
public int $year, | ||
public int $balanceInCents, | ||
) { | ||
} | ||
} | ||
``` | ||
!!! warning | ||
|
||
The event needs all data which is relevant the aggregate to be used since all past event will not be loaded! Keep | ||
this in mind if you want to use this feature. | ||
The event needs all data which is relevant the aggregate to be used since all past event will not be loaded! | ||
Keep this in mind if you want to use this feature. | ||
|
||
!!! note | ||
|
||
This archive flag only impacts the Store::load method which is used the build the aggregate from the stream. | ||
This impacts only the aggregate loaded by the repository. Subscriptions will still receive all 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
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