diff --git a/phpstan.neon b/phpstan.neon index 64e5e97c..93f52b64 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,5 +1,5 @@ parameters: - level: 2 + level: 3 paths: - src/ - tests/ diff --git a/psalm.xml b/psalm.xml index 5df66af5..a3b7bdbb 100644 --- a/psalm.xml +++ b/psalm.xml @@ -1,6 +1,6 @@ */ private function eventSourcedEntities(): iterable { diff --git a/src/Domain/Envelope.php b/src/Domain/Envelope.php index 382b79cb..342a051a 100644 --- a/src/Domain/Envelope.php +++ b/src/Domain/Envelope.php @@ -16,6 +16,8 @@ use Streak\Domain\Id\UUID; /** + * @template T of object + * * @author Alan Gabriel Bem */ interface Envelope extends ValueObject @@ -24,14 +26,20 @@ public function uuid(): UUID; public function name(): string; + /** + * @return T + */ public function message(); /** * @param string $name * - * @return float|int|string|null + * @return null|scalar */ public function get($name); + /** + * @return array + */ public function metadata(): array; } diff --git a/src/Domain/Event/Envelope.php b/src/Domain/Event/Envelope.php index 47ac1484..d319066d 100644 --- a/src/Domain/Event/Envelope.php +++ b/src/Domain/Event/Envelope.php @@ -20,7 +20,8 @@ /** * @author Alan Gabriel Bem * - * @template T of Event + * @template TMessage as Event + * @implements Domain\Envelope * * @see \Streak\Domain\Event\EnvelopeTest */ @@ -33,26 +34,44 @@ final class Envelope implements Domain\Envelope public const METADATA_PRODUCER_ID = 'producer_id'; public const METADATA_ENTITY_TYPE = 'entity_type'; public const METADATA_ENTITY_ID = 'entity_id'; - private array $metadata = []; /** - * @param T $message + * @var-phpstan non-empty-array + * @var-psalm non-empty-array&array{ + * uuid: non-empty-string, + * name: non-empty-string, + * producer_type: non-empty-string, + * producer_id: non-empty-string, + * entity_type: non-empty-string, + * entity_id: non-empty-string, + * version?: positive-int, + * } + */ + private array $metadata; + + /** + * @param TMessage $message */ public function __construct(UUID $uuid, string $name, private Event $message, Domain\Id $producerId, Domain\Id $entityId, ?int $version = null) { - $this->metadata[self::METADATA_UUID] = $uuid->toString(); - $this->metadata[self::METADATA_NAME] = $name; - $this->metadata[self::METADATA_PRODUCER_TYPE] = $producerId::class; - $this->metadata[self::METADATA_PRODUCER_ID] = $producerId->toString(); - $this->metadata[self::METADATA_ENTITY_TYPE] = $entityId::class; - $this->metadata[self::METADATA_ENTITY_ID] = $entityId->toString(); + $this->metadata = [ + self::METADATA_UUID => $uuid->toString(), + self::METADATA_NAME => $name, + self::METADATA_PRODUCER_TYPE => $producerId::class, + self::METADATA_PRODUCER_ID => $producerId->toString(), + self::METADATA_ENTITY_TYPE => $entityId::class, + self::METADATA_ENTITY_ID => $entityId->toString(), + ]; if (null !== $version) { $this->metadata[self::METADATA_VERSION] = $version; } } /** - * @return Envelope + * @template TEvent of Event + * @param TEvent $message + * + * @return self */ public static function new(Event $message, Domain\Id $producerId, ?int $version = null): self { @@ -61,18 +80,15 @@ public static function new(Event $message, Domain\Id $producerId, ?int $version public function uuid(): UUID { - return new UUID($this->get(self::METADATA_UUID)); + return new UUID($this->metadata[self::METADATA_UUID]); } public function name(): string { - return $this->get(self::METADATA_NAME); + return $this->metadata[self::METADATA_NAME]; } - /** - * @return T - */ - public function message(): Event + public function message() { return $this->message; } @@ -84,7 +100,7 @@ public function producerId(): Domain\Id /** @var class-string $class */ /** @phpstan-var class-string $class */ /** @psalm-var class-string $class */ - return $class::fromString($this->get(self::METADATA_PRODUCER_ID)); + return $class::fromString((string) $this->get(self::METADATA_PRODUCER_ID)); } public function entityId(): Domain\Id @@ -94,12 +110,12 @@ public function entityId(): Domain\Id /** @var class-string $class */ /** @phpstan-var class-string $class */ /** @psalm-var class-string $class */ - return $class::fromString($this->get(self::METADATA_ENTITY_ID)); + return $class::fromString((string) $this->get(self::METADATA_ENTITY_ID)); } public function version(): ?int { - return $this->get(self::METADATA_VERSION); + return $this->metadata[self::METADATA_VERSION] ?? null; } public function set(string $name, $value): self diff --git a/src/Domain/Event/Listener/Factory.php b/src/Domain/Event/Listener/Factory.php index 1ca6760d..6a42573d 100644 --- a/src/Domain/Event/Listener/Factory.php +++ b/src/Domain/Event/Listener/Factory.php @@ -15,20 +15,25 @@ use Streak\Domain\Event; use Streak\Domain\Event\Exception\InvalidEventGiven; -use Streak\Domain\Event\Listener; use Streak\Domain\Exception\InvalidIdGiven; /** + * @template T of Event\Listener + * * @author Alan Gabriel Bem */ interface Factory { /** + * @return T + * * @throws InvalidIdGiven */ - public function create(Listener\Id $id): Listener; + public function create(Event\Listener\Id $id): Event\Listener; /** + * @return T + * * @throws InvalidEventGiven */ public function createFor(Event\Envelope $event): Event\Listener; diff --git a/src/Domain/Event/Sourced/Entity/Helper.php b/src/Domain/Event/Sourced/Entity/Helper.php index 61e2efcf..6be8b7e2 100644 --- a/src/Domain/Event/Sourced/Entity/Helper.php +++ b/src/Domain/Event/Sourced/Entity/Helper.php @@ -42,7 +42,7 @@ public function applyEvent(Event\Envelope $event): void } /** - * @return Event\Sourced\Entity[] + * @return \Generator */ public function extractEventSourcedEntities(): iterable { @@ -128,6 +128,8 @@ private static function applyEventByArgumentType(Event\Envelope $event, object & /** * Extract event sourced entities recursively. + * + * @return \Generator */ private static function doExtractEventSourcedEntities(object $object, array &$ignored = []): iterable { diff --git a/src/Domain/Event/Stream.php b/src/Domain/Event/Stream.php index d64bee80..7db940b8 100644 --- a/src/Domain/Event/Stream.php +++ b/src/Domain/Event/Stream.php @@ -17,6 +17,8 @@ /** * @author Alan Gabriel Bem + * + * @psalm-immutable */ interface Stream extends \Traversable { diff --git a/src/Domain/Event/Subscription/Factory.php b/src/Domain/Event/Subscription/Factory.php index b5ddf677..40d3a030 100644 --- a/src/Domain/Event/Subscription/Factory.php +++ b/src/Domain/Event/Subscription/Factory.php @@ -16,9 +16,14 @@ use Streak\Domain\Event; /** + * @template T of Event\Subscription + * * @author Alan Gabriel Bem */ interface Factory { + /** + * @return T + */ public function create(Event\Listener $listener): Event\Subscription; } diff --git a/src/Infrastructure/Domain/AggregateRoot/Snapshotter/Storage/RedisStorage.php b/src/Infrastructure/Domain/AggregateRoot/Snapshotter/Storage/RedisStorage.php index af3316d1..9055aa3c 100644 --- a/src/Infrastructure/Domain/AggregateRoot/Snapshotter/Storage/RedisStorage.php +++ b/src/Infrastructure/Domain/AggregateRoot/Snapshotter/Storage/RedisStorage.php @@ -20,6 +20,8 @@ /** * @author Alan Gabriel Bem + * + * @see \Streak\Infrastructure\Domain\AggregateRoot\Snapshotter\Storage\RedisStorageTest */ final class RedisStorage implements Storage, Resettable { @@ -38,12 +40,17 @@ public function find(AggregateRoot $aggregate): string throw new SnapshotNotFound($aggregate); } + // Redis::get() can return Redis instance when it's in multi() mode. + if ($snapshot instanceof \Redis) { + throw new SnapshotNotFound($aggregate); + } + return $snapshot; } public function store(AggregateRoot $aggregate, string $snapshot): void { - $this->redis->set($this->key($aggregate), (string) $snapshot); + $this->redis->set($this->key($aggregate), $snapshot); } public function reset(): bool diff --git a/src/Infrastructure/Domain/Event/InMemoryStream.php b/src/Infrastructure/Domain/Event/InMemoryStream.php index 102741f1..e3e51d27 100644 --- a/src/Infrastructure/Domain/Event/InMemoryStream.php +++ b/src/Infrastructure/Domain/Event/InMemoryStream.php @@ -19,6 +19,8 @@ /** * @author Alan Gabriel Bem * + * @psalm-immutable + * * @see \Streak\Infrastructure\Domain\Event\InMemoryStreamTest */ final class InMemoryStream implements \IteratorAggregate, Event\Stream diff --git a/src/Infrastructure/Domain/Event/LoggingListener/Factory.php b/src/Infrastructure/Domain/Event/LoggingListener/Factory.php index 761a368d..798e628c 100644 --- a/src/Infrastructure/Domain/Event/LoggingListener/Factory.php +++ b/src/Infrastructure/Domain/Event/LoggingListener/Factory.php @@ -18,6 +18,8 @@ use Streak\Infrastructure\Domain\Event\LoggingListener; /** + * @implements Event\Listener\Factory + * * @author Alan Gabriel Bem * * @see \Streak\Infrastructure\Domain\Event\LoggingListener\FactoryTest @@ -28,14 +30,14 @@ public function __construct(private Event\Listener\Factory $factory, private Log { } - public function create(Event\Listener\Id $id): Event\Listener + public function create(Event\Listener\Id $id): LoggingListener { $saga = $this->factory->create($id); return new LoggingListener($saga, $this->logger); } - public function createFor(Event\Envelope $event): Event\Listener + public function createFor(Event\Envelope $event): LoggingListener { $listener = $this->factory->createFor($event); diff --git a/src/Infrastructure/Domain/Event/Sourced/Subscription/InMemoryState.php b/src/Infrastructure/Domain/Event/Sourced/Subscription/InMemoryState.php index 3364262a..368a28b3 100644 --- a/src/Infrastructure/Domain/Event/Sourced/Subscription/InMemoryState.php +++ b/src/Infrastructure/Domain/Event/Sourced/Subscription/InMemoryState.php @@ -55,7 +55,7 @@ public function get(string $name) return $this->state[$name]; } - public function set(string $name, $value): State + public function set(string $name, $value): self { $this->validate($name, $value); diff --git a/src/Infrastructure/Domain/Event/Subscription/CommittingSubscription/Factory.php b/src/Infrastructure/Domain/Event/Subscription/CommittingSubscription/Factory.php index b46bfc3f..3eb9460c 100644 --- a/src/Infrastructure/Domain/Event/Subscription/CommittingSubscription/Factory.php +++ b/src/Infrastructure/Domain/Event/Subscription/CommittingSubscription/Factory.php @@ -19,6 +19,8 @@ use Streak\Infrastructure\Domain\UnitOfWork; /** + * @implements Event\Subscription\Factory + * * @author Alan Gabriel Bem * * @see \Streak\Infrastructure\Domain\Event\Subscription\CommittingSubscription\FactoryTest @@ -29,7 +31,7 @@ public function __construct(private Subscription\Factory $factory, private UnitO { } - public function create(Event\Listener $listener): Event\Subscription + public function create(Event\Listener $listener): CommittingSubscription { $subscription = $this->factory->create($listener); diff --git a/src/Infrastructure/Domain/Event/Subscription/DAO.php b/src/Infrastructure/Domain/Event/Subscription/DAO.php index 8087dcc0..465ae458 100644 --- a/src/Infrastructure/Domain/Event/Subscription/DAO.php +++ b/src/Infrastructure/Domain/Event/Subscription/DAO.php @@ -30,7 +30,7 @@ public function exists(Listener\Id $id): bool; /** * @param string[] $types * - * @return DAO\Subscription[] + * @return iterable */ public function all(array $types = [], ?bool $completed = null): iterable; } diff --git a/src/Infrastructure/Domain/Event/Subscription/DAO/DbalPostgresDAO.php b/src/Infrastructure/Domain/Event/Subscription/DAO/DbalPostgresDAO.php index 409ebb42..47874063 100644 --- a/src/Infrastructure/Domain/Event/Subscription/DAO/DbalPostgresDAO.php +++ b/src/Infrastructure/Domain/Event/Subscription/DAO/DbalPostgresDAO.php @@ -30,8 +30,13 @@ */ class DbalPostgresDAO implements DAO { - public function __construct(private Subscription\Factory $subscriptions, private Event\Listener\Factory $listeners, private Connection $connection, private Event\Converter $converter) - { + public function __construct( + /** @var Subscription\Factory */ + private Subscription\Factory $subscriptions, + private Event\Listener\Factory $listeners, + private Connection $connection, + private Event\Converter $converter + ) { } /** @@ -69,11 +74,9 @@ public function exists(Listener\Id $id): bool } /** - * @param string[] $types + * @return \Generator * * @throws \Doctrine\DBAL\DBALException - * - * @return Subscription[] */ public function all(array $types = [], ?bool $completed = null): iterable { @@ -186,7 +189,7 @@ public function drop(): void $statement->execute(); } - private function fromRow($row): Subscription + private function fromRow($row): DAO\Subscription { $id = $row['subscription_type']; $id = $id::fromString($row['subscription_id']); @@ -306,11 +309,9 @@ private function doSave(DAO\Subscription $subscription): void } /** - * * @throws \Doctrine\DBAL\DBALException - * @return \Streak\Infrastructure\Domain\Event\Subscription\DAO\Subscription|null */ - private function doOne(Event\Listener\Id $id) + private function doOne(Event\Listener\Id $id): ?DAO\Subscription { $sql = 'SELECT subscription_type, subscription_id, subscription_version, state, started_by, started_at, last_processed_event, last_event_processed_at, completed, paused_at FROM subscriptions WHERE subscription_type = :subscription_type AND subscription_id = :subscription_id LIMIT 1'; @@ -354,6 +355,8 @@ private function doExists(Listener\Id $id): bool } /** + * @return \Generator + * * @throws \Doctrine\DBAL\DBALException */ private function doAll(array $types, ?bool $completed): \Generator diff --git a/src/Infrastructure/Domain/Event/Subscription/DAO/InMemoryDAO.php b/src/Infrastructure/Domain/Event/Subscription/DAO/InMemoryDAO.php index 56360950..cac5f52f 100644 --- a/src/Infrastructure/Domain/Event/Subscription/DAO/InMemoryDAO.php +++ b/src/Infrastructure/Domain/Event/Subscription/DAO/InMemoryDAO.php @@ -60,7 +60,7 @@ public function exists(Listener\Id $id): bool public function all(array $types = [], ?bool $completed = null): iterable { - foreach ($this->subscriptions as $key => $stored) { + foreach ($this->subscriptions as $stored) { if (\count($types)) { $type = $stored->id()::class; if (false === \in_array($type, $types)) { diff --git a/src/Infrastructure/Domain/Event/Subscription/DAO/Subscription.php b/src/Infrastructure/Domain/Event/Subscription/DAO/Subscription.php index 3c09522f..29b2e418 100644 --- a/src/Infrastructure/Domain/Event/Subscription/DAO/Subscription.php +++ b/src/Infrastructure/Domain/Event/Subscription/DAO/Subscription.php @@ -16,6 +16,7 @@ use Streak\Domain\Clock; use Streak\Domain\Event; use Streak\Domain\Event\Listener; +use Streak\Domain\Event\Listener\State; use Streak\Domain\Event\Subscription\Exception; use Streak\Domain\EventStore; use Streak\Infrastructure\Domain\Event\Sourced\Subscription\InMemoryState; @@ -28,12 +29,12 @@ class Subscription implements Event\Subscription { private const LIMIT_TO_INITIAL_STREAM = 0; - private InMemoryState $state; + private State $state; private ?Event\Envelope $startedBy = null; - private ?\DateTimeImmutable $startedAt = null; + private ?\DateTimeImmutable $startedAt = null; // @TODO: check if needed private ?\DateTimeImmutable $pausedAt = null; private ?Event\Envelope $lastProcessedEvent = null; - private ?\DateTimeImmutable $lastEventProcessedAt = null; + private ?\DateTimeImmutable $lastEventProcessedAt = null; // @TODO: check if needed private int $version = 0; private bool $completed = false; diff --git a/src/Infrastructure/Domain/Event/Subscription/DAO/Subscription/Factory.php b/src/Infrastructure/Domain/Event/Subscription/DAO/Subscription/Factory.php index 3568288c..ccfc119e 100644 --- a/src/Infrastructure/Domain/Event/Subscription/DAO/Subscription/Factory.php +++ b/src/Infrastructure/Domain/Event/Subscription/DAO/Subscription/Factory.php @@ -15,9 +15,11 @@ use Streak\Domain\Clock; use Streak\Domain\Event; -use Streak\Infrastructure\Domain\Event\Subscription\DAO\Subscription; +use Streak\Infrastructure\Domain\Event\Subscription\DAO; /** + * @implements Event\Subscription\Factory + * * @author Alan Gabriel Bem * * @see \Streak\Infrastructure\Domain\Event\Subscription\DAO\Subscription\FactoryTest @@ -28,8 +30,8 @@ public function __construct(private Clock $clock) { } - public function create(Event\Listener $listener): Event\Subscription + public function create(Event\Listener $listener): DAO\Subscription { - return new Subscription($listener, $this->clock); + return new DAO\Subscription($listener, $this->clock); } } diff --git a/src/Infrastructure/Domain/Event/Subscription/DbalTransactionalSubscription/Factory.php b/src/Infrastructure/Domain/Event/Subscription/DbalTransactionalSubscription/Factory.php index 86c89620..0fc0e64c 100644 --- a/src/Infrastructure/Domain/Event/Subscription/DbalTransactionalSubscription/Factory.php +++ b/src/Infrastructure/Domain/Event/Subscription/DbalTransactionalSubscription/Factory.php @@ -18,6 +18,8 @@ use Streak\Infrastructure\Domain\Event\Subscription\DbalTransactionalSubscription; /** + * @implements Event\Subscription\Factory + * * @author Alan Gabriel Bem * * @see \Streak\Infrastructure\Domain\Event\Subscription\DbalTransactionalSubscription\FactoryTest @@ -35,7 +37,7 @@ public function __construct(private Event\Subscription\Factory $factory, private $this->maxTransactionSize = $maxTransactionSize; } - public function create(Event\Listener $listener): Event\Subscription + public function create(Event\Listener $listener): DbalTransactionalSubscription { $subscription = $this->factory->create($listener); diff --git a/src/Infrastructure/Domain/EventBus/InMemoryEventBus.php b/src/Infrastructure/Domain/EventBus/InMemoryEventBus.php index 1e12e4cc..01277abf 100644 --- a/src/Infrastructure/Domain/EventBus/InMemoryEventBus.php +++ b/src/Infrastructure/Domain/EventBus/InMemoryEventBus.php @@ -48,7 +48,7 @@ public function add(Event\Listener $listener): void } } - $this->listeners[] = $listener; + $this->listeners->enqueue($listener); } public function remove(Event\Listener $listener): void diff --git a/src/Infrastructure/Domain/EventStore/DbalPostgresEventStore.php b/src/Infrastructure/Domain/EventStore/DbalPostgresEventStore.php index 43ec1b1d..52afdece 100644 --- a/src/Infrastructure/Domain/EventStore/DbalPostgresEventStore.php +++ b/src/Infrastructure/Domain/EventStore/DbalPostgresEventStore.php @@ -26,6 +26,8 @@ /** * @author Alan Gabriel Bem * + * @psalm-immutable + * * @see \Streak\Infrastructure\Domain\EventStore\DbalPostgresEventStoreTest */ class DbalPostgresEventStore implements \Iterator, EventStore, Event\Stream, Schemable, Schema diff --git a/src/Infrastructure/Domain/UnitOfWork/SubscriptionDAOUnitOfWork.php b/src/Infrastructure/Domain/UnitOfWork/SubscriptionDAOUnitOfWork.php index 186cfd3a..69f2b0ae 100644 --- a/src/Infrastructure/Domain/UnitOfWork/SubscriptionDAOUnitOfWork.php +++ b/src/Infrastructure/Domain/UnitOfWork/SubscriptionDAOUnitOfWork.php @@ -27,7 +27,7 @@ class SubscriptionDAOUnitOfWork implements UnitOfWork { /** - * @var Subscription[] + * @var DAO\Subscription[] */ private array $uncommited = []; @@ -98,7 +98,7 @@ public function commit(): \Generator try { while ($object = array_shift($this->uncommited)) { - /** @var Subscription $object */ + /** @var DAO\Subscription $object */ try { $this->dao->save($object); @@ -125,16 +125,12 @@ public function clear(): void private function supports(object $subscription): bool { - if ($subscription instanceof DAO\Subscription) { - return true; - } - while ($subscription instanceof Subscription\Decorator) { $subscription = $subscription->subscription(); + } - if ($subscription instanceof DAO\Subscription) { - return true; - } + if ($subscription instanceof DAO\Subscription) { + return true; } return false; diff --git a/tests/Domain/EventSourcingTest.php b/tests/Domain/EventSourcingTest.php index 85ac0bd0..bbe4da6e 100644 --- a/tests/Domain/EventSourcingTest.php +++ b/tests/Domain/EventSourcingTest.php @@ -637,7 +637,7 @@ class EventSourcedAggregateStub implements Event\Sourced\Aggregate use Aggregate\Identification; /** - * @var Event\Envelope[] + * @var array */ private array $appliedEvents = []; @@ -671,12 +671,12 @@ public function appliedEvents(): array private function applyEvent1(Event1 $event): void { - $this->appliedEvents = [$event]; + $this->appliedEvents[] = $event; } private function applyEvent2(Event2 $event): void { - $this->appliedEvents = [$event]; + $this->appliedEvents[] = $event; } } diff --git a/tests/Infrastructure/Domain/AggregateRoot/Snapshotter/Storage/RedisTest.php b/tests/Infrastructure/Domain/AggregateRoot/Snapshotter/Storage/RedisStorageTest.php similarity index 74% rename from tests/Infrastructure/Domain/AggregateRoot/Snapshotter/Storage/RedisTest.php rename to tests/Infrastructure/Domain/AggregateRoot/Snapshotter/Storage/RedisStorageTest.php index 3a52df2d..f66a8837 100644 --- a/tests/Infrastructure/Domain/AggregateRoot/Snapshotter/Storage/RedisTest.php +++ b/tests/Infrastructure/Domain/AggregateRoot/Snapshotter/Storage/RedisStorageTest.php @@ -23,7 +23,7 @@ * * @covers \Streak\Infrastructure\Domain\AggregateRoot\Snapshotter\Storage\RedisStorage */ -class RedisTest extends Storage\TestCase +class RedisStorageTest extends Storage\TestCase { public function testResetting(): void { @@ -40,12 +40,27 @@ public function testResetting(): void $this->storage->find($this->aggregate1); } + public function testRedisInMultiMode(): void + { + $redis = $this->newRedis(); + $storage = new RedisStorage($redis->multi()); + + $this->expectExceptionObject(new SnapshotNotFound($this->aggregate1)); + + $storage->find($this->aggregate1); + } + protected function newStorage(): Storage + { + return new RedisStorage($this->newRedis()); + } + + private function newRedis(): \Redis { $redis = new \Redis(); $redis->connect($_ENV['PHPUNIT_REDIS_HOSTNAME'], (int) $_ENV['PHPUNIT_REDIS_PORT']); $redis->select((int) $_ENV['PHPUNIT_REDIS_DATABASE']); - return new RedisStorage($redis); + return $redis; } } diff --git a/tests/Infrastructure/Domain/Event/Subscription/EventSourcedRepositoryTest.php b/tests/Infrastructure/Domain/Event/Subscription/EventSourcedRepositoryTest.php index 98bc5ef7..ad5cda86 100644 --- a/tests/Infrastructure/Domain/Event/Subscription/EventSourcedRepositoryTest.php +++ b/tests/Infrastructure/Domain/Event/Subscription/EventSourcedRepositoryTest.php @@ -243,7 +243,9 @@ public function testFindingSubscription(): void ->with(self::callback(function (Event\Stream $stream) use ($event1, $event2, $event3) { $stream = iterator_to_array($stream); - return self::equalTo([$event1, $event2, $event3])->evaluate($stream); + self::equalTo([$event1, $event2, $event3])->evaluate($stream); + + return true; })) ; @@ -300,7 +302,9 @@ public function testFindingPreviouslyRestartedSubscription(): void $stream = iterator_to_array($stream); // streaming from SubscriptionRestarted event - return self::equalTo([$event1, $event2, $event3, $event4, $event5, $event6])->evaluate($stream); + self::equalTo([$event1, $event2, $event3, $event4, $event5, $event6])->evaluate($stream); + + return true; })) ;