From 971a25386798f147dd0cab3adb168365c13cbf32 Mon Sep 17 00:00:00 2001 From: mhsdesign <85400359+mhsdesign@users.noreply.github.com> Date: Sun, 27 Oct 2024 21:06:12 +0100 Subject: [PATCH] TASK: Catchups will only be able to access the state of the projection they are registered for A catchup doesn't have access to the full content repository, as it would allow full recursion via handle and accessing other projections state is not safe as the other projection might not be behind - the order is undefined. This will make it possible to catchup projections from outside of the cr instance as proposed here: https://github.com/neos/neos-development-collection/pull/5321 --- .../RaceTrackerCatchUpHookFactory.php | 7 +++-- .../Classes/ContentRepository.php | 4 +-- .../ProjectionsAndCatchUpHooksFactory.php | 6 ++--- .../Projection/CatchUpHookFactories.php | 16 +++++++++--- .../CatchUpHookFactoryInterface.php | 13 ++++++++-- .../ContentGraphReadModelInterface.php | 6 ++++- .../Projection/ProjectionsAndCatchUpHooks.php | 1 + ...ushSubgraphCachePoolCatchUpHookFactory.php | 8 ++++-- .../CatchUpHook/AssetUsageCatchUpHook.php | 24 +++++++++-------- .../AssetUsageCatchUpHookFactory.php | 12 ++++++--- .../CatchUpHook/RouterCacheHook.php | 18 +++++-------- .../CatchUpHook/RouterCacheHookFactory.php | 12 ++++++--- ...phProjectorCatchUpHookForCacheFlushing.php | 26 ++++++++++--------- ...ctorCatchUpHookForCacheFlushingFactory.php | 12 ++++++--- 14 files changed, 104 insertions(+), 61 deletions(-) diff --git a/Neos.ContentRepository.BehavioralTests/Classes/ProjectionRaceConditionTester/RaceTrackerCatchUpHookFactory.php b/Neos.ContentRepository.BehavioralTests/Classes/ProjectionRaceConditionTester/RaceTrackerCatchUpHookFactory.php index 30467e9dd48..c123247b704 100644 --- a/Neos.ContentRepository.BehavioralTests/Classes/ProjectionRaceConditionTester/RaceTrackerCatchUpHookFactory.php +++ b/Neos.ContentRepository.BehavioralTests/Classes/ProjectionRaceConditionTester/RaceTrackerCatchUpHookFactory.php @@ -14,18 +14,21 @@ namespace Neos\ContentRepository\BehavioralTests\ProjectionRaceConditionTester; -use Neos\ContentRepository\Core\ContentRepository; use Neos\ContentRepository\Core\Projection\CatchUpHookFactoryInterface; use Neos\ContentRepository\Core\Projection\CatchUpHookInterface; +use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphReadModelInterface; +use Neos\ContentRepository\Core\Projection\ProjectionStateInterface; +use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId; /** * For full docs and context, see {@see RaceTrackerCatchUpHook} * + * @implements CatchUpHookFactoryInterface * @internal */ final class RaceTrackerCatchUpHookFactory implements CatchUpHookFactoryInterface { - public function build(ContentRepository $contentRepository): CatchUpHookInterface + public function build(ContentRepositoryId $contentRepositoryId, ProjectionStateInterface $projectionState): CatchUpHookInterface { return new RaceTrackerCatchUpHook(); } diff --git a/Neos.ContentRepository.Core/Classes/ContentRepository.php b/Neos.ContentRepository.Core/Classes/ContentRepository.php index 68c28d1069a..8b94e4fe8fb 100644 --- a/Neos.ContentRepository.Core/Classes/ContentRepository.php +++ b/Neos.ContentRepository.Core/Classes/ContentRepository.php @@ -29,8 +29,8 @@ use Neos\ContentRepository\Core\Projection\CatchUp; use Neos\ContentRepository\Core\Projection\CatchUpOptions; use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphInterface; -use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphReadModelInterface; use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphProjectionInterface; +use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphReadModelInterface; use Neos\ContentRepository\Core\Projection\ProjectionInterface; use Neos\ContentRepository\Core\Projection\ProjectionsAndCatchUpHooks; use Neos\ContentRepository\Core\Projection\ProjectionStateInterface; @@ -171,7 +171,7 @@ public function catchUpProjection(string $projectionClassName, CatchUpOptions $o $projection = $this->projectionsAndCatchUpHooks->projections->get($projectionClassName); $catchUpHookFactory = $this->projectionsAndCatchUpHooks->getCatchUpHookFactoryForProjection($projection); - $catchUpHook = $catchUpHookFactory?->build($this); + $catchUpHook = $catchUpHookFactory?->build($this->id, $projection->getState()); // TODO allow custom stream name per projection $streamName = VirtualStreamName::all(); diff --git a/Neos.ContentRepository.Core/Classes/Factory/ProjectionsAndCatchUpHooksFactory.php b/Neos.ContentRepository.Core/Classes/Factory/ProjectionsAndCatchUpHooksFactory.php index cd369a87a6e..f48ed1345c0 100644 --- a/Neos.ContentRepository.Core/Classes/Factory/ProjectionsAndCatchUpHooksFactory.php +++ b/Neos.ContentRepository.Core/Classes/Factory/ProjectionsAndCatchUpHooksFactory.php @@ -6,12 +6,12 @@ use Neos\ContentRepository\Core\Projection\CatchUpHookFactories; use Neos\ContentRepository\Core\Projection\CatchUpHookFactoryInterface; +use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphProjectionInterface; use Neos\ContentRepository\Core\Projection\ProjectionFactoryInterface; use Neos\ContentRepository\Core\Projection\ProjectionInterface; use Neos\ContentRepository\Core\Projection\Projections; use Neos\ContentRepository\Core\Projection\ProjectionsAndCatchUpHooks; use Neos\ContentRepository\Core\Projection\ProjectionStateInterface; -use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphProjectionInterface; /** * @api for custom framework integrations, not for users of the CR @@ -19,7 +19,7 @@ final class ProjectionsAndCatchUpHooksFactory { /** - * @var array>, options: array, catchUpHooksFactories: array}> + * @var array>, options: array, catchUpHooksFactories: array>}> */ private array $factories = []; @@ -40,7 +40,7 @@ public function registerFactory(ProjectionFactoryInterface $factory, array $opti /** * @param ProjectionFactoryInterface> $factory - * @param CatchUpHookFactoryInterface $catchUpHookFactory + * @param CatchUpHookFactoryInterface $catchUpHookFactory * @return void * @api */ diff --git a/Neos.ContentRepository.Core/Classes/Projection/CatchUpHookFactories.php b/Neos.ContentRepository.Core/Classes/Projection/CatchUpHookFactories.php index deabf53477b..f12fb3be7d4 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/CatchUpHookFactories.php +++ b/Neos.ContentRepository.Core/Classes/Projection/CatchUpHookFactories.php @@ -4,18 +4,22 @@ namespace Neos\ContentRepository\Core\Projection; -use Neos\ContentRepository\Core\ContentRepository; +use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId; /** + * @implements CatchUpHookFactoryInterface * @internal */ final class CatchUpHookFactories implements CatchUpHookFactoryInterface { /** - * @var array + * @var array> */ private array $catchUpHookFactories; + /** + * @param CatchUpHookFactoryInterface ...$catchUpHookFactories + */ private function __construct(CatchUpHookFactoryInterface ...$catchUpHookFactories) { $this->catchUpHookFactories = $catchUpHookFactories; @@ -26,6 +30,10 @@ public static function create(): self return new self(); } + /** + * @param CatchUpHookFactoryInterface $catchUpHookFactory + * @return self + */ public function with(CatchUpHookFactoryInterface $catchUpHookFactory): self { if ($this->has($catchUpHookFactory::class)) { @@ -44,9 +52,9 @@ private function has(string $catchUpHookFactoryClassName): bool return array_key_exists($catchUpHookFactoryClassName, $this->catchUpHookFactories); } - public function build(ContentRepository $contentRepository): CatchUpHookInterface + public function build(ContentRepositoryId $contentRepositoryId, ProjectionStateInterface $projectionState): CatchUpHookInterface { - $catchUpHooks = array_map(static fn(CatchUpHookFactoryInterface $catchUpHookFactory) => $catchUpHookFactory->build($contentRepository), $this->catchUpHookFactories); + $catchUpHooks = array_map(static fn(CatchUpHookFactoryInterface $catchUpHookFactory) => $catchUpHookFactory->build($contentRepositoryId, $projectionState), $this->catchUpHookFactories); return new DelegatingCatchUpHook(...$catchUpHooks); } } diff --git a/Neos.ContentRepository.Core/Classes/Projection/CatchUpHookFactoryInterface.php b/Neos.ContentRepository.Core/Classes/Projection/CatchUpHookFactoryInterface.php index ec84d096c16..10d918cd2d8 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/CatchUpHookFactoryInterface.php +++ b/Neos.ContentRepository.Core/Classes/Projection/CatchUpHookFactoryInterface.php @@ -4,12 +4,21 @@ namespace Neos\ContentRepository\Core\Projection; -use Neos\ContentRepository\Core\ContentRepository; +use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId; /** + * @template T of ProjectionStateInterface * @api */ interface CatchUpHookFactoryInterface { - public function build(ContentRepository $contentRepository): CatchUpHookInterface; + /** + * Note that a catchup doesn't have access to the full content repository, as it would allow full recursion via handle and accessing other projections + * state is not safe as the other projection might not be behind - the order is undefined. + * + * @param ContentRepositoryId $contentRepositoryId the content repository the catchup was registered in + * @param ProjectionStateInterface&T $projectionState the state of the projection the catchup was registered to (Its only safe to access this projections state) + * @return CatchUpHookInterface + */ + public function build(ContentRepositoryId $contentRepositoryId, ProjectionStateInterface $projectionState): CatchUpHookInterface; } diff --git a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentGraphReadModelInterface.php b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentGraphReadModelInterface.php index 03bce7a58b7..8c8582bb7be 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentGraphReadModelInterface.php +++ b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentGraphReadModelInterface.php @@ -24,7 +24,11 @@ use Neos\ContentRepository\Core\SharedModel\Workspace\Workspaces; /** - * @api for creating a custom content repository graph projection implementation, **not for users of the CR** + * This low level interface gives access to the content graph and workspaces + * + * Generally this is not accessible for users of the CR, except for registering a catchup-hook on the content graph + * + * @api as dependency in catchup hooks and for creating a custom content repository graph projection implementation */ interface ContentGraphReadModelInterface extends ProjectionStateInterface { diff --git a/Neos.ContentRepository.Core/Classes/Projection/ProjectionsAndCatchUpHooks.php b/Neos.ContentRepository.Core/Classes/Projection/ProjectionsAndCatchUpHooks.php index 255e59b7600..d7b674babdb 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/ProjectionsAndCatchUpHooks.php +++ b/Neos.ContentRepository.Core/Classes/Projection/ProjectionsAndCatchUpHooks.php @@ -26,6 +26,7 @@ public function __construct( /** * @param ProjectionInterface $projection + * @return ?CatchUpHookFactoryInterface */ public function getCatchUpHookFactoryForProjection(ProjectionInterface $projection): ?CatchUpHookFactoryInterface { diff --git a/Neos.ContentRepositoryRegistry/Classes/SubgraphCachingInMemory/FlushSubgraphCachePoolCatchUpHookFactory.php b/Neos.ContentRepositoryRegistry/Classes/SubgraphCachingInMemory/FlushSubgraphCachePoolCatchUpHookFactory.php index f31545386b3..72f8bb5a7c3 100644 --- a/Neos.ContentRepositoryRegistry/Classes/SubgraphCachingInMemory/FlushSubgraphCachePoolCatchUpHookFactory.php +++ b/Neos.ContentRepositoryRegistry/Classes/SubgraphCachingInMemory/FlushSubgraphCachePoolCatchUpHookFactory.php @@ -4,13 +4,16 @@ namespace Neos\ContentRepositoryRegistry\SubgraphCachingInMemory; -use Neos\ContentRepository\Core\ContentRepository; use Neos\ContentRepository\Core\Projection\CatchUpHookFactoryInterface; use Neos\ContentRepository\Core\Projection\CatchUpHookInterface; +use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphReadModelInterface; +use Neos\ContentRepository\Core\Projection\ProjectionStateInterface; +use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId; /** * Factory for {@see FlushSubgraphCachePoolCatchUpHook}, auto-registered in Settings.yaml for GraphProjection * + * @implements CatchUpHookFactoryInterface * @internal */ class FlushSubgraphCachePoolCatchUpHookFactory implements CatchUpHookFactoryInterface @@ -20,7 +23,8 @@ public function __construct( private readonly SubgraphCachePool $subgraphCachePool ) { } - public function build(ContentRepository $contentRepository): CatchUpHookInterface + + public function build(ContentRepositoryId $contentRepositoryId, ProjectionStateInterface $projectionState): CatchUpHookInterface { return new FlushSubgraphCachePoolCatchUpHook($this->subgraphCachePool); } diff --git a/Neos.Neos/Classes/AssetUsage/CatchUpHook/AssetUsageCatchUpHook.php b/Neos.Neos/Classes/AssetUsage/CatchUpHook/AssetUsageCatchUpHook.php index 7867326e1ea..dc9930aea8e 100644 --- a/Neos.Neos/Classes/AssetUsage/CatchUpHook/AssetUsageCatchUpHook.php +++ b/Neos.Neos/Classes/AssetUsage/CatchUpHook/AssetUsageCatchUpHook.php @@ -4,7 +4,6 @@ namespace Neos\Neos\AssetUsage\CatchUpHook; -use Neos\ContentRepository\Core\ContentRepository; use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePoint; use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePointSet; use Neos\ContentRepository\Core\EventStore\EventInterface; @@ -21,9 +20,11 @@ use Neos\ContentRepository\Core\Feature\WorkspacePublication\Event\WorkspaceWasDiscarded; use Neos\ContentRepository\Core\Feature\WorkspacePublication\Event\WorkspaceWasPartiallyDiscarded; use Neos\ContentRepository\Core\Projection\CatchUpHookInterface; +use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphReadModelInterface; use Neos\ContentRepository\Core\Projection\ContentGraph\Filter\FindDescendantNodesFilter; use Neos\ContentRepository\Core\Projection\ContentGraph\Node; use Neos\ContentRepository\Core\Projection\ContentGraph\VisibilityConstraints; +use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId; use Neos\ContentRepository\Core\SharedModel\Exception\WorkspaceDoesNotExist; use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId; use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName; @@ -36,7 +37,8 @@ class AssetUsageCatchUpHook implements CatchUpHookInterface { public function __construct( - private readonly ContentRepository $contentRepository, + private readonly ContentRepositoryId $contentRepositoryId, + private readonly ContentGraphReadModelInterface $contentGraphReadModel, private readonly AssetUsageIndexingService $assetUsageIndexingService ) { } @@ -50,7 +52,7 @@ public function onBeforeEvent(EventInterface $eventInstance, EventEnvelope $even if ($eventInstance instanceof EmbedsWorkspaceName && $eventInstance instanceof EmbedsContentStreamId) { // Safeguard for temporary content streams created during partial publish -> We want to skip these events, because their workspace doesn't match current content stream. try { - $contentGraph = $this->contentRepository->getContentGraph($eventInstance->getWorkspaceName()); + $contentGraph = $this->contentGraphReadModel->getContentGraph($eventInstance->getWorkspaceName()); } catch (WorkspaceDoesNotExist) { return; } @@ -71,7 +73,7 @@ public function onAfterEvent(EventInterface $eventInstance, EventEnvelope $event if ($eventInstance instanceof EmbedsWorkspaceName && $eventInstance instanceof EmbedsContentStreamId) { // Safeguard for temporary content streams created during partial publish -> We want to skip these events, because their workspace doesn't match current content stream. try { - $contentGraph = $this->contentRepository->getContentGraph($eventInstance->getWorkspaceName()); + $contentGraph = $this->contentGraphReadModel->getContentGraph($eventInstance->getWorkspaceName()); } catch (WorkspaceDoesNotExist) { return; } @@ -103,7 +105,7 @@ public function onAfterCatchUp(): void private function updateNode(WorkspaceName $workspaceName, NodeAggregateId $nodeAggregateId, DimensionSpacePoint $dimensionSpacePoint): void { - $contentGraph = $this->contentRepository->getContentGraph($workspaceName); + $contentGraph = $this->contentGraphReadModel->getContentGraph($workspaceName); $node = $contentGraph->getSubgraph($dimensionSpacePoint, VisibilityConstraints::withoutRestrictions())->findNodeById($nodeAggregateId); if ($node === null) { @@ -112,14 +114,14 @@ private function updateNode(WorkspaceName $workspaceName, NodeAggregateId $nodeA } $this->assetUsageIndexingService->updateIndex( - $this->contentRepository->id, + $this->contentRepositoryId, $node ); } private function removeNodes(WorkspaceName $workspaceName, NodeAggregateId $nodeAggregateId, DimensionSpacePointSet $dimensionSpacePoints): void { - $contentGraph = $this->contentRepository->getContentGraph($workspaceName); + $contentGraph = $this->contentGraphReadModel->getContentGraph($workspaceName); foreach ($dimensionSpacePoints as $dimensionSpacePoint) { $subgraph = $contentGraph->getSubgraph($dimensionSpacePoint, VisibilityConstraints::withoutRestrictions()); @@ -131,7 +133,7 @@ private function removeNodes(WorkspaceName $workspaceName, NodeAggregateId $node /** @var Node $node */ foreach ($nodes as $node) { $this->assetUsageIndexingService->removeIndexForNode( - $this->contentRepository->id, + $this->contentRepositoryId, $node ); } @@ -140,7 +142,7 @@ private function removeNodes(WorkspaceName $workspaceName, NodeAggregateId $node private function discardWorkspace(WorkspaceName $workspaceName): void { - $this->assetUsageIndexingService->removeIndexForWorkspace($this->contentRepository->id, $workspaceName); + $this->assetUsageIndexingService->removeIndexForWorkspace($this->contentRepositoryId, $workspaceName); } private function discardNodes(WorkspaceName $workspaceName, NodeIdsToPublishOrDiscard $nodeIds): void @@ -151,7 +153,7 @@ private function discardNodes(WorkspaceName $workspaceName, NodeIdsToPublishOrDi continue; } $this->assetUsageIndexingService->removeIndexForWorkspaceNameNodeAggregateIdAndDimensionSpacePoint( - $this->contentRepository->id, + $this->contentRepositoryId, $workspaceName, $nodeId->nodeAggregateId, $nodeId->dimensionSpacePoint @@ -161,6 +163,6 @@ private function discardNodes(WorkspaceName $workspaceName, NodeIdsToPublishOrDi private function updateDimensionSpacePoint(WorkspaceName $workspaceName, DimensionSpacePoint $source, DimensionSpacePoint $target): void { - $this->assetUsageIndexingService->updateDimensionSpacePointInIndex($this->contentRepository->id, $workspaceName, $source, $target); + $this->assetUsageIndexingService->updateDimensionSpacePointInIndex($this->contentRepositoryId, $workspaceName, $source, $target); } } diff --git a/Neos.Neos/Classes/AssetUsage/CatchUpHook/AssetUsageCatchUpHookFactory.php b/Neos.Neos/Classes/AssetUsage/CatchUpHook/AssetUsageCatchUpHookFactory.php index 89bcec32e86..a420aa62e90 100644 --- a/Neos.Neos/Classes/AssetUsage/CatchUpHook/AssetUsageCatchUpHookFactory.php +++ b/Neos.Neos/Classes/AssetUsage/CatchUpHook/AssetUsageCatchUpHookFactory.php @@ -14,10 +14,15 @@ * source code. */ -use Neos\ContentRepository\Core\ContentRepository; use Neos\ContentRepository\Core\Projection\CatchUpHookFactoryInterface; +use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphReadModelInterface; +use Neos\ContentRepository\Core\Projection\ProjectionStateInterface; +use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId; use Neos\Neos\AssetUsage\Service\AssetUsageIndexingService; +/** + * @implements CatchUpHookFactoryInterface + */ class AssetUsageCatchUpHookFactory implements CatchUpHookFactoryInterface { public function __construct( @@ -25,10 +30,11 @@ public function __construct( ) { } - public function build(ContentRepository $contentRepository): AssetUsageCatchUpHook + public function build(ContentRepositoryId $contentRepositoryId, ProjectionStateInterface $projectionState): AssetUsageCatchUpHook { return new AssetUsageCatchUpHook( - $contentRepository, + $contentRepositoryId, + $projectionState, $this->assetUsageIndexingService ); } diff --git a/Neos.Neos/Classes/FrontendRouting/CatchUpHook/RouterCacheHook.php b/Neos.Neos/Classes/FrontendRouting/CatchUpHook/RouterCacheHook.php index b6529d5be4c..1dc70d4fac7 100644 --- a/Neos.Neos/Classes/FrontendRouting/CatchUpHook/RouterCacheHook.php +++ b/Neos.Neos/Classes/FrontendRouting/CatchUpHook/RouterCacheHook.php @@ -4,7 +4,6 @@ namespace Neos\Neos\FrontendRouting\CatchUpHook; -use Neos\ContentRepository\Core\ContentRepository; use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePoint; use Neos\ContentRepository\Core\EventStore\EventInterface; use Neos\ContentRepository\Core\Feature\NodeModification\Event\NodePropertiesWereSet; @@ -28,7 +27,7 @@ final class RouterCacheHook implements CatchUpHookInterface private array $tagsToFlush = []; public function __construct( - private readonly ContentRepository $contentRepository, + private readonly DocumentUriPathFinder $documentUriPathFinder, private readonly RouterCachingService $routerCachingService, ) { } @@ -85,7 +84,7 @@ private function onBeforeSubtreeWasTagged(SubtreeWasTagged $event): void $this->collectTagsToFlush($node); - $descendantsOfNode = $this->getState()->getDescendantsOfNode($node); + $descendantsOfNode = $this->documentUriPathFinder->getDescendantsOfNode($node); array_map($this->collectTagsToFlush(...), iterator_to_array($descendantsOfNode)); } } @@ -105,7 +104,7 @@ private function onBeforeNodeAggregateWasRemoved(NodeAggregateWasRemoved $event) $this->collectTagsToFlush($node); - $descendantsOfNode = $this->getState()->getDescendantsOfNode($node); + $descendantsOfNode = $this->documentUriPathFinder->getDescendantsOfNode($node); array_map($this->collectTagsToFlush(...), iterator_to_array($descendantsOfNode)); } } @@ -130,7 +129,7 @@ private function onBeforeNodePropertiesWereSet(NodePropertiesWereSet $event): vo $this->collectTagsToFlush($node); - $descendantsOfNode = $this->getState()->getDescendantsOfNode($node); + $descendantsOfNode = $this->documentUriPathFinder->getDescendantsOfNode($node); array_map($this->collectTagsToFlush(...), iterator_to_array($descendantsOfNode)); } } @@ -153,7 +152,7 @@ private function onBeforeNodeAggregateWasMoved(NodeAggregateWasMoved $event): vo $this->collectTagsToFlush($node); - $descendantsOfNode = $this->getState()->getDescendantsOfNode($node); + $descendantsOfNode = $this->documentUriPathFinder->getDescendantsOfNode($node); array_map($this->collectTagsToFlush(...), iterator_to_array($descendantsOfNode)); } } @@ -173,15 +172,10 @@ private function flushAllCollectedTags(): void $this->tagsToFlush = []; } - private function getState(): DocumentUriPathFinder - { - return $this->contentRepository->projectionState(DocumentUriPathFinder::class); - } - private function findDocumentNodeInfoByIdAndDimensionSpacePoint(NodeAggregateId $nodeAggregateId, DimensionSpacePoint $dimensionSpacePoint): ?DocumentNodeInfo { try { - return $this->getState()->getByIdAndDimensionSpacePointHash( + return $this->documentUriPathFinder->getByIdAndDimensionSpacePointHash( $nodeAggregateId, $dimensionSpacePoint->hash ); diff --git a/Neos.Neos/Classes/FrontendRouting/CatchUpHook/RouterCacheHookFactory.php b/Neos.Neos/Classes/FrontendRouting/CatchUpHook/RouterCacheHookFactory.php index 15b92e86c39..432aff8a0cb 100644 --- a/Neos.Neos/Classes/FrontendRouting/CatchUpHook/RouterCacheHookFactory.php +++ b/Neos.Neos/Classes/FrontendRouting/CatchUpHook/RouterCacheHookFactory.php @@ -4,12 +4,16 @@ namespace Neos\Neos\FrontendRouting\CatchUpHook; -use Neos\ContentRepository\Core\ContentRepository; use Neos\ContentRepository\Core\Projection\CatchUpHookFactoryInterface; use Neos\ContentRepository\Core\Projection\CatchUpHookInterface; +use Neos\ContentRepository\Core\Projection\ProjectionStateInterface; +use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId; use Neos\Flow\Mvc\Routing\RouterCachingService; -use Neos\RedirectHandler\NeosAdapter\Service\NodeRedirectService; +use Neos\Neos\FrontendRouting\Projection\DocumentUriPathFinder; +/** + * @implements CatchUpHookFactoryInterface + */ final class RouterCacheHookFactory implements CatchUpHookFactoryInterface { public function __construct( @@ -17,10 +21,10 @@ public function __construct( ) { } - public function build(ContentRepository $contentRepository): CatchUpHookInterface + public function build(ContentRepositoryId $contentRepositoryId, ProjectionStateInterface $projectionState): CatchUpHookInterface { return new RouterCacheHook( - $contentRepository, + $projectionState, $this->routerCachingService ); } diff --git a/Neos.Neos/Classes/Fusion/Cache/GraphProjectorCatchUpHookForCacheFlushing.php b/Neos.Neos/Classes/Fusion/Cache/GraphProjectorCatchUpHookForCacheFlushing.php index 19ffd145d04..349d4eb3ac7 100644 --- a/Neos.Neos/Classes/Fusion/Cache/GraphProjectorCatchUpHookForCacheFlushing.php +++ b/Neos.Neos/Classes/Fusion/Cache/GraphProjectorCatchUpHookForCacheFlushing.php @@ -14,7 +14,6 @@ * source code. */ -use Neos\ContentRepository\Core\ContentRepository; use Neos\ContentRepository\Core\EventStore\EventInterface; use Neos\ContentRepository\Core\Feature\Common\EmbedsContentStreamId; use Neos\ContentRepository\Core\Feature\Common\EmbedsNodeAggregateId; @@ -37,7 +36,9 @@ use Neos\ContentRepository\Core\Feature\WorkspacePublication\Event\WorkspaceWasPartiallyDiscarded; use Neos\ContentRepository\Core\Feature\WorkspaceRebase\Event\WorkspaceWasRebased; use Neos\ContentRepository\Core\Projection\CatchUpHookInterface; +use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphReadModelInterface; use Neos\ContentRepository\Core\Projection\ContentGraph\NodeAggregate; +use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId; use Neos\ContentRepository\Core\SharedModel\Exception\WorkspaceDoesNotExist; use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId; use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateIds; @@ -107,7 +108,8 @@ public static function disabled(\Closure $fn): void public function __construct( - private readonly ContentRepository $contentRepository, + private readonly ContentRepositoryId $contentRepositoryId, + private readonly ContentGraphReadModelInterface $contentGraphReadModel, private readonly ContentCacheFlusher $contentCacheFlusher ) { } @@ -159,7 +161,7 @@ public function onBeforeEvent(EventInterface $eventInstance, EventEnvelope $even || $eventInstance instanceof NodeAggregateWasMoved ) { try { - $contentGraph = $this->contentRepository->getContentGraph($eventInstance->workspaceName); + $contentGraph = $this->contentGraphReadModel->getContentGraph($eventInstance->workspaceName); } catch (WorkspaceDoesNotExist) { return; } @@ -169,7 +171,7 @@ public function onBeforeEvent(EventInterface $eventInstance, EventEnvelope $even ); if ($nodeAggregate) { $this->scheduleCacheFlushJobForNodeAggregate( - $this->contentRepository, + $this->contentRepositoryId, $eventInstance->workspaceName, $nodeAggregate ); @@ -194,7 +196,7 @@ public function onAfterEvent(EventInterface $eventInstance, EventEnvelope $event || $eventInstance instanceof WorkspaceWasPartiallyDiscarded || $eventInstance instanceof WorkspaceWasRebased ) { - $this->scheduleCacheFlushJobForWorkspaceName($this->contentRepository, $eventInstance->workspaceName); + $this->scheduleCacheFlushJobForWorkspaceName($this->contentRepositoryId, $eventInstance->workspaceName); } elseif ( !($eventInstance instanceof NodeAggregateWasRemoved) && $eventInstance instanceof EmbedsNodeAggregateId @@ -202,7 +204,7 @@ public function onAfterEvent(EventInterface $eventInstance, EventEnvelope $event && $eventInstance instanceof EmbedsWorkspaceName ) { try { - $nodeAggregate = $this->contentRepository->getContentGraph($eventInstance->getWorkspaceName())->findNodeAggregateById( + $nodeAggregate = $this->contentGraphReadModel->getContentGraph($eventInstance->getWorkspaceName())->findNodeAggregateById( $eventInstance->getNodeAggregateId() ); } catch (WorkspaceDoesNotExist) { @@ -211,7 +213,7 @@ public function onAfterEvent(EventInterface $eventInstance, EventEnvelope $event if ($nodeAggregate) { $this->scheduleCacheFlushJobForNodeAggregate( - $this->contentRepository, + $this->contentRepositoryId, $eventInstance->getWorkspaceName(), $nodeAggregate ); @@ -220,13 +222,13 @@ public function onAfterEvent(EventInterface $eventInstance, EventEnvelope $event } private function scheduleCacheFlushJobForNodeAggregate( - ContentRepository $contentRepository, + ContentRepositoryId $contentRepositoryId, WorkspaceName $workspaceName, NodeAggregate $nodeAggregate ): void { // we store this in an associative array deduplicate. $this->flushNodeAggregateRequestsOnAfterCatchUp[$workspaceName->value . '__' . $nodeAggregate->nodeAggregateId->value] = FlushNodeAggregateRequest::create( - $contentRepository->id, + $contentRepositoryId, $workspaceName, $nodeAggregate->nodeAggregateId, $nodeAggregate->nodeTypeName, @@ -235,19 +237,19 @@ private function scheduleCacheFlushJobForNodeAggregate( } private function scheduleCacheFlushJobForWorkspaceName( - ContentRepository $contentRepository, + ContentRepositoryId $contentRepositoryId, WorkspaceName $workspaceName ): void { // we store this in an associative array deduplicate. $this->flushWorkspaceRequestsOnAfterCatchUp[$workspaceName->value] = FlushWorkspaceRequest::create( - $contentRepository->id, + $contentRepositoryId, $workspaceName, ); } private function determineAncestorNodeAggregateIds(WorkspaceName $workspaceName, NodeAggregateId $childNodeAggregateId): NodeAggregateIds { - $contentGraph = $this->contentRepository->getContentGraph($workspaceName); + $contentGraph = $this->contentGraphReadModel->getContentGraph($workspaceName); $stack = iterator_to_array($contentGraph->findParentNodeAggregates($childNodeAggregateId)); $ancestorNodeAggregateIds = []; diff --git a/Neos.Neos/Classes/Fusion/Cache/GraphProjectorCatchUpHookForCacheFlushingFactory.php b/Neos.Neos/Classes/Fusion/Cache/GraphProjectorCatchUpHookForCacheFlushingFactory.php index 62e8c499008..b2ea3d3a433 100644 --- a/Neos.Neos/Classes/Fusion/Cache/GraphProjectorCatchUpHookForCacheFlushingFactory.php +++ b/Neos.Neos/Classes/Fusion/Cache/GraphProjectorCatchUpHookForCacheFlushingFactory.php @@ -14,9 +14,14 @@ * source code. */ -use Neos\ContentRepository\Core\ContentRepository; use Neos\ContentRepository\Core\Projection\CatchUpHookFactoryInterface; +use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphReadModelInterface; +use Neos\ContentRepository\Core\Projection\ProjectionStateInterface; +use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId; +/** + * @implements CatchUpHookFactoryInterface + */ class GraphProjectorCatchUpHookForCacheFlushingFactory implements CatchUpHookFactoryInterface { public function __construct( @@ -24,10 +29,11 @@ public function __construct( ) { } - public function build(ContentRepository $contentRepository): GraphProjectorCatchUpHookForCacheFlushing + public function build(ContentRepositoryId $contentRepositoryId, ProjectionStateInterface $projectionState): GraphProjectorCatchUpHookForCacheFlushing { return new GraphProjectorCatchUpHookForCacheFlushing( - $contentRepository, + $contentRepositoryId, + $projectionState, $this->contentCacheFlusher ); }