Skip to content

Commit

Permalink
add argument resolver
Browse files Browse the repository at this point in the history
  • Loading branch information
DavidBadura committed Mar 25, 2024
1 parent e3da365 commit bf9fcc3
Show file tree
Hide file tree
Showing 16 changed files with 219 additions and 56 deletions.
26 changes: 3 additions & 23 deletions baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -115,15 +115,14 @@
</PossiblyNullPropertyFetch>
</file>
<file src="src/Subscription/Subscriber/MetadataSubscriberAccessor.php">
<MixedAssignment>
<code><![CDATA[$arguments[]]]></code>
</MixedAssignment>
<MixedMethodCall>
<code><![CDATA[$method]]></code>
<code><![CDATA[$method]]></code>
<code><![CDATA[$method]]></code>
</MixedMethodCall>
<MixedReturnTypeCoercion>
<code><![CDATA[$this->subscriber->$method(...)]]></code>
<code><![CDATA[Closure(Message):void]]></code>
</MixedReturnTypeCoercion>
</file>
<file src="tests/Benchmark/BasicImplementation/Profile.php">
<PropertyNotSetInConstructor>
Expand All @@ -134,15 +133,13 @@
</file>
<file src="tests/Benchmark/PersonalDataBench.php">
<MissingConstructor>
<code><![CDATA[$bus]]></code>
<code><![CDATA[$id]]></code>
<code><![CDATA[$repository]]></code>
<code><![CDATA[$store]]></code>
</MissingConstructor>
</file>
<file src="tests/Benchmark/SimpleSetupBench.php">
<MissingConstructor>
<code><![CDATA[$bus]]></code>
<code><![CDATA[$id]]></code>
<code><![CDATA[$repository]]></code>
<code><![CDATA[$store]]></code>
Expand All @@ -151,7 +148,6 @@
<file src="tests/Benchmark/SnapshotsBench.php">
<MissingConstructor>
<code><![CDATA[$adapter]]></code>
<code><![CDATA[$bus]]></code>
<code><![CDATA[$id]]></code>
<code><![CDATA[$repository]]></code>
<code><![CDATA[$snapshotStore]]></code>
Expand All @@ -163,15 +159,13 @@
<code><![CDATA[$this->id]]></code>
</ArgumentTypeCoercion>
<MissingConstructor>
<code><![CDATA[$bus]]></code>
<code><![CDATA[$id]]></code>
<code><![CDATA[$repository]]></code>
<code><![CDATA[$store]]></code>
</MissingConstructor>
</file>
<file src="tests/Benchmark/SubscriptionEngineBench.php">
<MissingConstructor>
<code><![CDATA[$bus]]></code>
<code><![CDATA[$id]]></code>
<code><![CDATA[$repository]]></code>
<code><![CDATA[$store]]></code>
Expand Down Expand Up @@ -202,13 +196,6 @@
<code><![CDATA[$name]]></code>
</PropertyNotSetInConstructor>
</file>
<file src="tests/Integration/Pipeline/Aggregate/Profile.php">
<PropertyNotSetInConstructor>
<code><![CDATA[$id]]></code>
<code><![CDATA[$privacy]]></code>
<code><![CDATA[$visited]]></code>
</PropertyNotSetInConstructor>
</file>
<file src="tests/Integration/Store/Profile.php">
<PropertyNotSetInConstructor>
<code><![CDATA[$id]]></code>
Expand Down Expand Up @@ -291,13 +278,6 @@
<code><![CDATA[$id]]></code>
</PropertyNotSetInConstructor>
</file>
<file src="tests/Unit/Pipeline/Source/InMemorySourceTest.php">
<InvalidMethodCall>
<code><![CDATA[current]]></code>
<code><![CDATA[current]]></code>
<code><![CDATA[next]]></code>
</InvalidMethodCall>
</file>
<file src="tests/Unit/Subscription/Engine/DefaultSubscriptionEngineTest.php">
<PossiblyUndefinedArrayOffset>
<code><![CDATA[$update1]]></code>
Expand Down
1 change: 1 addition & 0 deletions deptrac.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ deptrac:
- Metadata
- Subscription
Subscription:
- Aggregate
- Attribute
- Clock
- Message
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

