Skip to content

Commit

Permalink
Merge pull request #118 from patchlevel/playhead-missmatch
Browse files Browse the repository at this point in the history
check playhead mismatch
  • Loading branch information
DavidBadura authored Dec 13, 2021
2 parents 4e86b02 + 8c79c18 commit b50566a
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 83 deletions.
2 changes: 1 addition & 1 deletion docs/tests.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ final class ProfileTest extends TestCase
$id = ProfileId::generate();

$events = [
ProfileCreated::raise($id, Email::fromString('foo@email.com')),
ProfileCreated::raise($id, Email::fromString('foo@email.com'))->recordNow(1),
];

$profile = Profile::createFromEventStream($events);
Expand Down
5 changes: 5 additions & 0 deletions src/Aggregate/AggregateRoot.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ public static function createFromEventStream(array $stream): self

foreach ($stream as $message) {
$self->playhead++;

if ($self->playhead !== $message->playhead()) {
throw new PlayheadSequenceMismatch();
}

$self->apply($message);
}

Expand Down
13 changes: 13 additions & 0 deletions src/Aggregate/PlayheadSequenceMismatch.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

declare(strict_types=1);

namespace Patchlevel\EventSourcing\Aggregate;

final class PlayheadSequenceMismatch extends AggregateException
{
public function __construct()
{
parent::__construct('The playhead sequence does not match the aggregate playhead.');
}
}
5 changes: 5 additions & 0 deletions src/Aggregate/SnapshotableAggregateRoot.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ public static function createFromSnapshot(Snapshot $snapshot, array $stream): se

foreach ($stream as $message) {
$self->playhead++;

if ($self->playhead !== $message->playhead()) {
throw new PlayheadSequenceMismatch();
}

$self->apply($message);
}

Expand Down
26 changes: 24 additions & 2 deletions tests/Unit/Aggregate/AggregateRootTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Patchlevel\EventSourcing\Tests\Unit\Aggregate;

use Patchlevel\EventSourcing\Aggregate\PlayheadSequenceMismatch;
use Patchlevel\EventSourcing\Tests\Unit\Fixture\Email;
use Patchlevel\EventSourcing\Tests\Unit\Fixture\Message;
use Patchlevel\EventSourcing\Tests\Unit\Fixture\MessageId;
Expand Down Expand Up @@ -106,19 +107,40 @@ public function testInitliazingState(): void
ProfileCreated::raise(
ProfileId::fromString('1'),
Email::fromString('profile@test.com')
),
)->recordNow(1),
MessagePublished::raise(
ProfileId::fromString('1'),
Message::create(
MessageId::fromString('2'),
'message value'
)
),
)->recordNow(2),
];

$profile = Profile::createFromEventStream($eventStream);

self::assertEquals('1', $profile->id()->toString());
self::assertCount(1, $profile->messages());
}

public function testPlayheadSequenceMismatch(): void
{
$this->expectException(PlayheadSequenceMismatch::class);

$eventStream = [
ProfileCreated::raise(
ProfileId::fromString('1'),
Email::fromString('profile@test.com')
)->recordNow(1),
MessagePublished::raise(
ProfileId::fromString('1'),
Message::create(
MessageId::fromString('2'),
'message value'
)
)->recordNow(1),
];

Profile::createFromEventStream($eventStream);
}
}
131 changes: 51 additions & 80 deletions tests/Unit/Aggregate/SnapshotableAggregateRootTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,135 +4,106 @@

namespace Patchlevel\EventSourcing\Tests\Unit\Aggregate;

use Patchlevel\EventSourcing\Aggregate\PlayheadSequenceMismatch;
use Patchlevel\EventSourcing\Snapshot\Snapshot;
use Patchlevel\EventSourcing\Tests\Unit\Fixture\Email;
use Patchlevel\EventSourcing\Tests\Unit\Fixture\Message;
use Patchlevel\EventSourcing\Tests\Unit\Fixture\MessageId;
use Patchlevel\EventSourcing\Tests\Unit\Fixture\MessagePublished;
use Patchlevel\EventSourcing\Tests\Unit\Fixture\ProfileCreated;
use Patchlevel\EventSourcing\Tests\Unit\Fixture\ProfileId;
use Patchlevel\EventSourcing\Tests\Unit\Fixture\ProfileWithSnapshot;
use PHPUnit\Framework\TestCase;

