Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Message with headers #494

Merged
merged 8 commits into from
Feb 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 5 additions & 25 deletions baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,6 @@
<code><![CDATA[$method->getName()]]></code>
</MixedMethodCall>
</file>
<file src="src/EventBus/Message.php">
<InvalidReturnStatement>
<code>$headers</code>
</InvalidReturnStatement>
<InvalidReturnType>
<code>Headers</code>
</InvalidReturnType>
</file>
<file src="src/EventBus/Serializer/EventSerializerMessageSerializer.php">
<MixedArgumentTypeCoercion>
<code><![CDATA[$data['headers']]]></code>
Expand Down Expand Up @@ -104,6 +96,11 @@
<code>$index</code>
</InvalidPropertyAssignmentValue>
</file>
<file src="src/Store/DoctrineDbalStoreStream.php">
<ArgumentTypeCoercion>
<code><![CDATA[DoctrineHelper::normalizeCustomHeaders($data['custom_headers'], $platform)]]></code>
</ArgumentTypeCoercion>
</file>
<file src="src/Store/DoctrineHelper.php">
<MixedReturnTypeCoercion>
<code>$normalizedCustomHeaders</code>
Expand Down Expand Up @@ -193,23 +190,6 @@
<code>$name</code>
</PropertyNotSetInConstructor>
</file>
<file src="tests/Unit/EventBus/MessageTest.php">
<InvalidArgument>
<code><![CDATA[[
'foo' => 'bar',
'aggregateName' => 'profile',
'aggregateId' => '1',
'playhead' => 3,
'recordedOn' => $recordedAt,
'newStreamStart' => true,
'archived' => true,
]]]></code>
</InvalidArgument>
<TypeDoesNotContainType>
<code>assertSame</code>
<code>assertSame</code>
</TypeDoesNotContainType>
</file>
<file src="tests/Unit/Fixture/MessageNormalizer.php">
<MixedArgumentTypeCoercion>
<code>$value</code>
Expand Down
47 changes: 33 additions & 14 deletions docs/pages/event_bus.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,14 @@ event/message.

## Message

A `Message` contains the event and related meta information such as the aggregate class and id.
A message contains the following information:
A `Message` contains the event and related meta information as headers. A `Message` contains only two properties, first
the `event` and second the `headers`. Internally we are also using the `headers` to store meta information for
the `Message` for example:

* aggregate class
* aggregate name
* aggregate id
* playhead
* event
* recorded on
* custom headers

Each event is packed into a message and dispatched using the event bus.

Expand All @@ -26,7 +25,7 @@ use Patchlevel\EventSourcing\EventBus\Message;

$clock = SystemClock();
$message = Message::create(new NameChanged('foo'))
->withAggregateClass(Profile::class)
->withAggregateName('profile')
->withAggregateId('bca7576c-536f-4428-b694-7b1f00c714b7')
->withPlayhead(2)
->withRecordedOn($clock->now());
Expand All @@ -38,35 +37,55 @@ $eventBus->dispatch($message);

The message object is immutable.

You don't have to create the message yourself,
it is automatically created, saved and dispatched in the [repository](repository.md).
You don't have to create the message yourself, it is automatically created, saved and dispatched in
the [repository](repository.md).

### Custom headers

You can also enrich your own header or metadata information.
This information is then accessible in the message object and is also stored in the database.
As already mentioned, you can enrich the `Message` with your own meta information. This is then accessible in the
message object and is also stored in the database.

```php
use Patchlevel\EventSourcing\EventBus\Message;

$message = Message::create(new NameChanged('foo'))
// ...
->withCustomHeader('application-id', 'app');
->withHeader('application-id', 'app');
```

!!! note

You can read about how to pass additional headers to the message object in the [message decorator](message_decorator.md) docs.

You can also access your custom headers.
You can also access your custom headers. For this case there is also a method to only retrieve the headers which are not
used internally.

```php
use Patchlevel\EventSourcing\EventBus\Message;

$message->customHeader('application-id'); // app
$message->header('application-id'); // app
$message->customHeaders(); // ['application-id' => 'app']
```

If you want *all* the headers you can also retrieve them.

```php
use Patchlevel\EventSourcing\EventBus\Message;

$message->headers();
// results in:
[
'aggregateName' => 'profile',
'aggregateId' => '1',
// {...},
'application-id' => 'app'
]
```

!!! warning