namespace Patchlevel\EventSourcing\Subscription\Subscriber\ArgumentResolver;

use Patchlevel\EventSourcing\Aggregate\AggregateHeader;
use Patchlevel\EventSourcing\Message\Message;

use function in_array;

final class AggregateIdArgumentResolver implements ArgumentResolver
{
public function resolve(Argument $argument, Message $message): string
{
return $message->header(AggregateHeader::class)->aggregateId;
}

public function support(Argument $argument, string $eventClass): bool
{
return $argument->type === 'string' && in_array($argument->name, ['aggregateId', 'aggregateRootId']);
}
}
14 changes: 14 additions & 0 deletions src/Subscription/Subscriber/ArgumentResolver/Argument.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

declare(strict_types=1);

namespace Patchlevel\EventSourcing\Subscription\Subscriber\ArgumentResolver;

final class Argument
{
public function __construct(
public readonly string $name,
public readonly string $type,
) {
}
}
14 changes: 14 additions & 0 deletions src/Subscription/Subscriber/ArgumentResolver/ArgumentResolver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

declare(strict_types=1);

namespace Patchlevel\EventSourcing\Subscription\Subscriber\ArgumentResolver;

use Patchlevel\EventSourcing\Message\Message;

interface ArgumentResolver
{
public function resolve(Argument $argument, Message $message): mixed;

public function support(Argument $argument, string $eventClass): bool;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

namespace Patchlevel\EventSourcing\Subscription\Subscriber\ArgumentResolver;

use Patchlevel\EventSourcing\Message\Message;

use function class_exists;
use function is_a;

final class EventArgumentResolver implements ArgumentResolver
{
public function resolve(Argument $argument, Message $message): object
{
return $message->event();
}

public function support(Argument $argument, string $eventClass): bool
{
return class_exists($argument->type) && is_a($eventClass, $argument->type, true);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

namespace Patchlevel\EventSourcing\Subscription\Subscriber\ArgumentResolver;

use Patchlevel\EventSourcing\Message\Message;

final class MessageArgumentResolver implements ArgumentResolver
{
public function resolve(Argument $argument, Message $message): Message
{
return $message;
}

public function support(Argument $argument, string $eventClass): bool
{
return $argument->type === Message::class;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

namespace Patchlevel\EventSourcing\Subscription\Subscriber\ArgumentResolver;

use DateTimeImmutable;
use Patchlevel\EventSourcing\Aggregate\AggregateHeader;
use Patchlevel\EventSourcing\Message\Message;

final class RecordedOnArgumentResolver implements ArgumentResolver
{
public function resolve(Argument $argument, Message $message): DateTimeImmutable
{
return $message->header(AggregateHeader::class)->recordedOn;
}

public function support(Argument $argument, string $eventClass): bool
{
return $argument->type === DateTimeImmutable::class;
}
}
71 changes: 69 additions & 2 deletions src/Subscription/Subscriber/MetadataSubscriberAccessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
use Patchlevel\EventSourcing\Message\Message;
use Patchlevel\EventSourcing\Metadata\Subscriber\SubscriberMetadata;
use Patchlevel\EventSourcing\Subscription\RunMode;
use Patchlevel\EventSourcing\Subscription\Subscriber\ArgumentResolver\Argument;
use Patchlevel\EventSourcing\Subscription\Subscriber\ArgumentResolver\ArgumentResolver;
use ReflectionMethod;
use ReflectionNamedType;
use RuntimeException;

use function array_key_exists;
use function array_map;
Expand All @@ -19,9 +24,11 @@ final class MetadataSubscriberAccessor implements SubscriberAccessor
/** @var array<class-string, list<Closure(Message):void>> */
private array $subscribeCache = [];

/** @param list<ArgumentResolver> $argumentResolvers */
public function __construct(
private readonly object $subscriber,
private readonly SubscriberMetadata $metadata,
private readonly array $argumentResolvers,
) {
}

Expand Down Expand Up @@ -79,11 +86,71 @@ public function subscribeMethods(string $eventClass): array
);

$this->subscribeCache[$eventClass] = array_map(
/** @return Closure(Message):void */
fn (string $method) => $this->subscriber->$method(...),
fn (string $method): Closure => $this->createClosure($eventClass, $method),
$methods,
);

return $this->subscribeCache[$eventClass];
}

/**
* @param class-string $eventClass
*
* @return Closure(Message):void
*/
private function createClosure(string $eventClass, string $method): Closure
{
$resolvers = $this->resolvers($eventClass, $method);

return function (Message $message) use ($method, $resolvers): void {
$arguments = [];

foreach ($resolvers as $resolver) {
$arguments[] = $resolver($message);
}

$this->subscriber->$method(...$arguments);
};
}

/**
* @param class-string $eventClass
*
* @return list<Closure(Message):mixed>
*/
private function resolvers(string $eventClass, string $method): array
{
$resolvers = [];

$reflection = new ReflectionMethod($this->subscriber, $method);

foreach ($reflection->getParameters() as $parameter) {
$type = $parameter->getType();

if (!$type instanceof ReflectionNamedType) {
throw new RuntimeException('parameter type is required');
}

$argument = new Argument(
$parameter->getName(),
$type->getName(),
);

foreach ($this->argumentResolvers as $resolver) {
if (!$resolver->support($argument, $eventClass)) {
continue;
}

$resolvers[] = static function (Message $message) use ($resolver, $argument): mixed {
return $resolver->resolve($argument, $message);
};

continue 2;
}

throw new RuntimeException('no argument resolver found');
}

return $resolvers;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,12 @@ private function subscriberAccessorMap(): array

foreach ($this->subscribers as $subscriber) {
$metadata = $this->metadataFactory->metadata($subscriber::class);
$this->subscribersMap[$metadata->id] = new MetadataSubscriberAccessor($subscriber, $metadata);
$this->subscribersMap[$metadata->id] = new MetadataSubscriberAccessor($subscriber, $metadata, [
new ArgumentResolver\MessageArgumentResolver(),
new ArgumentResolver\EventArgumentResolver(),
new ArgumentResolver\AggregateIdArgumentResolver(),
new ArgumentResolver\RecordedOnArgumentResolver(),
]);
}

return $this->subscribersMap;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,14 @@
namespace Patchlevel\EventSourcing\Tests\Benchmark\BasicImplementation\Projection;

use Doctrine\DBAL\Connection;
use Patchlevel\EventSourcing\Aggregate\AggregateHeader;
use Patchlevel\EventSourcing\Attribute\Projector;
use Patchlevel\EventSourcing\Attribute\Setup;
use Patchlevel\EventSourcing\Attribute\Subscribe;
use Patchlevel\EventSourcing\Attribute\Teardown;
use Patchlevel\EventSourcing\Message\Message;
use Patchlevel\EventSourcing\Subscription\Subscriber\SubscriberUtil;
use Patchlevel\EventSourcing\Tests\Benchmark\BasicImplementation\Events\NameChanged;
use Patchlevel\EventSourcing\Tests\Benchmark\BasicImplementation\Events\ProfileCreated;

use function assert;

#[Projector('profile')]
final class ProfileProjector
{
Expand All @@ -40,12 +36,8 @@ public function drop(): void
}

#[Subscribe(ProfileCreated::class)]
public function onProfileCreated(Message $message): void
public function onProfileCreated(ProfileCreated $profileCreated): void
{
$profileCreated = $message->event();

assert($profileCreated instanceof ProfileCreated);

$this->connection->insert(
$this->table(),
[
Expand All @@ -56,16 +48,12 @@ public function onProfileCreated(Message $message): void
}

#[Subscribe(NameChanged::class)]
public function onNameChanged(Message $message): void
public function onNameChanged(NameChanged $nameChanged, string $aggregateRootId): void
{
$nameChanged = $message->event();

assert($nameChanged instanceof NameChanged);

$this->connection->update(
$this->table(),
['name' => $nameChanged->name],
['id' => $message->header(AggregateHeader::class)->aggregateId],
['id' => $aggregateRootId],
);
}

Expand Down
Loading

0 comments on commit bf9fcc3

Please sign in to comment.