class SnapshotableAggregateRootTest extends TestCase
{
public function testCreateAggregate(): void
public function testSerialize(): void
{
$id = ProfileId::fromString('1');
$email = Email::fromString('d.a.badura@gmail.com');
$email = Email::fromString('david.badura@patchlevel.de');

$profile = ProfileWithSnapshot::createProfile($id, $email);
$snapshot = $profile->toSnapshot();

self::assertEquals('1', $profile->aggregateRootId());
self::assertEquals(1, $profile->playhead());
self::assertEquals($id, $profile->id());
self::assertEquals($email, $profile->email());

$events = $profile->releaseEvents();

self::assertCount(1, $events);
$event = $events[0];
self::assertEquals(1, $event->playhead());
}

public function testExecuteMethod(): void
{
$profileId = ProfileId::fromString('1');
$email = Email::fromString('d.a.badura@gmail.com');

$messageId = MessageId::fromString('2');

$profile = ProfileWithSnapshot::createProfile($profileId, $email);

$events = $profile->releaseEvents();

self::assertCount(1, $events);
self::assertEquals(1, $profile->playhead());
$event = $events[0];
self::assertEquals(1, $event->playhead());

$profile->publishMessage(
Message::create(
$messageId,
'foo'
)
self::assertEquals('1', $snapshot->id());
self::assertEquals(1, $snapshot->playhead());
self::assertEquals(ProfileWithSnapshot::class, $snapshot->aggregate());
self::assertEquals(
[
'id' => '1',
'email' => 'david.badura@patchlevel.de',
],
$snapshot->payload()
);

self::assertEquals('1', $profile->aggregateRootId());
self::assertEquals(2, $profile->playhead());
self::assertEquals($profileId, $profile->id());
self::assertEquals($email, $profile->email());

$events = $profile->releaseEvents();

self::assertCount(1, $events);
$event = $events[0];
self::assertEquals(2, $event->playhead());
}

public function testEventWithoutApplyMethod(): void
public function testInitliazingState(): void
{
$visitorProfile = ProfileWithSnapshot::createProfile(
ProfileId::fromString('1'),
Email::fromString('visitor@test.com')
);

$events = $visitorProfile->releaseEvents();
self::assertCount(1, $events);
self::assertEquals(1, $visitorProfile->playhead());
$event = $events[0];
self::assertEquals(1, $event->playhead());
$eventStream = [
MessagePublished::raise(
ProfileId::fromString('1'),
Message::create(
MessageId::fromString('2'),
'message value'
)
)->recordNow(2),
];

$visitedProfile = ProfileWithSnapshot::createProfile(
ProfileId::fromString('2'),
Email::fromString('visited@test.com')
$snapshot = new Snapshot(
ProfileWithSnapshot::class,
'1',
1,
[
'id' => '1',
'email' => 'profile@test.com',
]
);

$events = $visitedProfile->releaseEvents();
self::assertCount(1, $events);
self::assertEquals(1, $visitedProfile->playhead());
$event = $events[0];
self::assertEquals(1, $event->playhead());

$visitorProfile->visitProfile($visitedProfile->id());
$profile = ProfileWithSnapshot::createFromSnapshot($snapshot, $eventStream);

$events = $visitedProfile->releaseEvents();
self::assertCount(0, $events);
self::assertEquals(1, $visitedProfile->playhead());
self::assertEquals('1', $profile->id()->toString());
self::assertCount(1, $profile->messages());
}

public function testInitliazingState(): void
public function testCreateFromSnapshot(): void
{
$eventStream = [
ProfileCreated::raise(
ProfileId::fromString('1'),
Email::fromString('profile@test.com')
),
MessagePublished::raise(
ProfileId::fromString('1'),
Message::create(
MessageId::fromString('2'),
'message value'
)
),
)->recordNow(2),
];

$profile = ProfileWithSnapshot::createFromEventStream($eventStream);
$snapshot = new Snapshot(
ProfileWithSnapshot::class,
'1',
1,
[
'id' => '1',
'email' => 'profile@test.com',
]
);

$profile = ProfileWithSnapshot::createFromSnapshot($snapshot, $eventStream);

self::assertEquals('1', $profile->id()->toString());
self::assertCount(1, $profile->messages());
}

public function testCreateFromSnapshot(): void
public function testPlayheadSequenceMismatch(): void
{
$this->expectException(PlayheadSequenceMismatch::class);

$eventStream = [
MessagePublished::raise(
ProfileId::fromString('1'),
Message::create(
MessageId::fromString('2'),
'message value'
)
),
)->recordNow(5),
];

$snapshot = new Snapshot(
Expand Down

0 comments on commit b50566a

Please sign in to comment.