From cc8a6d6f5c733b630cade6fe9bb45c4c1a36d86b Mon Sep 17 00:00:00 2001 From: David Badura Date: Thu, 14 Mar 2024 12:33:48 +0100 Subject: [PATCH 1/2] load the internal header automatically --- deptrac.yaml | 3 +++ docs/pages/getting_started.md | 2 -- src/Aggregate/AggregateHeader.php | 2 -- src/Debug/Trace/TraceHeader.php | 3 --- .../Serializer/DefaultHeadersSerializer.php | 9 +++++++ .../AttributeMessageHeaderRegistryFactory.php | 2 +- .../Message/MessageHeaderRegistry.php | 18 +++++++++++++ src/Store/ArchivedHeader.php | 3 --- src/Store/DoctrineDbalStore.php | 6 ++++- src/Store/NewStreamStartHeader.php | 3 --- tests/Benchmark/SimpleSetupBench.php | 6 +---- tests/Benchmark/SnapshotsBench.php | 6 +---- tests/Benchmark/SplitStreamBench.php | 6 +---- tests/Benchmark/SubscriptionEngineBench.php | 8 +----- .../IntegrationTest.php | 6 +---- .../BasicIntegrationTest.php | 6 ++--- .../Pipeline/PipelineChangeStoreTest.php | 9 ++----- tests/Integration/Store/StoreTest.php | 6 +---- .../Subscription/SubscriptionTest.php | 26 ++++--------------- .../Serializer/HeadersSerializerTest.php | 6 ++--- 20 files changed, 53 insertions(+), 83 deletions(-) diff --git a/deptrac.yaml b/deptrac.yaml index 5798c3dc6..e76d22ee2 100644 --- a/deptrac.yaml +++ b/deptrac.yaml @@ -128,8 +128,11 @@ deptrac: - Attribute - Metadata MetadataMessage: + - Aggregate - Attribute + - Debug - Metadata + - Store MetadataSubscriber: - Attribute - Metadata diff --git a/docs/pages/getting_started.md b/docs/pages/getting_started.md index 9318678d9..dc783d052 100644 --- a/docs/pages/getting_started.md +++ b/docs/pages/getting_started.md @@ -297,12 +297,10 @@ $projectionConnection = DriverManager::getConnection([ $mailer = /* your own mailer */; $serializer = DefaultEventSerializer::createFromPaths(['src/Domain/Hotel/Event']); -$aggregateRegistry = (new AttributeAggregateRootRegistryFactory)->create(['src/Domain/Hotel']); $eventStore = new DoctrineDbalStore( $connection, $serializer, - $aggregateRegistry, ); $hotelProjector = new HotelProjector($projectionConnection); diff --git a/src/Aggregate/AggregateHeader.php b/src/Aggregate/AggregateHeader.php index 506a25ffe..d4e9b515d 100644 --- a/src/Aggregate/AggregateHeader.php +++ b/src/Aggregate/AggregateHeader.php @@ -5,11 +5,9 @@ namespace Patchlevel\EventSourcing\Aggregate; use DateTimeImmutable; -use Patchlevel\EventSourcing\Attribute\Header; use Patchlevel\Hydrator\Normalizer\DateTimeImmutableNormalizer; /** @psalm-immutable */ -#[Header('aggregate')] final class AggregateHeader { /** @param positive-int $playhead */ diff --git a/src/Debug/Trace/TraceHeader.php b/src/Debug/Trace/TraceHeader.php index 2151b420a..c0406f1de 100644 --- a/src/Debug/Trace/TraceHeader.php +++ b/src/Debug/Trace/TraceHeader.php @@ -4,10 +4,7 @@ namespace Patchlevel\EventSourcing\Debug\Trace; -use Patchlevel\EventSourcing\Attribute\Header; - /** @experimental */ -#[Header('trace')] final class TraceHeader { /** @param list $traces */ diff --git a/src/Message/Serializer/DefaultHeadersSerializer.php b/src/Message/Serializer/DefaultHeadersSerializer.php index a6331ac9e..cc96f52d6 100644 --- a/src/Message/Serializer/DefaultHeadersSerializer.php +++ b/src/Message/Serializer/DefaultHeadersSerializer.php @@ -60,4 +60,13 @@ public static function createFromPaths(array $paths): static new JsonEncoder(), ); } + + public static function createDefault(): static + { + return new self( + MessageHeaderRegistry::createWithInternalHeaders(), + new MetadataHydrator(), + new JsonEncoder(), + ); + } } diff --git a/src/Metadata/Message/AttributeMessageHeaderRegistryFactory.php b/src/Metadata/Message/AttributeMessageHeaderRegistryFactory.php index 819b0cf34..103e5d432 100644 --- a/src/Metadata/Message/AttributeMessageHeaderRegistryFactory.php +++ b/src/Metadata/Message/AttributeMessageHeaderRegistryFactory.php @@ -31,6 +31,6 @@ public function create(array $paths): MessageHeaderRegistry $result[$aggregateName] = $class; } - return new MessageHeaderRegistry($result); + return MessageHeaderRegistry::createWithInternalHeaders($result); } } diff --git a/src/Metadata/Message/MessageHeaderRegistry.php b/src/Metadata/Message/MessageHeaderRegistry.php index e6821bc11..d4bdb56d3 100644 --- a/src/Metadata/Message/MessageHeaderRegistry.php +++ b/src/Metadata/Message/MessageHeaderRegistry.php @@ -4,6 +4,11 @@ namespace Patchlevel\EventSourcing\Metadata\Message; +use Patchlevel\EventSourcing\Aggregate\AggregateHeader; +use Patchlevel\EventSourcing\Debug\Trace\TraceHeader; +use Patchlevel\EventSourcing\Store\ArchivedHeader; +use Patchlevel\EventSourcing\Store\NewStreamStartHeader; + use function array_flip; use function array_key_exists; @@ -63,4 +68,17 @@ public function headerNames(): array { return $this->classToNameMap; } + + /** @param array $headerNameToClassMap */ + public static function createWithInternalHeaders(array $headerNameToClassMap = []): self + { + $internalHeaders = [ + 'aggregate' => AggregateHeader::class, + 'trace' => TraceHeader::class, + 'archived' => ArchivedHeader::class, + 'newStreamStart' => NewStreamStartHeader::class, + ]; + + return new self($headerNameToClassMap + $internalHeaders); + } } diff --git a/src/Store/ArchivedHeader.php b/src/Store/ArchivedHeader.php index 941de7178..d65906031 100644 --- a/src/Store/ArchivedHeader.php +++ b/src/Store/ArchivedHeader.php @@ -4,10 +4,7 @@ namespace Patchlevel\EventSourcing\Store; -use Patchlevel\EventSourcing\Attribute\Header; - /** @psalm-immutable */ -#[Header('archived')] final class ArchivedHeader { public function __construct( diff --git a/src/Store/DoctrineDbalStore.php b/src/Store/DoctrineDbalStore.php index ab944b9fa..3ecb13c68 100644 --- a/src/Store/DoctrineDbalStore.php +++ b/src/Store/DoctrineDbalStore.php @@ -14,6 +14,7 @@ use Patchlevel\EventSourcing\Aggregate\AggregateHeader; use Patchlevel\EventSourcing\Message\HeaderNotFound; use Patchlevel\EventSourcing\Message\Message; +use Patchlevel\EventSourcing\Message\Serializer\DefaultHeadersSerializer; use Patchlevel\EventSourcing\Message\Serializer\HeadersSerializer; use Patchlevel\EventSourcing\Schema\DoctrineSchemaConfigurator; use Patchlevel\EventSourcing\Serializer\EventSerializer; @@ -36,12 +37,15 @@ final class DoctrineDbalStore implements Store, ArchivableStore, DoctrineSchemaC */ private const MAX_UNSIGNED_SMALL_INT = 65_535; + private readonly HeadersSerializer $headersSerializer; + public function __construct( private readonly Connection $connection, private readonly EventSerializer $eventSerializer, - private readonly HeadersSerializer $headersSerializer, + HeadersSerializer|null $headersSerializer = null, private readonly string $storeTableName = 'eventstore', ) { + $this->headersSerializer = $headersSerializer ?? DefaultHeadersSerializer::createDefault(); } public function load( diff --git a/src/Store/NewStreamStartHeader.php b/src/Store/NewStreamStartHeader.php index c7b8da202..0e84f7226 100644 --- a/src/Store/NewStreamStartHeader.php +++ b/src/Store/NewStreamStartHeader.php @@ -4,10 +4,7 @@ namespace Patchlevel\EventSourcing\Store; -use Patchlevel\EventSourcing\Attribute\Header; - /** @psalm-immutable */ -#[Header('newStreamStart')] final class NewStreamStartHeader { public function __construct( diff --git a/tests/Benchmark/SimpleSetupBench.php b/tests/Benchmark/SimpleSetupBench.php index e6a13c7f5..e93075f23 100644 --- a/tests/Benchmark/SimpleSetupBench.php +++ b/tests/Benchmark/SimpleSetupBench.php @@ -7,7 +7,6 @@ use Patchlevel\EventSourcing\Aggregate\AggregateRootId; use Patchlevel\EventSourcing\EventBus\DefaultEventBus; use Patchlevel\EventSourcing\EventBus\EventBus; -use Patchlevel\EventSourcing\Message\Serializer\DefaultHeadersSerializer; use Patchlevel\EventSourcing\Repository\DefaultRepository; use Patchlevel\EventSourcing\Repository\Repository; use Patchlevel\EventSourcing\Schema\DoctrineSchemaDirector; @@ -37,10 +36,7 @@ public function setUp(): void $this->store = new DoctrineDbalStore( $connection, DefaultEventSerializer::createFromPaths([__DIR__ . '/BasicImplementation/Events']), - DefaultHeadersSerializer::createFromPaths([ - __DIR__ . '/../../src', - __DIR__ . '/BasicImplementation/Events', - ]), + null, 'eventstore', ); diff --git a/tests/Benchmark/SnapshotsBench.php b/tests/Benchmark/SnapshotsBench.php index a8c898b31..31aae3982 100644 --- a/tests/Benchmark/SnapshotsBench.php +++ b/tests/Benchmark/SnapshotsBench.php @@ -7,7 +7,6 @@ use Patchlevel\EventSourcing\Aggregate\AggregateRootId; use Patchlevel\EventSourcing\EventBus\DefaultEventBus; use Patchlevel\EventSourcing\EventBus\EventBus; -use Patchlevel\EventSourcing\Message\Serializer\DefaultHeadersSerializer; use Patchlevel\EventSourcing\Repository\DefaultRepository; use Patchlevel\EventSourcing\Repository\Repository; use Patchlevel\EventSourcing\Schema\DoctrineSchemaDirector; @@ -43,10 +42,7 @@ public function setUp(): void $this->store = new DoctrineDbalStore( $connection, DefaultEventSerializer::createFromPaths([__DIR__ . '/BasicImplementation/Events']), - DefaultHeadersSerializer::createFromPaths([ - __DIR__ . '/../../src', - __DIR__ . '/BasicImplementation/Events', - ]), + null, 'eventstore', ); diff --git a/tests/Benchmark/SplitStreamBench.php b/tests/Benchmark/SplitStreamBench.php index c0b1ced5f..2d6ae6442 100644 --- a/tests/Benchmark/SplitStreamBench.php +++ b/tests/Benchmark/SplitStreamBench.php @@ -7,7 +7,6 @@ use Patchlevel\EventSourcing\Aggregate\AggregateRootId; use Patchlevel\EventSourcing\EventBus\DefaultEventBus; use Patchlevel\EventSourcing\EventBus\EventBus; -use Patchlevel\EventSourcing\Message\Serializer\DefaultHeadersSerializer; use Patchlevel\EventSourcing\Metadata\Event\AttributeEventMetadataFactory; use Patchlevel\EventSourcing\Repository\DefaultRepository; use Patchlevel\EventSourcing\Repository\MessageDecorator\SplitStreamDecorator; @@ -41,10 +40,7 @@ public function setUp(): void $this->store = new DoctrineDbalStore( $connection, DefaultEventSerializer::createFromPaths([__DIR__ . '/BasicImplementation/Events']), - DefaultHeadersSerializer::createFromPaths([ - __DIR__ . '/../../src', - __DIR__ . '/BasicImplementation/Events', - ]), + null, 'eventstore', ); diff --git a/tests/Benchmark/SubscriptionEngineBench.php b/tests/Benchmark/SubscriptionEngineBench.php index c30a0567d..34f3d805a 100644 --- a/tests/Benchmark/SubscriptionEngineBench.php +++ b/tests/Benchmark/SubscriptionEngineBench.php @@ -7,7 +7,6 @@ use Patchlevel\EventSourcing\Aggregate\AggregateRootId; use Patchlevel\EventSourcing\EventBus\DefaultEventBus; use Patchlevel\EventSourcing\EventBus\EventBus; -use Patchlevel\EventSourcing\Message\Serializer\DefaultHeadersSerializer; use Patchlevel\EventSourcing\Repository\DefaultRepository; use Patchlevel\EventSourcing\Repository\Repository; use Patchlevel\EventSourcing\Schema\ChainDoctrineSchemaConfigurator; @@ -46,12 +45,7 @@ public function setUp(): void $this->store = new DoctrineDbalStore( $connection, DefaultEventSerializer::createFromPaths([__DIR__ . '/BasicImplementation/Events']), - DefaultHeadersSerializer::createFromPaths( - [ - __DIR__ . '/BasicImplementation/Events', - __DIR__ . '/../../src', - ], - ), + null, 'eventstore', ); diff --git a/tests/Integration/BankAccountSplitStream/IntegrationTest.php b/tests/Integration/BankAccountSplitStream/IntegrationTest.php index 50a48bc7a..f7a7e9fcc 100644 --- a/tests/Integration/BankAccountSplitStream/IntegrationTest.php +++ b/tests/Integration/BankAccountSplitStream/IntegrationTest.php @@ -6,7 +6,6 @@ use Doctrine\DBAL\Connection; use Patchlevel\EventSourcing\EventBus\DefaultEventBus; -use Patchlevel\EventSourcing\Message\Serializer\DefaultHeadersSerializer; use Patchlevel\EventSourcing\Metadata\AggregateRoot\AggregateRootRegistry; use Patchlevel\EventSourcing\Metadata\Event\AttributeEventMetadataFactory; use Patchlevel\EventSourcing\Repository\DefaultRepositoryManager; @@ -48,10 +47,7 @@ public function testSuccessful(): void $store = new DoctrineDbalStore( $this->connection, DefaultEventSerializer::createFromPaths([__DIR__ . '/Events']), - DefaultHeadersSerializer::createFromPaths([ - __DIR__ . '/../../../src', - __DIR__, - ]), + null, 'eventstore', ); diff --git a/tests/Integration/BasicImplementation/BasicIntegrationTest.php b/tests/Integration/BasicImplementation/BasicIntegrationTest.php index 6d2bce8f2..f150c88b2 100644 --- a/tests/Integration/BasicImplementation/BasicIntegrationTest.php +++ b/tests/Integration/BasicImplementation/BasicIntegrationTest.php @@ -46,8 +46,7 @@ public function testSuccessful(): void $this->connection, DefaultEventSerializer::createFromPaths([__DIR__ . '/Events']), DefaultHeadersSerializer::createFromPaths([ - __DIR__ . '/../../../src', - __DIR__, + __DIR__ . '/Header', ]), 'eventstore', ); @@ -115,8 +114,7 @@ public function testSnapshot(): void $this->connection, DefaultEventSerializer::createFromPaths([__DIR__ . '/Events']), DefaultHeadersSerializer::createFromPaths([ - __DIR__ . '/../../../src', - __DIR__, + __DIR__ . '/Header', ]), 'eventstore', ); diff --git a/tests/Integration/Pipeline/PipelineChangeStoreTest.php b/tests/Integration/Pipeline/PipelineChangeStoreTest.php index 565ed9b98..5f17b49c1 100644 --- a/tests/Integration/Pipeline/PipelineChangeStoreTest.php +++ b/tests/Integration/Pipeline/PipelineChangeStoreTest.php @@ -6,7 +6,6 @@ use Doctrine\DBAL\Connection; use Patchlevel\EventSourcing\EventBus\DefaultEventBus; -use Patchlevel\EventSourcing\Message\Serializer\DefaultHeadersSerializer; use Patchlevel\EventSourcing\Pipeline\Middleware\ExcludeEventMiddleware; use Patchlevel\EventSourcing\Pipeline\Middleware\RecalculatePlayheadMiddleware; use Patchlevel\EventSourcing\Pipeline\Middleware\ReplaceEventMiddleware; @@ -45,15 +44,11 @@ public function tearDown(): void public function testSuccessful(): void { $eventSerializer = DefaultEventSerializer::createFromPaths([__DIR__ . '/Events']); - $headersSerializer = DefaultHeadersSerializer::createFromPaths([ - __DIR__ . '/../../../src', - __DIR__, - ]); $oldStore = new DoctrineDbalStore( $this->connectionOld, $eventSerializer, - $headersSerializer, + null, 'eventstore', ); @@ -67,7 +62,7 @@ public function testSuccessful(): void $newStore = new DoctrineDbalStore( $this->connectionNew, $eventSerializer, - $headersSerializer, + null, 'eventstore', ); diff --git a/tests/Integration/Store/StoreTest.php b/tests/Integration/Store/StoreTest.php index 5ef674048..4af0d3091 100644 --- a/tests/Integration/Store/StoreTest.php +++ b/tests/Integration/Store/StoreTest.php @@ -8,7 +8,6 @@ use Doctrine\DBAL\Connection; use Patchlevel\EventSourcing\Aggregate\AggregateHeader; use Patchlevel\EventSourcing\Message\Message; -use Patchlevel\EventSourcing\Message\Serializer\DefaultHeadersSerializer; use Patchlevel\EventSourcing\Schema\DoctrineSchemaDirector; use Patchlevel\EventSourcing\Serializer\DefaultEventSerializer; use Patchlevel\EventSourcing\Store\DoctrineDbalStore; @@ -32,10 +31,7 @@ public function setUp(): void $this->store = new DoctrineDbalStore( $this->connection, DefaultEventSerializer::createFromPaths([__DIR__ . '/Events']), - DefaultHeadersSerializer::createFromPaths([ - __DIR__ . '/../../../src', - __DIR__, - ]), + null, 'eventstore', ); diff --git a/tests/Integration/Subscription/SubscriptionTest.php b/tests/Integration/Subscription/SubscriptionTest.php index 3640c7c4f..a1aa9bf76 100644 --- a/tests/Integration/Subscription/SubscriptionTest.php +++ b/tests/Integration/Subscription/SubscriptionTest.php @@ -13,7 +13,6 @@ use Patchlevel\EventSourcing\Debug\Trace\TraceStack; use Patchlevel\EventSourcing\EventBus\DefaultEventBus; use Patchlevel\EventSourcing\Message\Message; -use Patchlevel\EventSourcing\Message\Serializer\DefaultHeadersSerializer; use Patchlevel\EventSourcing\Metadata\AggregateRoot\AggregateRootRegistry; use Patchlevel\EventSourcing\Repository\DefaultRepositoryManager; use Patchlevel\EventSourcing\Schema\ChainDoctrineSchemaConfigurator; @@ -64,10 +63,7 @@ public function testHappyPath(): void $store = new DoctrineDbalStore( $this->connection, DefaultEventSerializer::createFromPaths([__DIR__ . '/Events']), - DefaultHeadersSerializer::createFromPaths([ - __DIR__ . '/../../../src', - __DIR__, - ]), + null, 'eventstore', ); @@ -185,10 +181,7 @@ public function testErrorHandling(): void $store = new DoctrineDbalStore( $this->connection, DefaultEventSerializer::createFromPaths([__DIR__ . '/Events']), - DefaultHeadersSerializer::createFromPaths([ - __DIR__ . '/../../../src', - __DIR__, - ]), + null, 'eventstore', ); @@ -318,10 +311,7 @@ public function testProcessor(): void $store = new DoctrineDbalStore( $this->connection, DefaultEventSerializer::createFromPaths([__DIR__ . '/Events']), - DefaultHeadersSerializer::createFromPaths([ - __DIR__ . '/../../../src', - __DIR__, - ]), + null, 'eventstore', ); @@ -433,10 +423,7 @@ public function testBlueGreenDeployment(): void $store = new DoctrineDbalStore( $this->connection, DefaultEventSerializer::createFromPaths([__DIR__ . '/Events']), - DefaultHeadersSerializer::createFromPaths([ - __DIR__ . '/../../../src', - __DIR__, - ]), + null, 'eventstore', ); @@ -595,10 +582,7 @@ public function testBlueGreenDeploymentRollback(): void $store = new DoctrineDbalStore( $this->connection, DefaultEventSerializer::createFromPaths([__DIR__ . '/Events']), - DefaultHeadersSerializer::createFromPaths([ - __DIR__ . '/../../../src', - __DIR__, - ]), + null, 'eventstore', ); diff --git a/tests/Unit/Message/Serializer/HeadersSerializerTest.php b/tests/Unit/Message/Serializer/HeadersSerializerTest.php index a1d8b587f..11951382e 100644 --- a/tests/Unit/Message/Serializer/HeadersSerializerTest.php +++ b/tests/Unit/Message/Serializer/HeadersSerializerTest.php @@ -22,8 +22,7 @@ final class HeadersSerializerTest extends TestCase public function testSerialize(): void { $serializer = DefaultHeadersSerializer::createFromPaths([ - __DIR__ . '/../../../../src', // add our headers - __DIR__ . '/../../Fixture', // add user headers + __DIR__ . '/../../Fixture', ]); $content = $serializer->serialize([ @@ -44,8 +43,7 @@ public function testDeserialize(): void { $serializer = new DefaultHeadersSerializer( (new AttributeMessageHeaderRegistryFactory())->create([ - __DIR__ . '/../../../../src', // add our headers - __DIR__ . '/../../Fixture', // add user headers + __DIR__ . '/../../Fixture', ]), new MetadataHydrator(), new JsonEncoder(), From 60abbe687c8c159deb5b19fc1faaf7a123f132bd Mon Sep 17 00:00:00 2001 From: David Badura Date: Mon, 18 Mar 2024 11:39:41 +0100 Subject: [PATCH 2/2] simplify headers --- deptrac.yaml | 18 ++--- src/Aggregate/AggregateHeader.php | 35 +++++++-- src/Attribute/Header.php | 16 ----- src/Console/Command/ShowAggregateCommand.php | 4 +- src/Console/Command/ShowCommand.php | 4 +- src/Console/Command/WatchCommand.php | 4 +- src/Console/OutputStyle.php | 23 ++---- src/Debug/Trace/TraceHeader.php | 27 ++++++- src/Message/Header.php | 22 ++++++ .../Message/HeaderClassNotRegistered.php | 6 +- .../Message/HeaderNameNotRegistered.php | 6 +- src/Message/Message.php | 10 +-- .../Message/MessageHeaderRegistry.php | 53 +++++++------- .../Serializer/DefaultHeadersSerializer.php | 72 ------------------- src/Message/Serializer/DeserializeFailed.php | 28 -------- src/Message/Serializer/HeadersSerializer.php | 23 ------ .../AttributeMessageHeaderRegistryFactory.php | 36 ---------- .../Message/MessageHeaderRegistryFactory.php | 11 --- src/Store/ArchivedHeader.php | 26 ++++++- src/Store/DoctrineDbalStore.php | 36 +++++----- src/Store/DoctrineDbalStoreStream.php | 15 ++-- src/Store/NewStreamStartHeader.php | 26 ++++++- .../BasicIntegrationTest.php | 14 ++-- .../BasicImplementation/Header/BazHeader.php | 29 ++++++-- .../BasicImplementation/Header/FooHeader.php | 29 ++++++-- .../MessageDecorator/FooMessageDecorator.php | 4 +- .../Serializer/DeserializeFailedTest.php | 34 --------- .../Serializer/HeadersSerializerTest.php | 67 ----------------- 28 files changed, 267 insertions(+), 411 deletions(-) delete mode 100644 src/Attribute/Header.php create mode 100644 src/Message/Header.php rename src/{Metadata => }/Message/HeaderClassNotRegistered.php (62%) rename src/{Metadata => }/Message/HeaderNameNotRegistered.php (61%) rename src/{Metadata => }/Message/MessageHeaderRegistry.php (55%) delete mode 100644 src/Message/Serializer/DefaultHeadersSerializer.php delete mode 100644 src/Message/Serializer/DeserializeFailed.php delete mode 100644 src/Message/Serializer/HeadersSerializer.php delete mode 100644 src/Metadata/Message/AttributeMessageHeaderRegistryFactory.php delete mode 100644 src/Metadata/Message/MessageHeaderRegistryFactory.php delete mode 100644 tests/Unit/Message/Serializer/DeserializeFailedTest.php delete mode 100644 tests/Unit/Message/Serializer/HeadersSerializerTest.php diff --git a/deptrac.yaml b/deptrac.yaml index e76d22ee2..54606e197 100644 --- a/deptrac.yaml +++ b/deptrac.yaml @@ -41,10 +41,6 @@ deptrac: collectors: - type: directory value: src/Metadata/Event/.* - - name: MetadataMessage - collectors: - - type: directory - value: src/Metadata/Message/.* - name: MetadataSubscriber collectors: - type: directory @@ -60,8 +56,6 @@ deptrac: value: MetadataAggregate - type: layer value: MetadataEvent - - type: layer - value: MetadataMessage - type: layer value: MetadataSubscriber - name: Pipeline @@ -96,6 +90,7 @@ deptrac: ruleset: Aggregate: - Attribute + - Message - MetadataAggregate Attribute: Clock: @@ -117,8 +112,9 @@ deptrac: - Attribute - Message Message: - - MetadataMessage - - Serializer + - Aggregate + - Debug + - Store Metadata: MetadataAggregate: - Aggregate @@ -127,12 +123,6 @@ deptrac: MetadataEvent: - Attribute - Metadata - MetadataMessage: - - Aggregate - - Attribute - - Debug - - Metadata - - Store MetadataSubscriber: - Attribute - Metadata diff --git a/src/Aggregate/AggregateHeader.php b/src/Aggregate/AggregateHeader.php index d4e9b515d..2354ce616 100644 --- a/src/Aggregate/AggregateHeader.php +++ b/src/Aggregate/AggregateHeader.php @@ -5,18 +5,45 @@ namespace Patchlevel\EventSourcing\Aggregate; use DateTimeImmutable; -use Patchlevel\Hydrator\Normalizer\DateTimeImmutableNormalizer; +use Patchlevel\EventSourcing\Message\Header; -/** @psalm-immutable */ -final class AggregateHeader +/** + * @template-implements Header + * @psalm-immutable + */ +final class AggregateHeader implements Header { /** @param positive-int $playhead */ public function __construct( public readonly string $aggregateName, public readonly string $aggregateId, public readonly int $playhead, - #[DateTimeImmutableNormalizer] public readonly DateTimeImmutable $recordedOn, ) { } + + public static function name(): string + { + return 'aggregate'; + } + + public static function fromJsonSerialize(array $data): static + { + return new self( + $data['aggregateName'], + $data['aggregateId'], + $data['playhead'], + new DateTimeImmutable($data['recordedOn']), + ); + } + + public function jsonSerialize(): array + { + return [ + 'aggregateName' => $this->aggregateName, + 'aggregateId' => $this->aggregateId, + 'playhead' => $this->playhead, + 'recordedOn' => $this->recordedOn->format(DateTimeImmutable::ATOM), + ]; + } } diff --git a/src/Attribute/Header.php b/src/Attribute/Header.php deleted file mode 100644 index cb0e85824..000000000 --- a/src/Attribute/Header.php +++ /dev/null @@ -1,16 +0,0 @@ -message($this->eventSerializer, $this->headersSerializer, $message); + $console->message($this->eventSerializer, $message); } $stream->close(); diff --git a/src/Console/Command/ShowCommand.php b/src/Console/Command/ShowCommand.php index ee0fbdf40..3d79423f6 100644 --- a/src/Console/Command/ShowCommand.php +++ b/src/Console/Command/ShowCommand.php @@ -6,7 +6,6 @@ use Patchlevel\EventSourcing\Console\InputHelper; use Patchlevel\EventSourcing\Console\OutputStyle; -use Patchlevel\EventSourcing\Message\Serializer\HeadersSerializer; use Patchlevel\EventSourcing\Serializer\EventSerializer; use Patchlevel\EventSourcing\Store\Store; use Symfony\Component\Console\Attribute\AsCommand; @@ -26,7 +25,6 @@ final class ShowCommand extends Command public function __construct( private readonly Store $store, private readonly EventSerializer $eventSerializer, - private readonly HeadersSerializer $headersSerializer, ) { parent::__construct(); } @@ -74,7 +72,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int break 2; } - $console->message($this->eventSerializer, $this->headersSerializer, $message); + $console->message($this->eventSerializer, $message); $stream->next(); diff --git a/src/Console/Command/WatchCommand.php b/src/Console/Command/WatchCommand.php index 58bba45eb..e23cd197a 100644 --- a/src/Console/Command/WatchCommand.php +++ b/src/Console/Command/WatchCommand.php @@ -6,7 +6,6 @@ use Patchlevel\EventSourcing\Console\InputHelper; use Patchlevel\EventSourcing\Console\OutputStyle; -use Patchlevel\EventSourcing\Message\Serializer\HeadersSerializer; use Patchlevel\EventSourcing\Serializer\EventSerializer; use Patchlevel\EventSourcing\Store\Criteria; use Patchlevel\EventSourcing\Store\Store; @@ -26,7 +25,6 @@ final class WatchCommand extends Command public function __construct( private readonly Store $store, private readonly EventSerializer $eventSerializer, - private readonly HeadersSerializer $headersSerializer, ) { parent::__construct(); } @@ -76,7 +74,7 @@ function () use ($console, &$index, $aggregate, $aggregateId): void { ); foreach ($stream as $message) { - $console->message($this->eventSerializer, $this->headersSerializer, $message); + $console->message($this->eventSerializer, $message); $index = $stream->index(); } diff --git a/src/Console/OutputStyle.php b/src/Console/OutputStyle.php index 832fddaa1..815cff4bc 100644 --- a/src/Console/OutputStyle.php +++ b/src/Console/OutputStyle.php @@ -5,7 +5,6 @@ namespace Patchlevel\EventSourcing\Console; use Patchlevel\EventSourcing\Message\Message; -use Patchlevel\EventSourcing\Message\Serializer\HeadersSerializer; use Patchlevel\EventSourcing\Serializer\Encoder\Encoder; use Patchlevel\EventSourcing\Serializer\EventSerializer; use Symfony\Component\Console\Style\SymfonyStyle; @@ -13,13 +12,16 @@ use function array_keys; use function array_values; +use function json_encode; use function sprintf; +use const JSON_PRETTY_PRINT; +use const JSON_THROW_ON_ERROR; + final class OutputStyle extends SymfonyStyle { public function message( EventSerializer $eventSerializer, - HeadersSerializer $headersSerializer, Message $message, ): void { $event = $message->event(); @@ -42,21 +44,8 @@ public function message( return; } - try { - $headers = $headersSerializer->serialize($message->headers(), [Encoder::OPTION_PRETTY_PRINT => true]); - } catch (Throwable $error) { - $this->error( - sprintf( - 'Error while serializing headers: %s', - $error->getMessage(), - ), - ); - - if ($this->isVeryVerbose()) { - $this->throwable($error); - } - - return; + foreach ($message->headers() as $header) { + $headers[$header::name()] = json_encode($header, JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT); } $this->title($data->name); diff --git a/src/Debug/Trace/TraceHeader.php b/src/Debug/Trace/TraceHeader.php index c0406f1de..4171c3220 100644 --- a/src/Debug/Trace/TraceHeader.php +++ b/src/Debug/Trace/TraceHeader.php @@ -4,12 +4,35 @@ namespace Patchlevel\EventSourcing\Debug\Trace; -/** @experimental */ -final class TraceHeader +use Patchlevel\EventSourcing\Message\Header; + +/** + * @experimental + * @template-implements Header}> + * @psalm-immutable + */ +final class TraceHeader implements Header { /** @param list $traces */ public function __construct( public readonly array $traces, ) { } + + public static function name(): string + { + return 'trace'; + } + + public static function fromJsonSerialize(array $data): static + { + return new self($data['traces']); + } + + public function jsonSerialize(): array + { + return [ + 'traces' => $this->traces, + ]; + } } diff --git a/src/Message/Header.php b/src/Message/Header.php new file mode 100644 index 000000000..f9b43489b --- /dev/null +++ b/src/Message/Header.php @@ -0,0 +1,22 @@ + */ + /** @var array */ private array $headers = []; /** @param T $event */ @@ -36,7 +36,7 @@ public static function create(object $event): self return new self($event); } - /** @param iterable $headers */ + /** @param iterable
$headers */ public static function createWithHeaders(object $event, iterable $headers): self { return self::create($event)->withHeaders($headers); @@ -55,7 +55,7 @@ public function event(): object * * @throws HeaderNotFound * - * @template H1 of object + * @template H1 of Header */ public function header(string $name): object { @@ -78,13 +78,13 @@ public function withHeader(object $header): self return $message; } - /** @return list */ + /** @return list
*/ public function headers(): array { return array_values($this->headers); } - /** @param iterable $headers */ + /** @param iterable
$headers */ public function withHeaders(iterable $headers): self { $message = clone $this; diff --git a/src/Metadata/Message/MessageHeaderRegistry.php b/src/Message/MessageHeaderRegistry.php similarity index 55% rename from src/Metadata/Message/MessageHeaderRegistry.php rename to src/Message/MessageHeaderRegistry.php index d4bdb56d3..734eb31f1 100644 --- a/src/Metadata/Message/MessageHeaderRegistry.php +++ b/src/Message/MessageHeaderRegistry.php @@ -2,32 +2,34 @@ declare(strict_types=1); -namespace Patchlevel\EventSourcing\Metadata\Message; +namespace Patchlevel\EventSourcing\Message; use Patchlevel\EventSourcing\Aggregate\AggregateHeader; use Patchlevel\EventSourcing\Debug\Trace\TraceHeader; use Patchlevel\EventSourcing\Store\ArchivedHeader; use Patchlevel\EventSourcing\Store\NewStreamStartHeader; -use function array_flip; use function array_key_exists; +use function array_merge; final class MessageHeaderRegistry { - /** @var array */ - private array $nameToClassMap; + /** @var array> */ + private array $nameToClassMap = []; - /** @var array */ - private array $classToNameMap; + /** @var array, string> */ + private array $classToNameMap = []; - /** @param array $headerNameToClassMap */ - public function __construct(array $headerNameToClassMap) + /** @param list> $headers */ + public function __construct(array $headers) { - $this->nameToClassMap = $headerNameToClassMap; - $this->classToNameMap = array_flip($headerNameToClassMap); + foreach ($headers as $header) { + $this->nameToClassMap[$header::name()] = $header; + $this->classToNameMap[$header] = $header::name(); + } } - /** @param class-string $headerClass */ + /** @param class-string
$headerClass */ public function headerName(string $headerClass): string { if (!array_key_exists($headerClass, $this->classToNameMap)) { @@ -37,7 +39,7 @@ public function headerName(string $headerClass): string return $this->classToNameMap[$headerClass]; } - /** @return class-string */ + /** @return class-string
*/ public function headerClass(string $headerName): string { if (!array_key_exists($headerName, $this->nameToClassMap)) { @@ -57,28 +59,31 @@ public function hasHeaderName(string $headerName): bool return array_key_exists($headerName, $this->nameToClassMap); } - /** @return array */ + /** @return array> */ public function headerClasses(): array { return $this->nameToClassMap; } - /** @return array */ + /** @return array, string> */ public function headerNames(): array { return $this->classToNameMap; } - /** @param array $headerNameToClassMap */ - public static function createWithInternalHeaders(array $headerNameToClassMap = []): self + /** @param list> $headers */ + public static function createWithInternalHeaders(array $headers = []): self { - $internalHeaders = [ - 'aggregate' => AggregateHeader::class, - 'trace' => TraceHeader::class, - 'archived' => ArchivedHeader::class, - 'newStreamStart' => NewStreamStartHeader::class, - ]; - - return new self($headerNameToClassMap + $internalHeaders); + return new self( + array_merge( + $headers, + [ + AggregateHeader::class, + TraceHeader::class, + ArchivedHeader::class, + NewStreamStartHeader::class, + ], + ), + ); } } diff --git a/src/Message/Serializer/DefaultHeadersSerializer.php b/src/Message/Serializer/DefaultHeadersSerializer.php deleted file mode 100644 index cc96f52d6..000000000 --- a/src/Message/Serializer/DefaultHeadersSerializer.php +++ /dev/null @@ -1,72 +0,0 @@ - $headers - * @param array $options - * - * @return array - */ - public function serialize(array $headers, array $options = []): array - { - $serializedHeaders = []; - foreach ($headers as $header) { - $serializedHeaders[$this->messageHeaderRegistry->headerName($header::class)] = $this->encoder->encode($this->hydrator->extract($header), $options); - } - - return $serializedHeaders; - } - - /** - * @param array $serializedHeaders - * - * @return list - */ - public function deserialize(array $serializedHeaders): array - { - $headers = []; - foreach ($serializedHeaders as $headerName => $headerPayload) { - $headers[] = $this->hydrator->hydrate($this->messageHeaderRegistry->headerClass($headerName), $this->encoder->decode($headerPayload)); - } - - return $headers; - } - - /** @param list $paths */ - public static function createFromPaths(array $paths): static - { - return new self( - (new AttributeMessageHeaderRegistryFactory())->create($paths), - new MetadataHydrator(), - new JsonEncoder(), - ); - } - - public static function createDefault(): static - { - return new self( - MessageHeaderRegistry::createWithInternalHeaders(), - new MetadataHydrator(), - new JsonEncoder(), - ); - } -} diff --git a/src/Message/Serializer/DeserializeFailed.php b/src/Message/Serializer/DeserializeFailed.php deleted file mode 100644 index 51afaa20d..000000000 --- a/src/Message/Serializer/DeserializeFailed.php +++ /dev/null @@ -1,28 +0,0 @@ - $headers - * @param array $options - * - * @return array - */ - public function serialize(array $headers, array $options = []): array; - - /** - * @param array $serializedHeaders - * - * @return list - */ - public function deserialize(array $serializedHeaders): array; -} diff --git a/src/Metadata/Message/AttributeMessageHeaderRegistryFactory.php b/src/Metadata/Message/AttributeMessageHeaderRegistryFactory.php deleted file mode 100644 index 103e5d432..000000000 --- a/src/Metadata/Message/AttributeMessageHeaderRegistryFactory.php +++ /dev/null @@ -1,36 +0,0 @@ - $paths */ - public function create(array $paths): MessageHeaderRegistry - { - $classes = (new ClassFinder())->findClassNames($paths); - - $result = []; - - foreach ($classes as $class) { - $reflection = new ReflectionClass($class); - $attributes = $reflection->getAttributes(Header::class); - - if (count($attributes) === 0) { - continue; - } - - $aggregateName = $attributes[0]->newInstance()->name; - $result[$aggregateName] = $class; - } - - return MessageHeaderRegistry::createWithInternalHeaders($result); - } -} diff --git a/src/Metadata/Message/MessageHeaderRegistryFactory.php b/src/Metadata/Message/MessageHeaderRegistryFactory.php deleted file mode 100644 index a2532ebf5..000000000 --- a/src/Metadata/Message/MessageHeaderRegistryFactory.php +++ /dev/null @@ -1,11 +0,0 @@ - $paths */ - public function create(array $paths): MessageHeaderRegistry; -} diff --git a/src/Store/ArchivedHeader.php b/src/Store/ArchivedHeader.php index d65906031..607cc0e06 100644 --- a/src/Store/ArchivedHeader.php +++ b/src/Store/ArchivedHeader.php @@ -4,11 +4,33 @@ namespace Patchlevel\EventSourcing\Store; -/** @psalm-immutable */ -final class ArchivedHeader +use Patchlevel\EventSourcing\Message\Header; + +/** + * @template-implements Header + * @psalm-immutable + */ +final class ArchivedHeader implements Header { public function __construct( public readonly bool $archived, ) { } + + public static function name(): string + { + return 'archived'; + } + + public static function fromJsonSerialize(array $data): static + { + return new self($data['archived']); + } + + public function jsonSerialize(): array + { + return [ + 'archived' => $this->archived, + ]; + } } diff --git a/src/Store/DoctrineDbalStore.php b/src/Store/DoctrineDbalStore.php index 3ecb13c68..7ef818cd7 100644 --- a/src/Store/DoctrineDbalStore.php +++ b/src/Store/DoctrineDbalStore.php @@ -14,14 +14,11 @@ use Patchlevel\EventSourcing\Aggregate\AggregateHeader; use Patchlevel\EventSourcing\Message\HeaderNotFound; use Patchlevel\EventSourcing\Message\Message; -use Patchlevel\EventSourcing\Message\Serializer\DefaultHeadersSerializer; -use Patchlevel\EventSourcing\Message\Serializer\HeadersSerializer; +use Patchlevel\EventSourcing\Message\MessageHeaderRegistry; use Patchlevel\EventSourcing\Schema\DoctrineSchemaConfigurator; use Patchlevel\EventSourcing\Serializer\EventSerializer; use function array_fill; -use function array_filter; -use function array_values; use function count; use function floor; use function implode; @@ -37,15 +34,15 @@ final class DoctrineDbalStore implements Store, ArchivableStore, DoctrineSchemaC */ private const MAX_UNSIGNED_SMALL_INT = 65_535; - private readonly HeadersSerializer $headersSerializer; + private readonly MessageHeaderRegistry $headerRegistry; public function __construct( private readonly Connection $connection, private readonly EventSerializer $eventSerializer, - HeadersSerializer|null $headersSerializer = null, + MessageHeaderRegistry|null $headerRegistry = null, private readonly string $storeTableName = 'eventstore', ) { - $this->headersSerializer = $headersSerializer ?? DefaultHeadersSerializer::createDefault(); + $this->headerRegistry = $headerRegistry ?? MessageHeaderRegistry::createWithInternalHeaders(); } public function load( @@ -71,7 +68,7 @@ public function load( $builder->getParameterTypes(), ), $this->eventSerializer, - $this->headersSerializer, + $this->headerRegistry, $this->connection->getDatabasePlatform(), ); } @@ -201,7 +198,7 @@ function (Connection $connection) use ($messages): void { $parameters[] = $archived; $types[$offset + 7] = $booleanType; - $parameters[] = $this->headersSerializer->serialize($this->getCustomHeaders($message)); + $parameters[] = $this->extractCustomHeaders($message); $types[$offset + 8] = $jsonType; $position++; @@ -315,8 +312,8 @@ public function configureSchema(Schema $schema, Connection $connection): void $table->addIndex(['aggregate', 'aggregate_id', 'playhead', 'archived']); } - /** @return list */ - private function getCustomHeaders(Message $message): array + /** @return array */ + private function extractCustomHeaders(Message $message): array { $filteredHeaders = [ AggregateHeader::class, @@ -324,11 +321,16 @@ private function getCustomHeaders(Message $message): array ArchivedHeader::class, ]; - return array_values( - array_filter( - $message->headers(), - static fn (object $header) => !in_array($header::class, $filteredHeaders, true), - ), - ); + $result = []; + + foreach ($message->headers() as $header) { + if (in_array($header::class, $filteredHeaders, true)) { + continue; + } + + $result[$header::name()] = $header->jsonSerialize(); + } + + return $result; } } diff --git a/src/Store/DoctrineDbalStoreStream.php b/src/Store/DoctrineDbalStoreStream.php index eb5e7be85..3459aeb4c 100644 --- a/src/Store/DoctrineDbalStoreStream.php +++ b/src/Store/DoctrineDbalStoreStream.php @@ -10,7 +10,7 @@ use IteratorAggregate; use Patchlevel\EventSourcing\Aggregate\AggregateHeader; use Patchlevel\EventSourcing\Message\Message; -use Patchlevel\EventSourcing\Message\Serializer\HeadersSerializer; +use Patchlevel\EventSourcing\Message\MessageHeaderRegistry; use Patchlevel\EventSourcing\Serializer\EventSerializer; use Patchlevel\EventSourcing\Serializer\SerializedEvent; use Traversable; @@ -32,11 +32,11 @@ final class DoctrineDbalStoreStream implements Stream, IteratorAggregate public function __construct( Result $result, EventSerializer $eventSerializer, - HeadersSerializer $headersSerializer, + MessageHeaderRegistry $headerRegistry, AbstractPlatform $platform, ) { $this->result = $result; - $this->generator = $this->buildGenerator($result, $eventSerializer, $headersSerializer, $platform); + $this->generator = $this->buildGenerator($result, $eventSerializer, $headerRegistry, $platform); $this->position = null; $this->index = null; } @@ -118,7 +118,7 @@ public function getIterator(): Traversable private function buildGenerator( Result $result, EventSerializer $eventSerializer, - HeadersSerializer $headersSerializer, + MessageHeaderRegistry $headerRegistry, AbstractPlatform $platform, ): Generator { /** @var array{id: positive-int, aggregate: string, aggregate_id: string, playhead: int|string, event: string, payload: string, recorded_on: string, archived: int|string, new_stream_start: int|string, custom_headers: string} $data */ @@ -132,7 +132,12 @@ private function buildGenerator( $this->index = $data['id']; $event = $eventSerializer->deserialize(new SerializedEvent($data['event'], $data['payload'])); - $customHeaders = $headersSerializer->deserialize(DoctrineHelper::normalizeCustomHeaders($data['custom_headers'], $platform)); + $headerData = DoctrineHelper::normalizeCustomHeaders($data['custom_headers'], $platform); + $customHeaders = []; + foreach ($headerData as $name => $value) { + $headerClass = $headerRegistry->headerClass($name); + $customHeaders[] = $headerClass::fromJsonSerialize($value); + } yield Message::create($event) ->withHeader(new AggregateHeader( diff --git a/src/Store/NewStreamStartHeader.php b/src/Store/NewStreamStartHeader.php index 0e84f7226..d8ec7cf6e 100644 --- a/src/Store/NewStreamStartHeader.php +++ b/src/Store/NewStreamStartHeader.php @@ -4,11 +4,33 @@ namespace Patchlevel\EventSourcing\Store; -/** @psalm-immutable */ -final class NewStreamStartHeader +use Patchlevel\EventSourcing\Message\Header; + +/** + * @template-implements Header + * @psalm-immutable + */ +final class NewStreamStartHeader implements Header { public function __construct( public readonly bool $newStreamStart, ) { } + + public static function name(): string + { + return 'newStreamStart'; + } + + public static function fromJsonSerialize(array $data): static + { + return new self($data['newStreamStart']); + } + + public function jsonSerialize(): array + { + return [ + 'newStreamStart' => $this->newStreamStart, + ]; + } } diff --git a/tests/Integration/BasicImplementation/BasicIntegrationTest.php b/tests/Integration/BasicImplementation/BasicIntegrationTest.php index f150c88b2..29ce2f125 100644 --- a/tests/Integration/BasicImplementation/BasicIntegrationTest.php +++ b/tests/Integration/BasicImplementation/BasicIntegrationTest.php @@ -6,7 +6,7 @@ use Doctrine\DBAL\Connection; use Patchlevel\EventSourcing\EventBus\DefaultEventBus; -use Patchlevel\EventSourcing\Message\Serializer\DefaultHeadersSerializer; +use Patchlevel\EventSourcing\Message\MessageHeaderRegistry; use Patchlevel\EventSourcing\Metadata\AggregateRoot\AggregateRootRegistry; use Patchlevel\EventSourcing\Repository\DefaultRepositoryManager; use Patchlevel\EventSourcing\Schema\DoctrineSchemaDirector; @@ -19,6 +19,8 @@ use Patchlevel\EventSourcing\Subscription\Subscriber\MetadataSubscriberAccessorRepository; use Patchlevel\EventSourcing\Tests\DbalManager; use Patchlevel\EventSourcing\Tests\Integration\BasicImplementation\Aggregate\Profile; +use Patchlevel\EventSourcing\Tests\Integration\BasicImplementation\Header\BazHeader; +use Patchlevel\EventSourcing\Tests\Integration\BasicImplementation\Header\FooHeader; use Patchlevel\EventSourcing\Tests\Integration\BasicImplementation\MessageDecorator\FooMessageDecorator; use Patchlevel\EventSourcing\Tests\Integration\BasicImplementation\Processor\SendEmailProcessor; use Patchlevel\EventSourcing\Tests\Integration\BasicImplementation\Projection\ProfileProjector; @@ -45,8 +47,9 @@ public function testSuccessful(): void $store = new DoctrineDbalStore( $this->connection, DefaultEventSerializer::createFromPaths([__DIR__ . '/Events']), - DefaultHeadersSerializer::createFromPaths([ - __DIR__ . '/Header', + MessageHeaderRegistry::createWithInternalHeaders([ + BazHeader::class, + FooHeader::class, ]), 'eventstore', ); @@ -113,8 +116,9 @@ public function testSnapshot(): void $store = new DoctrineDbalStore( $this->connection, DefaultEventSerializer::createFromPaths([__DIR__ . '/Events']), - DefaultHeadersSerializer::createFromPaths([ - __DIR__ . '/Header', + MessageHeaderRegistry::createWithInternalHeaders([ + BazHeader::class, + FooHeader::class, ]), 'eventstore', ); diff --git a/tests/Integration/BasicImplementation/Header/BazHeader.php b/tests/Integration/BasicImplementation/Header/BazHeader.php index 18a9941f3..9cd51a031 100644 --- a/tests/Integration/BasicImplementation/Header/BazHeader.php +++ b/tests/Integration/BasicImplementation/Header/BazHeader.php @@ -2,16 +2,35 @@ declare(strict_types=1); -namespace Integration\BasicImplementation\Header; +namespace Patchlevel\EventSourcing\Tests\Integration\BasicImplementation\Header; -use Patchlevel\EventSourcing\Attribute\Header; +use Patchlevel\EventSourcing\Message\Header; -/** @psalm-immutable */ -#[Header('baz')] -final class BazHeader +/** + * @template-implements Header + * @psalm-immutable + */ +final class BazHeader implements Header { public function __construct( public readonly string $data, ) { } + + public static function name(): string + { + return 'baz'; + } + + public static function fromJsonSerialize(array $data): static + { + return new self($data['data']); + } + + public function jsonSerialize(): array + { + return [ + 'data' => $this->data, + ]; + } } diff --git a/tests/Integration/BasicImplementation/Header/FooHeader.php b/tests/Integration/BasicImplementation/Header/FooHeader.php index 6f8206b65..9b476272e 100644 --- a/tests/Integration/BasicImplementation/Header/FooHeader.php +++ b/tests/Integration/BasicImplementation/Header/FooHeader.php @@ -2,16 +2,35 @@ declare(strict_types=1); -namespace Integration\BasicImplementation\Header; +namespace Patchlevel\EventSourcing\Tests\Integration\BasicImplementation\Header; -use Patchlevel\EventSourcing\Attribute\Header; +use Patchlevel\EventSourcing\Message\Header; -/** @psalm-immutable */ -#[Header('foo')] -final class FooHeader +/** + * @template-implements Header + * @psalm-immutable + */ +final class FooHeader implements Header { public function __construct( public readonly string $data, ) { } + + public static function name(): string + { + return 'foo'; + } + + public static function fromJsonSerialize(array $data): static + { + return new self($data['data']); + } + + public function jsonSerialize(): array + { + return [ + 'data' => $this->data, + ]; + } } diff --git a/tests/Integration/BasicImplementation/MessageDecorator/FooMessageDecorator.php b/tests/Integration/BasicImplementation/MessageDecorator/FooMessageDecorator.php index d1b26f48a..44e304c16 100644 --- a/tests/Integration/BasicImplementation/MessageDecorator/FooMessageDecorator.php +++ b/tests/Integration/BasicImplementation/MessageDecorator/FooMessageDecorator.php @@ -4,10 +4,10 @@ namespace Patchlevel\EventSourcing\Tests\Integration\BasicImplementation\MessageDecorator; -use Integration\BasicImplementation\Header\BazHeader; -use Integration\BasicImplementation\Header\FooHeader; use Patchlevel\EventSourcing\Message\Message; use Patchlevel\EventSourcing\Repository\MessageDecorator\MessageDecorator; +use Patchlevel\EventSourcing\Tests\Integration\BasicImplementation\Header\BazHeader; +use Patchlevel\EventSourcing\Tests\Integration\BasicImplementation\Header\FooHeader; final class FooMessageDecorator implements MessageDecorator { diff --git a/tests/Unit/Message/Serializer/DeserializeFailedTest.php b/tests/Unit/Message/Serializer/DeserializeFailedTest.php deleted file mode 100644 index c6fb4ccb7..000000000 --- a/tests/Unit/Message/Serializer/DeserializeFailedTest.php +++ /dev/null @@ -1,34 +0,0 @@ -getMessage(), - ); - self::assertSame(0, $exception->getCode()); - } - - public function testInvalidData(): void - { - $exception = DeserializeFailed::invalidData('foo'); - - self::assertSame( - 'Invalid data: string', - $exception->getMessage(), - ); - self::assertSame(0, $exception->getCode()); - } -} diff --git a/tests/Unit/Message/Serializer/HeadersSerializerTest.php b/tests/Unit/Message/Serializer/HeadersSerializerTest.php deleted file mode 100644 index 11951382e..000000000 --- a/tests/Unit/Message/Serializer/HeadersSerializerTest.php +++ /dev/null @@ -1,67 +0,0 @@ -serialize([ - new AggregateHeader('profile', '1', 1, new DateTimeImmutable('2020-01-01T20:00:00.000000+0100')), - new ArchivedHeader(false), - ]); - - self::assertEquals( - [ - 'aggregate' => '{"aggregateName":"profile","aggregateId":"1","playhead":1,"recordedOn":"2020-01-01T20:00:00+01:00"}', - 'archived' => '{"archived":false}', - ], - $content, - ); - } - - public function testDeserialize(): void - { - $serializer = new DefaultHeadersSerializer( - (new AttributeMessageHeaderRegistryFactory())->create([ - __DIR__ . '/../../Fixture', - ]), - new MetadataHydrator(), - new JsonEncoder(), - ); - - $deserializedMessage = $serializer->deserialize( - [ - 'aggregate' => '{"aggregateName":"profile","aggregateId":"1","playhead":1,"recordedOn":"2020-01-01T20:00:00+01:00"}', - 'archived' => '{"archived":false}', - ], - ); - - self::assertEquals( - [ - new AggregateHeader('profile', '1', 1, new DateTimeImmutable('2020-01-01T20:00:00.000000+0100')), - new ArchivedHeader(false), - ], - $deserializedMessage, - ); - } -}