Relying on internal meta data could be dangerous as they could be changed. So be cautios if you want to implement logic on them.

## Event Bus

The event bus is responsible for dispatching the messages to the listeners.
Expand Down Expand Up @@ -196,7 +215,7 @@ final class WelcomeSubscriber
## Psr-14 Event Bus

You can also use a [psr-14](https://www.php-fig.org/psr/psr-14/) compatible event bus.
In this case, you can't use the `Subscribe` attribute.
In this case, you can't use the `Subscribe` attribute.
You need to use the system of the psr-14 event bus.

```php
Expand Down
6 changes: 3 additions & 3 deletions docs/pages/message_decorator.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ $repository = $repositoryManager->get(Profile::class);
## Create own decorator

You can also use this feature to add your own metadata to your events. For this the have an extra methods on `Message`
to add data `withCustomHeader` and to read this data later on `customHeader`.
to add data `withHeader` and to read this data later on `header`.

```php
use Patchlevel\EventSourcing\EventBus\Message;
Expand All @@ -74,7 +74,7 @@ final class OnSystemRecordedDecorator implements MessageDecorator
{
public function __invoke(Message $message): Message
{
return $message->withCustomHeader('system', 'accounting_system');
return $message->withHeader('system', 'accounting_system');
}
}
```
Expand All @@ -85,7 +85,7 @@ final class OnSystemRecordedDecorator implements MessageDecorator

!!! tip

You can also set multiple headers with `withCustomHeaders` which expects an hashmap.
You can also set multiple headers with `withHeaders` which expects an hashmap.

## Learn more

Expand Down
7 changes: 6 additions & 1 deletion phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ parameters:
path: src/Console/DoctrineHelper.php

-
message: "#^Method Patchlevel\\\\EventSourcing\\\\EventBus\\\\Message\\:\\:headers\\(\\) should return array\\{aggregateName\\?\\: string, aggregateId\\?\\: string, playhead\\?\\: int\\<1, max\\>, recordedOn\\?\\: DateTimeImmutable, newStreamStart\\?\\: bool, archived\\?\\: bool\\} but returns non\\-empty\\-array\\<string, mixed\\>\\.$#"
message: "#^Property Patchlevel\\\\EventSourcing\\\\EventBus\\\\Message\\<T of object\\>\\:\\:\\$headers \\(array\\{aggregateName\\?\\: string, aggregateId\\?\\: string, playhead\\?\\: int\\<1, max\\>, recordedOn\\?\\: DateTimeImmutable, newStreamStart\\?\\: bool, archived\\?\\: bool\\}\\) does not accept non\\-empty\\-array\\<string, mixed\\>\\.$#"
count: 1
path: src/EventBus/Message.php

Expand Down Expand Up @@ -35,6 +35,11 @@ parameters:
count: 1
path: src/Store/ArrayStream.php

-
message: "#^Parameter \\#1 \\$headers of method Patchlevel\\\\EventSourcing\\\\EventBus\\\\Message\\<object\\>\\:\\:withHeaders\\(\\) expects array\\{aggregateName\\?\\: string, aggregateId\\?\\: string, playhead\\?\\: int\\<1, max\\>, recordedOn\\?\\: DateTimeImmutable, newStreamStart\\?\\: bool, archived\\?\\: bool\\}, array\\<string, mixed\\> given\\.$#"
count: 1
path: src/Store/DoctrineDbalStoreStream.php

-
message: "#^Ternary operator condition is always true\\.$#"
count: 1
Expand Down
6 changes: 1 addition & 5 deletions src/EventBus/Decorator/SplitStreamDecorator.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,6 @@ public function __invoke(Message $message): Message
$event = $message->event();
$metadata = $this->eventMetadataFactory->metadata($event::class);

if ($metadata->splitStream) {
return $message->withNewStreamStart(true);
}

return $message;
return $message->withNewStreamStart($metadata->splitStream);
}
}
10 changes: 10 additions & 0 deletions src/EventBus/HeaderNotFound.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@ public static function recordedOn(): self
return new self(Message::HEADER_RECORDED_ON);
}

public static function newStreamStart(): self
{
return new self(Message::HEADER_NEW_STREAM_START);
}

public static function archived(): self
{
return new self(Message::HEADER_ARCHIVED);
}

public static function custom(string $name): self
{
return new self($name);
Expand Down
Loading
Loading