Skip to content

Commit b671bbb

Browse files
committed
Add QueryBus integration test which was missing, also add "full cycle" bench which dispatches a command and then query the name.
Fix a deprecation notice regarding `SplObjectStorage`
1 parent 440a663 commit b671bbb

14 files changed

Lines changed: 393 additions & 21 deletions

File tree

phpstan-baseline.neon

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,6 @@ parameters:
4242
count: 1
4343
path: src/Message/Serializer/DefaultHeadersSerializer.php
4444

45-
-
46-
message: '#^Call to an undefined method Patchlevel\\EventSourcing\\Store\\Store\:\:archive\(\)\.$#'
47-
identifier: method.notFound
48-
count: 1
49-
path: src/Repository/DefaultRepository.php
50-
5145
-
5246
message: '#^Parameter \#1 \.\.\.\$streamName of class Patchlevel\\EventSourcing\\Store\\Criteria\\StreamCriterion constructor expects string, string\|null given\.$#'
5347
identifier: argument.type
@@ -168,6 +162,24 @@ parameters:
168162
count: 3
169163
path: src/Subscription/ThrowableToErrorContextTransformer.php
170164

165+
-
166+
message: '#^Property Patchlevel\\EventSourcing\\Tests\\Benchmark\\BasicImplementation\\ProfileWithCommands\:\:\$id is never read, only written\.$#'
167+
identifier: property.onlyWritten
168+
count: 1
169+
path: tests/Benchmark/BasicImplementation/ProfileWithCommands.php
170+
171+
-
172+
message: '#^Cannot access offset ''name'' on array\<string, mixed\>\|false\.$#'
173+
identifier: offsetAccess.nonOffsetAccessible
174+
count: 1
175+
path: tests/Benchmark/BasicImplementation/Projection/ProfileProjector.php
176+
177+
-
178+
message: '#^Method Patchlevel\\EventSourcing\\Tests\\Benchmark\\BasicImplementation\\Projection\\ProfileProjector\:\:getProfileName\(\) should return string but returns mixed\.$#'
179+
identifier: return.type
180+
count: 1
181+
path: tests/Benchmark/BasicImplementation/Projection/ProfileProjector.php
182+
171183
-
172184
message: '#^Parameter \#1 \$id of static method Patchlevel\\EventSourcing\\Tests\\Benchmark\\BasicImplementation\\Profile\:\:create\(\) expects Patchlevel\\EventSourcing\\Tests\\Benchmark\\BasicImplementation\\ProfileId, Patchlevel\\EventSourcing\\Aggregate\\AggregateRootId given\.$#'
173185
identifier: argument.type
@@ -234,6 +246,18 @@ parameters:
234246
count: 1
235247
path: tests/Integration/BasicImplementation/ProfileWithCommands.php
236248

249+
-
250+
message: '#^Cannot access offset ''name'' on array\<string, mixed\>\|false\.$#'
251+
identifier: offsetAccess.nonOffsetAccessible
252+
count: 1
253+
path: tests/Integration/BasicImplementation/Projection/ProfileProjector.php
254+
255+
-
256+
message: '#^Method Patchlevel\\EventSourcing\\Tests\\Integration\\BasicImplementation\\Projection\\ProfileProjector\:\:getProfileName\(\) should return string but returns mixed\.$#'
257+
identifier: return.type
258+
count: 1
259+
path: tests/Integration/BasicImplementation/Projection/ProfileProjector.php
260+
237261
-
238262
message: '#^Call to static method PHPUnit\\Framework\\Assert\:\:assertInstanceOf\(\) with ''Patchlevel\\\\EventSourcing\\\\Tests\\\\Integration\\\\ChildAggregate\\\\Profile'' and Patchlevel\\EventSourcing\\Tests\\Integration\\ChildAggregate\\Profile will always evaluate to true\.$#'
239263
identifier: staticMethod.alreadyNarrowedType

src/Subscription/Engine/SubscriptionManager.php

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,48 +77,48 @@ public function find(SubscriptionCriteria $criteria): array
7777
public function add(Subscription ...$subscriptions): void
7878
{
7979
foreach ($subscriptions as $sub) {
80-
$this->forAdd->attach($sub);
80+
$this->forAdd->offsetSet($sub);
8181
}
8282
}
8383

8484
public function update(Subscription ...$subscriptions): void
8585
{
8686
foreach ($subscriptions as $sub) {
87-
$this->forUpdate->attach($sub);
87+
$this->forUpdate->offsetSet($sub);
8888
}
8989
}
9090

