Skip to content

Commit 08a5c9f

Browse files
committed
add only last event filter
1 parent df8ddda commit 08a5c9f

6 files changed

Lines changed: 54 additions & 7 deletions

File tree

src/CommandBus/InstantRetryCommandBus.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use Patchlevel\EventSourcing\Attribute\InstantRetry;
88
use Patchlevel\EventSourcing\Repository\AggregateOutdated;
9+
use Patchlevel\EventSourcing\Store\AppendConditionNotMet;
910
use ReflectionClass;
1011
use Throwable;
1112

@@ -20,7 +21,7 @@ final class InstantRetryCommandBus implements CommandBus
2021
public function __construct(
2122
private readonly CommandBus $commandBus,
2223
private readonly int $defaultMaxRetries = 3,
23-
private readonly array $defaultExceptions = [AggregateOutdated::class],
24+
private readonly array $defaultExceptions = [AggregateOutdated::class, AppendConditionNotMet::class],
2425
) {
2526
}
2627

src/DCB/EventRouter.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ public function subQuery(): SubQuery
5252
$this->tagFilter(),
5353
$this->eventTypeFilter(),
5454
$this->streamName(),
55+
$this->lastEventIsEnough(),
5556
);
5657
}
5758

@@ -182,4 +183,9 @@ public function streamName(): string|null
182183
{
183184
return null;
184185
}
186+
187+
public function lastEventIsEnough(): bool
188+
{
189+
return false;
190+
}
185191
}

src/Store/SubQuery.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ public function __construct(
2323
public readonly array $tags = [],
2424
public readonly array $events = [],
2525
public readonly string|null $streamName = null,
26+
public readonly bool $onlyLastEvent = false,
2627
) {
2728
sort($tags);
2829
sort($events);
@@ -53,7 +54,8 @@ public function equals(self $queryComponent): bool
5354
{
5455
return $this->streamName === $queryComponent->streamName
5556
&& $this->tags === $queryComponent->tags
56-
&& $this->events === $queryComponent->events;
57+
&& $this->events === $queryComponent->events
58+
&& $this->onlyLastEvent === $queryComponent->onlyLastEvent;
5759
}
5860

5961
/**
@@ -67,6 +69,8 @@ private function isSubset(array $needle, array $haystack): bool
6769

6870
public function empty(): bool
6971
{
70-
return $this->streamName === null && $this->tags === [] && $this->events === [];
72+
return $this->streamName === null
73+
&& $this->tags === []
74+
&& $this->events === [];
7175
}
7276
}

src/Store/TaggableDoctrineDbalStore.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -803,11 +803,10 @@ private function unlock(): void
803803
private function uniqueParameterGenerator(): Closure
804804
{
805805
return static function () {
806+
/** @var int $counter */
806807
static $counter = 0;
807808

808-
++$counter;
809-
810-
return 'param' . $counter;
809+
return 'param' . ++$counter;
811810
};
812811
}
813812

@@ -868,6 +867,10 @@ private function queryCondition(QueryBuilder $builder, Query $query): void
868867
);
869868
}
870869

870+
if ($subQuery->onlyLastEvent) {
871+
$subQueryBuilder->select('MAX(id) AS id');
872+
}
873+
871874
$subqueries[] = $subQueryBuilder->getSQL();
872875
}
873876

tests/Integration/DynamicConsistencyBoundary/Invoice/Projection/NextInvoiceNumberProjection.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ public function initialState(): int
2727
#[Apply]
2828
public function applyInvoiceCreated(int $state, InvoiceCreated $event): int
2929
{
30-
return $state + 1;
30+
return $event->invoiceNumber + 1;
31+
}
32+
33+
public function lastEventIsEnough(): bool
34+
{
35+
return true;
3136
}
3237
}

tests/Integration/Store/TaggableDoctrineDbalStoreTest.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,34 @@ public function testQueryTagAndEvent(): void
687687
self::assertStreamEquals([$message1], $stream);
688688
}
689689

690+
public function testOnlyLastEvent(): void
691+
{
692+
$profileId1 = ProfileId::generate();
693+
$profileId2 = ProfileId::generate();
694+
695+
$message1 = Message::create(new ProfileCreated($profileId1, 'test'))
696+
->withHeader(new StreamNameHeader('foo'))
697+
->withHeader(new RecordedOnHeader(new DateTimeImmutable('2020-01-01 00:00:00')))
698+
->withHeader(new TagsHeader(['profile:' . $profileId1->toString()]));
699+
$message2 = Message::create(new ProfileCreated($profileId2, 'test'))
700+
->withHeader(new StreamNameHeader('foo'))
701+
->withHeader(new RecordedOnHeader(new DateTimeImmutable('2020-01-01 00:00:00')))
702+
->withHeader(new TagsHeader(['profile:' . $profileId2->toString()]));
703+
704+
$this->store->append([$message1, $message2]);
705+
706+
$stream = $this->store->query(
707+
new Query(
708+
new SubQuery(
709+
events: [ProfileCreated::class],
710+
onlyLastEvent: true,
711+
),
712+
),
713+
);
714+
715+
self::assertStreamEquals([$message2], $stream);
716+
}
717+
690718
public function testComplexQuery(): void
691719
{
692720
$profileId1 = ProfileId::generate();

0 commit comments

Comments
 (0)