Skip to content

Commit 81ca6ca

Browse files
authored
feat: Add isSubjectPopulated precondition (#58)
1 parent 39d7744 commit 81ca6ca

File tree

3 files changed

+102
-0
lines changed

3 files changed

+102
-0
lines changed

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,20 @@ $writtenEvents = $client->writeEvents([
7979
]);
8080
```
8181

82+
#### Using the `isSubjectPopulated` precondition
83+
84+
If you only want to write events in case a subject (such as `/books/42`) already has at least one event, import the `IsSubjectPopulated` class, use it to create a precondition, and pass it in an array as the second argument:
85+
86+
```php
87+
use Thenativeweb\Eventsourcingdb\IsSubjectPopulated;
88+
89+
$writtenEvents = $client->writeEvents([
90+
// events
91+
], [
92+
new IsSubjectPopulated('/books/42'),
93+
]);
94+
```
95+
8296
#### Using the `isSubjectOnEventId` precondition
8397

8498
If you only want to write events in case the last event of a subject (such as `/books/42`) has a specific ID (e.g., `0`), import the `IsSubjectOnEventId` class, use it to create a precondition, and pass it in an array as the second argument:

src/IsSubjectPopulated.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Thenativeweb\Eventsourcingdb;
6+
7+
use JsonSerializable;
8+
9+
final readonly class IsSubjectPopulated implements JsonSerializable
10+
{
11+
public function __construct(
12+
public string $subject,
13+
) {
14+
}
15+
16+
public function jsonSerialize(): array
17+
{
18+
return [
19+
'type' => 'isSubjectPopulated',
20+
'payload' => [
21+
'subject' => $this->subject,
22+
],
23+
];
24+
}
25+
}

tests/WriteEventsTest.php

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Thenativeweb\Eventsourcingdb\EventCandidate;
88
use Thenativeweb\Eventsourcingdb\IsEventQlQueryTrue;
99
use Thenativeweb\Eventsourcingdb\IsSubjectOnEventId;
10+
use Thenativeweb\Eventsourcingdb\IsSubjectPopulated;
1011
use Thenativeweb\Eventsourcingdb\IsSubjectPristine;
1112
use Thenativeweb\Eventsourcingdb\Tests\Trait\ClientTestTrait;
1213

@@ -104,6 +105,68 @@ public function testSupportsTheIsSubjectPristinePrecondition(): void
104105
);
105106
}
106107

108+
public function testRejectsWritingToEmptySubjectWhenUsingTheIsSubjectPopulatedPrecondition(): void
109+
{
110+
$eventCandidate = new EventCandidate(
111+
source: 'https://www.eventsourcingdb.io',
112+
subject: '/test',
113+
type: 'io.eventsourcingdb.test',
114+
data: [
115+
'value' => 42,
116+
],
117+
);
118+
119+
$this->expectExceptionMessage("Failed to write events, got HTTP status code '409', expected '200'");
120+
121+
$this->client->writeEvents(
122+
[
123+
$eventCandidate,
124+
],
125+
[
126+
new IsSubjectPopulated('/test'),
127+
],
128+
);
129+
}
130+
131+
public function testSupportsTheIsSubjectPopulatedPrecondition(): void
132+
{
133+
$firstEvent = new EventCandidate(
134+
source: 'https://www.eventsourcingdb.io',
135+
subject: '/test',
136+
type: 'io.eventsourcingdb.test',
137+
data: [
138+
'value' => 23,
139+
],
140+
);
141+
142+
$secondEvent = new EventCandidate(
143+
source: 'https://www.eventsourcingdb.io',
144+
subject: '/test',
145+
type: 'io.eventsourcingdb.test',
146+
data: [
147+
'value' => 42,
148+
],
149+
);
150+
151+
$this->client->writeEvents([
152+
$firstEvent,
153+
]);
154+
155+
$writtenEvents = $this->client->writeEvents(
156+
[
157+
$secondEvent,
158+
],
159+
[
160+
new IsSubjectPopulated('/test'),
161+
],
162+
);
163+
164+
$this->assertCount(1, $writtenEvents);
165+
$this->assertInstanceOf(CloudEvent::class, $writtenEvents[0]);
166+
$this->assertSame('1', $writtenEvents[0]->id);
167+
$this->assertSame(42, $writtenEvents[0]->data['value']);
168+
}
169+
107170
public function testSupportsTheIsSubjectOnEventIdPrecondition(): void
108171
{
109172
$firstEvent = new EventCandidate(

0 commit comments

Comments
 (0)