9191
public function remove(Subscription ...$subscriptions): void
9292
{
9393
foreach ($subscriptions as $sub) {
94-
$this->forRemove->attach($sub);
94+
$this->forRemove->offsetSet($sub);
9595
}
9696
}
9797

9898
public function flush(): void
9999
{
100100
foreach ($this->forAdd as $subscription) {
101-
if ($this->forRemove->contains($subscription)) {
101+
if ($this->forRemove->offsetExists($subscription)) {
102102
continue;
103103
}
104104

105105
$this->subscriptionStore->add($subscription);
106106
}
107107

108108
foreach ($this->forUpdate as $subscription) {
109-
if ($this->forAdd->contains($subscription)) {
109+
if ($this->forAdd->offsetExists($subscription)) {
110110
continue;
111111
}
112112

113-
if ($this->forRemove->contains($subscription)) {
113+
if ($this->forRemove->offsetExists($subscription)) {
114114
continue;
115115
}
116116

117117
$this->subscriptionStore->update($subscription);
118118
}
119119

120120
foreach ($this->forRemove as $subscription) {
121-
if ($this->forAdd->contains($subscription)) {
121+
if ($this->forAdd->offsetExists($subscription)) {
122122
continue;
123123
}
124124

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Patchlevel\EventSourcing\Tests\Benchmark\BasicImplementation\Command;
6+
7+
use Patchlevel\EventSourcing\Attribute\Id;
8+
use Patchlevel\EventSourcing\Tests\Benchmark\BasicImplementation\ProfileId;
9+
10+
final class ChangeProfileName
11+
{
12+
public function __construct(
13+
#[Id]
14+
public readonly ProfileId $id,
15+
public readonly string $name,
16+
) {
17+
}
18+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Patchlevel\EventSourcing\Tests\Benchmark\BasicImplementation\Command;
6+
7+
use Patchlevel\EventSourcing\Tests\Benchmark\BasicImplementation\ProfileId;
8+
9+
final class CreateProfile
10+
{
11+
public function __construct(
12+
public readonly ProfileId $id,
13+
public readonly string $name,
14+
) {
15+
}
16+
}

tests/Benchmark/BasicImplementation/Events/NameChanged.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
namespace Patchlevel\EventSourcing\Tests\Benchmark\BasicImplementation\Events;
66

77
use Patchlevel\EventSourcing\Attribute\Event;
8+
use Patchlevel\EventSourcing\Tests\Benchmark\BasicImplementation\ProfileId;
89

910
#[Event('profile.name_changed')]
10-
final class NameChanged
11+
final readonly class NameChanged
1112
{
1213
public function __construct(
14+
public ProfileId $profileId,
1315
public string $name,
1416
) {
1517
}

tests/Benchmark/BasicImplementation/Profile.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public static function create(ProfileId $id, string $name, string|null $email =
3333

3434
public function changeName(string $name): void
3535
{
36-
$this->recordThat(new NameChanged($name));
36+
$this->recordThat(new NameChanged($this->id, $name));
3737
}
3838

3939
public function changeEmail(string $email): void
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Patchlevel\EventSourcing\Tests\Benchmark\BasicImplementation;
6+
7+
use Patchlevel\EventSourcing\Aggregate\BasicAggregateRoot;
8+
use Patchlevel\EventSourcing\Attribute\Aggregate;
9+
use Patchlevel\EventSourcing\Attribute\Apply;
10+
use Patchlevel\EventSourcing\Attribute\Handle;
11+
use Patchlevel\EventSourcing\Attribute\Id;
12+
use Patchlevel\EventSourcing\Attribute\Inject;
13+
use Patchlevel\EventSourcing\Attribute\Snapshot;
14+
use Patchlevel\EventSourcing\Tests\Benchmark\BasicImplementation\Command\ChangeProfileName;
15+
use Patchlevel\EventSourcing\Tests\Benchmark\BasicImplementation\Command\CreateProfile;
16+
use Patchlevel\EventSourcing\Tests\Benchmark\BasicImplementation\Events\NameChanged;
17+
use Patchlevel\EventSourcing\Tests\Benchmark\BasicImplementation\Events\ProfileCreated;
18+
use Psr\Clock\ClockInterface;
19+
20+
#[Aggregate('profile_with_commands')]
21+
#[Snapshot('default', 100)]
22+
final class ProfileWithCommands extends BasicAggregateRoot
23+
{
24+
#[Id]
25+
private ProfileId $id;
26+
private string $name;
27+
28+
#[Handle]
29+
public static function create(
30+
CreateProfile $command,
31+
ClockInterface $clock,
32+
#[Inject('env')]
33+
string $env,
34+
): self {
35+
$self = new self();
36+
$self->recordThat(new ProfileCreated($command->id, $command->name, null));
37+
38+
return $self;
39+
}
40+
41+
#[Handle]
42+
public function changeName(
43+
ChangeProfileName $command,
44+
ClockInterface $clock,
45+
#[Inject('env')]
46+
string $env,
47+
): void {
48+
$this->recordThat(new NameChanged($this->id, $command->name));
49+
}
50+
51+
#[Apply]
52+
protected function applyProfileCreated(ProfileCreated $event): void
53+
{
54+
$this->id = $event->profileId;
55+
$this->name = $event->name;
56+
}
57+
58+
#[Apply]
59+
protected function applyNameChanged(NameChanged $event): void
60+
{
61+
$this->name = $event->name;
62+
}
63+
64+
public function name(): string
65+
{
66+
return $this->name;
67+
}
68+
}

tests/Benchmark/BasicImplementation/Projection/BatchProfileProjector.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
use Patchlevel\EventSourcing\Subscription\Subscriber\SubscriberUtil;
1414
use Patchlevel\EventSourcing\Tests\Benchmark\BasicImplementation\Events\NameChanged;
1515
use Patchlevel\EventSourcing\Tests\Benchmark\BasicImplementation\Events\ProfileCreated;
16-
use Patchlevel\EventSourcing\Tests\Benchmark\BasicImplementation\ProfileId;
1716

1817
#[Projector('profile')]
1918
final class BatchProfileProjector implements BatchableSubscriber
@@ -53,9 +52,9 @@ public function onProfileCreated(ProfileCreated $profileCreated): void
5352
}
5453

5554
#[Subscribe(NameChanged::class)]
56-
public function onNameChanged(NameChanged $nameChanged, ProfileId $profileId): void
55+
public function onNameChanged(NameChanged $nameChanged): void
5756
{
58-
$this->nameChanged[$profileId->toString()] = $nameChanged->name;
57+
$this->nameChanged[$nameChanged->profileId->toString()] = $nameChanged->name;
5958
}
6059

6160
public function table(): string

tests/Benchmark/BasicImplementation/Projection/ProfileProjector.php

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@
55
namespace Patchlevel\EventSourcing\Tests\Benchmark\BasicImplementation\Projection;
66

77
use Doctrine\DBAL\Connection;
8+
use Patchlevel\EventSourcing\Attribute\Answer;
89
use Patchlevel\EventSourcing\Attribute\Projector;
910
use Patchlevel\EventSourcing\Attribute\Setup;
1011
use Patchlevel\EventSourcing\Attribute\Subscribe;
1112
use Patchlevel\EventSourcing\Attribute\Teardown;
1213
use Patchlevel\EventSourcing\Subscription\Subscriber\SubscriberUtil;
1314
use Patchlevel\EventSourcing\Tests\Benchmark\BasicImplementation\Events\NameChanged;
1415
use Patchlevel\EventSourcing\Tests\Benchmark\BasicImplementation\Events\ProfileCreated;
15-
use Patchlevel\EventSourcing\Tests\Benchmark\BasicImplementation\ProfileId;
16+
use Patchlevel\EventSourcing\Tests\Benchmark\BasicImplementation\Query\QueryProfileName;
1617

1718
#[Projector('profile')]
1819
final class ProfileProjector
@@ -49,15 +50,24 @@ public function onProfileCreated(ProfileCreated $profileCreated): void
4950
}
5051

5152
#[Subscribe(NameChanged::class)]
52-
public function onNameChanged(NameChanged $nameChanged, ProfileId $profileId): void
53+
public function onNameChanged(NameChanged $nameChanged): void
5354
{
5455
$this->connection->update(
5556
$this->table(),
5657
['name' => $nameChanged->name],
57-
['id' => $profileId->toString()],
58+
['id' => $nameChanged->profileId->toString()],
5859
);
5960
}
6061

62+
#[Answer]
63+
public function getProfileName(QueryProfileName $queryProfileName): string
64+
{
65+
return $this->connection->fetchAssociative(
66+
"SELECT name FROM {$this->table()} WHERE id = :id;",
67+
['id' => $queryProfileName->id->toString()],
68+
)['name'];
69+
}
70+
6171
public function table(): string
6272
{
6373
return 'projection_' . $this->subscriberId();
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Patchlevel\EventSourcing\Tests\Benchmark\BasicImplementation\Query;
6+
7+
use Patchlevel\EventSourcing\Tests\Benchmark\BasicImplementation\ProfileId;
8+
9+
final readonly class QueryProfileName
10+
{
11+
public function __construct(public ProfileId $id)
12+
{
13+
}
14+
}

0 commit comments

Comments
 (0)