From 19af2f6a3842093a985daa24987cbf626f3cc451 Mon Sep 17 00:00:00 2001 From: bwaidelich Date: Fri, 11 Aug 2023 10:52:08 +0200 Subject: [PATCH] Fix `ProjectionReplayService` and introduce `CatchUpOptions` --- .../Classes/ContentRepository.php | 3 +- .../Classes/Projection/CatchUpOptions.php | 55 +++++++++++++++++++ .../Features/Bootstrap/EventSourcedTrait.php | 3 +- .../Classes/Command/CrCommandController.php | 5 +- .../Classes/Command/CrCommandController.php | 9 ++- ...cessProjectionCatchUpCommandController.php | 3 +- .../CatchUpTriggerWithSynchronousOption.php | 3 +- .../Service/ProjectionReplayService.php | 22 ++------ .../ProjectionReplayServiceFactory.php | 1 - 9 files changed, 78 insertions(+), 26 deletions(-) create mode 100644 Neos.ContentRepository.Core/Classes/Projection/CatchUpOptions.php diff --git a/Neos.ContentRepository.Core/Classes/ContentRepository.php b/Neos.ContentRepository.Core/Classes/ContentRepository.php index 34ab55fa50d..311be1255a4 100644 --- a/Neos.ContentRepository.Core/Classes/ContentRepository.php +++ b/Neos.ContentRepository.Core/Classes/ContentRepository.php @@ -28,6 +28,7 @@ use Neos\ContentRepository\Core\Factory\ContentRepositoryFactory; use Neos\ContentRepository\Core\Factory\ContentRepositoryId; use Neos\ContentRepository\Core\NodeType\NodeTypeManager; +use Neos\ContentRepository\Core\Projection\CatchUpOptions; use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphInterface; use Neos\ContentRepository\Core\Projection\ContentStream\ContentStreamFinder; use Neos\ContentRepository\Core\Projection\ProjectionInterface; @@ -155,7 +156,7 @@ public function projectionState(string $projectionStateClassName): ProjectionSta /** * @param class-string> $projectionClassName */ - public function catchUpProjection(string $projectionClassName): void + public function catchUpProjection(string $projectionClassName, CatchUpOptions $options): void { $projection = $this->projectionsAndCatchUpHooks->projections->get($projectionClassName); diff --git a/Neos.ContentRepository.Core/Classes/Projection/CatchUpOptions.php b/Neos.ContentRepository.Core/Classes/Projection/CatchUpOptions.php new file mode 100644 index 00000000000..09679cd6d1c --- /dev/null +++ b/Neos.ContentRepository.Core/Classes/Projection/CatchUpOptions.php @@ -0,0 +1,55 @@ +maximumSequenceNumber, + ); + } +} diff --git a/Neos.ContentRepository.Core/Tests/Behavior/Features/Bootstrap/EventSourcedTrait.php b/Neos.ContentRepository.Core/Tests/Behavior/Features/Bootstrap/EventSourcedTrait.php index f640177a9e0..fa646c46e42 100644 --- a/Neos.ContentRepository.Core/Tests/Behavior/Features/Bootstrap/EventSourcedTrait.php +++ b/Neos.ContentRepository.Core/Tests/Behavior/Features/Bootstrap/EventSourcedTrait.php @@ -40,6 +40,7 @@ use Neos\ContentRepository\Core\Feature\NodeModification\Dto\PropertyValuesToWrite; use Neos\ContentRepository\Core\Infrastructure\DbalClientInterface; use Neos\ContentRepository\Core\NodeType\NodeTypeName; +use Neos\ContentRepository\Core\Projection\CatchUpOptions; use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphInterface; use Neos\ContentRepository\Core\Projection\ContentGraph\Filter\FindSubtreeFilter; use Neos\ContentRepository\Core\Projection\ContentGraph\Node; @@ -554,7 +555,7 @@ public function iPruneRemovedContentStreamsFromTheEventStream() public function iReplayTheProjection(string $projectionName) { $this->contentRepository->resetProjectionState($projectionName); - $this->contentRepository->catchUpProjection($projectionName); + $this->contentRepository->catchUpProjection($projectionName, CatchUpOptions::create()); } abstract protected function getContentRepositoryService( diff --git a/Neos.ContentRepository.LegacyNodeMigration/Classes/Command/CrCommandController.php b/Neos.ContentRepository.LegacyNodeMigration/Classes/Command/CrCommandController.php index 4e38b77998c..fabefad1565 100644 --- a/Neos.ContentRepository.LegacyNodeMigration/Classes/Command/CrCommandController.php +++ b/Neos.ContentRepository.LegacyNodeMigration/Classes/Command/CrCommandController.php @@ -18,6 +18,7 @@ use Doctrine\DBAL\DriverManager; use Doctrine\DBAL\Exception as DbalException; use Doctrine\DBAL\Exception\ConnectionException; +use Neos\ContentRepository\Core\Projection\CatchUpOptions; use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; use Neos\ContentRepository\LegacyNodeMigration\LegacyMigrationService; use Neos\ContentRepository\LegacyNodeMigration\LegacyMigrationServiceFactory; @@ -130,7 +131,7 @@ public function migrateLegacyDataCommand(bool $verbose = false, string $config = // we also need to reset the projections; in order to ensure the system runs deterministically. We // do this by replaying the just-truncated event stream. $projectionService = $this->contentRepositoryRegistry->buildService($contentRepositoryId, $this->projectionReplayServiceFactory); - $projectionService->replayAllProjections(); + $projectionService->replayAllProjections(CatchUpOptions::create()); $this->outputLine('Truncated events'); $liveContentStreamId = ContentStreamId::create(); @@ -156,7 +157,7 @@ public function migrateLegacyDataCommand(bool $verbose = false, string $config = $this->outputLine(); $this->outputLine('Replaying projections'); - $projectionService->replayAllProjections(); + $projectionService->replayAllProjections(CatchUpOptions::create()); $this->outputLine('Done'); } diff --git a/Neos.ContentRepositoryRegistry/Classes/Command/CrCommandController.php b/Neos.ContentRepositoryRegistry/Classes/Command/CrCommandController.php index 2c026c21ac6..1c79af84cb2 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Command/CrCommandController.php +++ b/Neos.ContentRepositoryRegistry/Classes/Command/CrCommandController.php @@ -4,6 +4,7 @@ namespace Neos\ContentRepositoryRegistry\Command; use Neos\ContentRepository\Core\Factory\ContentRepositoryId; +use Neos\ContentRepository\Core\Projection\CatchUpOptions; use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry; use Neos\ContentRepositoryRegistry\Service\ProjectionReplayServiceFactory; use Neos\EventStore\Model\Event\SequenceNumber; @@ -54,7 +55,11 @@ public function replayCommand(string $projection, string $contentRepository = 'd $this->outputLine('Replaying events for projection "%s" of Content Repository "%s" ...', [$projection, $contentRepositoryId->value]); // TODO start progress bar } - $projectionService->replayProjection($projection, $until !== 0 ? SequenceNumber::fromInteger($until) : null); + $options = CatchUpOptions::create(); + if ($until !== null) { + $options = $options->with(maximumSequenceNumber: SequenceNumber::fromInteger($until)); + } + $projectionService->replayProjection($projection, $options); if (!$quiet) { // TODO finish progress bar $this->outputLine('Done.'); @@ -75,7 +80,7 @@ public function replayAllCommand(string $contentRepository = 'default', bool $qu $this->outputLine('Replaying events for all projections of Content Repository "%s" ...', [$contentRepositoryId->value]); // TODO start progress bar } - $projectionService->replayAllProjections(); + $projectionService->replayAllProjections(CatchUpOptions::create()); if (!$quiet) { // TODO finish progress bar $this->outputLine('Done.'); diff --git a/Neos.ContentRepositoryRegistry/Classes/Command/SubprocessProjectionCatchUpCommandController.php b/Neos.ContentRepositoryRegistry/Classes/Command/SubprocessProjectionCatchUpCommandController.php index bf122f2a606..b0ec9ee2d39 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Command/SubprocessProjectionCatchUpCommandController.php +++ b/Neos.ContentRepositoryRegistry/Classes/Command/SubprocessProjectionCatchUpCommandController.php @@ -3,6 +3,7 @@ namespace Neos\ContentRepositoryRegistry\Command; +use Neos\ContentRepository\Core\Projection\CatchUpOptions; use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry; use Neos\ContentRepositoryRegistry\Factory\ProjectionCatchUpTrigger\SubprocessProjectionCatchUpTrigger; use Neos\ContentRepository\Core\Factory\ContentRepositoryId; @@ -25,6 +26,6 @@ public function catchupCommand(string $contentRepositoryIdentifier, string $proj { $contentRepository = $this->contentRepositoryRegistry->get(ContentRepositoryId::fromString($contentRepositoryIdentifier)); - $contentRepository->catchUpProjection($projectionClassName); + $contentRepository->catchUpProjection($projectionClassName, CatchUpOptions::create()); } } diff --git a/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/CatchUpTriggerWithSynchronousOption.php b/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/CatchUpTriggerWithSynchronousOption.php index d1f24235f7c..adbff879b0e 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/CatchUpTriggerWithSynchronousOption.php +++ b/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/CatchUpTriggerWithSynchronousOption.php @@ -3,6 +3,7 @@ namespace Neos\ContentRepositoryRegistry\Factory\ProjectionCatchUpTrigger; +use Neos\ContentRepository\Core\Projection\CatchUpOptions; use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry; use Neos\Flow\Annotations as Flow; use Neos\ContentRepository\Core\Projection\ProjectionCatchUpTriggerInterface; @@ -66,7 +67,7 @@ public function triggerCatchUp(Projections $projections): void $contentRepository = $this->contentRepositoryRegistry->get($this->contentRepositoryId); foreach ($projections as $projection) { $projectionClassName = get_class($projection); - $contentRepository->catchUpProjection($projectionClassName); + $contentRepository->catchUpProjection($projectionClassName, CatchUpOptions::create()); } } else { $this->inner->triggerCatchUp($projections); diff --git a/Neos.ContentRepositoryRegistry/Classes/Service/ProjectionReplayService.php b/Neos.ContentRepositoryRegistry/Classes/Service/ProjectionReplayService.php index 27f81c161bd..8ff1b8ba568 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Service/ProjectionReplayService.php +++ b/Neos.ContentRepositoryRegistry/Classes/Service/ProjectionReplayService.php @@ -5,10 +5,8 @@ use Neos\ContentRepository\Core\ContentRepository; use Neos\ContentRepository\Core\Factory\ContentRepositoryServiceInterface; +use Neos\ContentRepository\Core\Projection\CatchUpOptions; use Neos\ContentRepository\Core\Projection\Projections; -use Neos\EventStore\EventStoreInterface; -use Neos\EventStore\Model\Event\SequenceNumber; -use Neos\EventStore\Model\EventStream\VirtualStreamName; /** * Content Repository service to perform Projection replays @@ -21,31 +19,21 @@ final class ProjectionReplayService implements ContentRepositoryServiceInterface public function __construct( private readonly Projections $projections, private readonly ContentRepository $contentRepository, - private readonly EventStoreInterface $eventStore, ) { } - public function replayProjection(string $projectionAliasOrClassName, ?SequenceNumber $maximumSequenceNumber = null): void + public function replayProjection(string $projectionAliasOrClassName, CatchUpOptions $options): void { $projectionClassName = $this->resolveProjectionClassName($projectionAliasOrClassName); $this->contentRepository->resetProjectionState($projectionClassName); - - // the logic below is from ContentRepository::catchUpProjection, - // but adjusted with the maximumSequenceNumber restriction - $projection = $this->projections->get($projectionClassName); - $streamName = VirtualStreamName::all(); - $eventStream = $this->eventStore->load($streamName); - if ($maximumSequenceNumber !== null) { - $eventStream = $eventStream->withMaximumSequenceNumber($maximumSequenceNumber); - } - $projection->catchUp($eventStream, $this->contentRepository); + $this->contentRepository->catchUpProjection($projectionClassName, $options); } - public function replayAllProjections(): void + public function replayAllProjections(CatchUpOptions $options): void { foreach ($this->projectionClassNamesAndAliases() as $classNamesAndAlias) { $this->contentRepository->resetProjectionState($classNamesAndAlias['className']); - $this->contentRepository->catchUpProjection($classNamesAndAlias['className']); + $this->contentRepository->catchUpProjection($classNamesAndAlias['className'], $options); } } diff --git a/Neos.ContentRepositoryRegistry/Classes/Service/ProjectionReplayServiceFactory.php b/Neos.ContentRepositoryRegistry/Classes/Service/ProjectionReplayServiceFactory.php index 5d7820f17d5..134d34b4f27 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Service/ProjectionReplayServiceFactory.php +++ b/Neos.ContentRepositoryRegistry/Classes/Service/ProjectionReplayServiceFactory.php @@ -24,7 +24,6 @@ public function build(ContentRepositoryServiceFactoryDependencies $serviceFactor return new ProjectionReplayService( $serviceFactoryDependencies->projections, $serviceFactoryDependencies->contentRepository, - $serviceFactoryDependencies->eventStore ); } }