From e96cd7aa18e85d658e0f587164f17b2cc311c948 Mon Sep 17 00:00:00 2001 From: David Badura Date: Mon, 19 Feb 2024 11:08:49 +0100 Subject: [PATCH] add transactional store interface --- .../Projection/Store/DoctrineStore.php | 9 +++++++-- .../Projection/Store/InMemoryStore.php | 6 ------ .../Projection/Store/ProjectionStore.php | 3 --- .../Store/TransactionCommitNotPossible.php | 20 +++++++++++++++++++ .../Projection/Store/TransactionalStore.php | 12 +++++++++++ .../Projectionist/DefaultProjectionist.php | 10 ++++++++-- tests/Unit/Projection/DummyStore.php | 6 ------ 7 files changed, 47 insertions(+), 19 deletions(-) create mode 100644 src/Projection/Projection/Store/TransactionCommitNotPossible.php create mode 100644 src/Projection/Projection/Store/TransactionalStore.php diff --git a/src/Projection/Projection/Store/DoctrineStore.php b/src/Projection/Projection/Store/DoctrineStore.php index debf36a95..437423b52 100644 --- a/src/Projection/Projection/Store/DoctrineStore.php +++ b/src/Projection/Projection/Store/DoctrineStore.php @@ -7,6 +7,7 @@ use Closure; use Doctrine\DBAL\ArrayParameterType; use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Exception\DriverException; use Doctrine\DBAL\Platforms\SQLitePlatform; use Doctrine\DBAL\Schema\Schema; use Doctrine\DBAL\Types\Types; @@ -33,7 +34,7 @@ * retry: int, * } */ -final class DoctrineStore implements ProjectionStore, SchemaConfigurator +final class DoctrineStore implements ProjectionStore, TransactionalStore, SchemaConfigurator { public function __construct( private readonly Connection $connection, @@ -162,7 +163,11 @@ public function transactional(Closure $closure): void try { $closure(); } finally { - $this->connection->commit(); + try { + $this->connection->commit(); + } catch (DriverException $e) { + throw new TransactionCommitNotPossible($e); + } } } diff --git a/src/Projection/Projection/Store/InMemoryStore.php b/src/Projection/Projection/Store/InMemoryStore.php index bd575d338..469660f2e 100644 --- a/src/Projection/Projection/Store/InMemoryStore.php +++ b/src/Projection/Projection/Store/InMemoryStore.php @@ -4,7 +4,6 @@ namespace Patchlevel\EventSourcing\Projection\Projection\Store; -use Closure; use Patchlevel\EventSourcing\Projection\Projection\Projection; use Patchlevel\EventSourcing\Projection\Projection\ProjectionAlreadyExists; use Patchlevel\EventSourcing\Projection\Projection\ProjectionCriteria; @@ -96,9 +95,4 @@ public function remove(Projection $projection): void { unset($this->projections[$projection->id()]); } - - public function transactional(Closure $closure): void - { - $closure(); - } } diff --git a/src/Projection/Projection/Store/ProjectionStore.php b/src/Projection/Projection/Store/ProjectionStore.php index 45e1717fa..743647d7c 100644 --- a/src/Projection/Projection/Store/ProjectionStore.php +++ b/src/Projection/Projection/Store/ProjectionStore.php @@ -4,7 +4,6 @@ namespace Patchlevel\EventSourcing\Projection\Projection\Store; -use Closure; use Patchlevel\EventSourcing\Projection\Projection\Projection; use Patchlevel\EventSourcing\Projection\Projection\ProjectionAlreadyExists; use Patchlevel\EventSourcing\Projection\Projection\ProjectionCriteria; @@ -26,6 +25,4 @@ public function update(Projection $projection): void; /** @throws ProjectionNotFound */ public function remove(Projection $projection): void; - - public function transactional(Closure $closure): void; } diff --git a/src/Projection/Projection/Store/TransactionCommitNotPossible.php b/src/Projection/Projection/Store/TransactionCommitNotPossible.php new file mode 100644 index 000000000..b9db0165a --- /dev/null +++ b/src/Projection/Projection/Store/TransactionCommitNotPossible.php @@ -0,0 +1,20 @@ +findForUpdate( - null, + new ProjectionCriteria(), function (array $projections): void { foreach ($this->projectors as $projector) { $projectorId = $this->projectorId($projector); @@ -821,8 +821,14 @@ private function lowestProjectionPosition(array $projections): int } /** @param Closure(list):void $closure */ - private function findForUpdate(ProjectionCriteria|null $criteria, Closure $closure): void + private function findForUpdate(ProjectionCriteria $criteria, Closure $closure): void { + if (!$this->projectionStore instanceof Store) { + $closure($this->projectionStore->find($criteria)); + + return; + } + $this->projectionStore->transactional(function () use ($closure, $criteria): void { $projections = $this->projectionStore->find($criteria); diff --git a/tests/Unit/Projection/DummyStore.php b/tests/Unit/Projection/DummyStore.php index d9a8b1b69..0bad434e8 100644 --- a/tests/Unit/Projection/DummyStore.php +++ b/tests/Unit/Projection/DummyStore.php @@ -4,7 +4,6 @@ namespace Patchlevel\EventSourcing\Tests\Unit\Projection; -use Closure; use Patchlevel\EventSourcing\Projection\Projection\Projection; use Patchlevel\EventSourcing\Projection\Projection\ProjectionCriteria; use Patchlevel\EventSourcing\Projection\Projection\Store\InMemoryStore; @@ -57,9 +56,4 @@ public function remove(Projection $projection): void $this->parentStore->remove($projection); $this->removedProjections[] = clone $projection; } - - public function transactional(Closure $closure): void - { - $this->parentStore->transactional($closure); - } }