Skip to content

Commit db39252

Browse files
authored
Merge pull request #5506 from mhsdesign/bugfix/invoke-markStale-of-projections-after-subscription-engine-refactoring
TASK: Remove `markStale()` and `WithMarkStaleInterface` && Fully remove dead caching for `DocumentUriPathFinder`
2 parents ff294ec + 2748e4a commit db39252

File tree

9 files changed

+45
-229
lines changed

9 files changed

+45
-229
lines changed

Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentGraphReadModelInterface.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ interface ContentGraphReadModelInterface extends ProjectionStateInterface
3333
{
3434
/**
3535
* @throws WorkspaceDoesNotExist if the workspace does not exist
36-
* todo cache instances to reduce queries (revert https://github.com/neos/neos-development-collection/pull/5246)
3736
*/
3837
public function getContentGraph(WorkspaceName $workspaceName): ContentGraphInterface;
3938

Neos.ContentRepository.Core/Classes/Projection/ProjectionInterface.php

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,6 @@
1212
* Common interface for a Content Repository projection. This API is NOT exposed to the outside world, but is
1313
* the contract between {@see ContentRepository} and the individual projections.
1414
*
15-
* If the Projection needs to be notified that a catchup is about to happen, you can additionally
16-
* implement {@see WithMarkStaleInterface}. This is useful f.e. to disable runtime caches in the ProjectionState.
17-
*
1815
* @template-covariant TState of ProjectionStateInterface
1916
* @api you can write custom projections
2017
*/
@@ -33,10 +30,12 @@ public function status(): ProjectionStatus;
3330
public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void;
3431

3532
/**
36-
* NOTE: The ProjectionStateInterface returned must be ALWAYS THE SAME INSTANCE.
33+
* NOTE: The state will be accessed eagerly ONCE upon initialisation of the content repository
34+
* and put into the immutable {@see ProjectionStates} collection.
35+
* This ensures always the same instance is being returned when accessing it.
3736
*
38-
* If the Projection needs to be notified that a catchup is about to happen, you can additionally
39-
* implement {@see WithMarkStaleInterface}. This is useful f.e. to disable runtime caches in the ProjectionState.
37+
* Projections should on construction already have the state prepared, that also for internal
38+
* use cases the SAME INSTANCE is always used.
4039
*
4140
* @return TState
4241
*/

Neos.ContentRepository.Core/Classes/Projection/WithMarkStaleInterface.php

Lines changed: 0 additions & 28 deletions
This file was deleted.

Neos.Neos/Classes/FrontendRouting/Projection/DocumentUriPathFinder.php

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,6 @@
1818
*/
1919
final class DocumentUriPathFinder implements ProjectionStateInterface
2020
{
21-
private bool $cacheEnabled = true;
22-
23-
/**
24-
* @var array<string,DocumentNodeInfo>
25-
*/
26-
private array $getByIdAndDimensionSpacePointHashCache = [];
27-
2821
public function __construct(
2922
private readonly Connection $dbal,
3023
private readonly string $tableNamePrefix
@@ -76,10 +69,6 @@ public function getByIdAndDimensionSpacePointHash(
7669
NodeAggregateId $nodeAggregateId,
7770
string $dimensionSpacePointHash
7871
): DocumentNodeInfo {
79-
$cacheKey = $this->calculateCacheKey($nodeAggregateId, $dimensionSpacePointHash);
80-
if ($this->cacheEnabled && isset($this->getByIdAndDimensionSpacePointHashCache[$cacheKey])) {
81-
return $this->getByIdAndDimensionSpacePointHashCache[$cacheKey];
82-
}
8372
$result = $this->fetchSingle(
8473
'nodeAggregateId = :nodeAggregateId
8574
AND dimensionSpacePointHash = :dimensionSpacePointHash',
@@ -88,9 +77,6 @@ public function getByIdAndDimensionSpacePointHash(
8877
'dimensionSpacePointHash' => $dimensionSpacePointHash,
8978
]
9079
);
91-
if ($this->cacheEnabled) {
92-
$this->getByIdAndDimensionSpacePointHashCache[$cacheKey] = $result;
93-
}
9480
return $result;
9581
}
9682

@@ -274,25 +260,6 @@ private function fetchMultiple(string $where, array $parameters): DocumentNodeIn
274260
);
275261
}
276262

277-
private function calculateCacheKey(NodeAggregateId $nodeAggregateId, string $dimensionSpacePointHash): string
278-
{
279-
return $nodeAggregateId->value . '#' . $dimensionSpacePointHash;
280-
}
281-
282-
public function purgeCacheFor(DocumentNodeInfo $nodeInfo): void
283-
{
284-
if ($this->cacheEnabled) {
285-
$cacheKey = $this->calculateCacheKey($nodeInfo->getNodeAggregateId(), $nodeInfo->getDimensionSpacePointHash());
286-
unset($this->getByIdAndDimensionSpacePointHashCache[$cacheKey]);
287-
}
288-
}
289-
290-
public function disableCache(): void
291-
{
292-
$this->cacheEnabled = false;
293-
$this->getByIdAndDimensionSpacePointHashCache = [];
294-
}
295-
296263
/**
297264
* Returns the DocumentNodeInfos of all descendants of a given node.
298265
* Note: This will not exclude *disabled* nodes in order to allow the calling side

Neos.Neos/Classes/FrontendRouting/Projection/DocumentUriPathProjection.php

Lines changed: 19 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
use Neos\ContentRepository\Core\NodeType\NodeTypeName;
3030
use Neos\ContentRepository\Core\Projection\ProjectionInterface;
3131
use Neos\ContentRepository\Core\Projection\ProjectionStatus;
32-
use Neos\ContentRepository\Core\Projection\WithMarkStaleInterface;
3332
use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId;
3433
use Neos\ContentRepository\Core\SharedModel\Node\PropertyName;
3534
use Neos\EventStore\Model\EventEnvelope;
@@ -41,13 +40,13 @@
4140
* @implements ProjectionInterface<DocumentUriPathFinder>
4241
* @internal implementation detail to manage document node uris. For resolving please use the NodeUriBuilder and for matching the Router.
4342
*/
44-
final class DocumentUriPathProjection implements ProjectionInterface, WithMarkStaleInterface
43+
final class DocumentUriPathProjection implements ProjectionInterface
4544
{
4645
public const COLUMN_TYPES_DOCUMENT_URIS = [
4746
'shortcutTarget' => Types::JSON,
4847
];
4948

50-
private ?DocumentUriPathFinder $stateAccessor = null;
49+
private DocumentUriPathFinder $documentUriPathFinder;
5150

5251
/**
5352
* @var array<string, DocumentTypeClassification>
@@ -59,6 +58,7 @@ public function __construct(
5958
private readonly Connection $dbal,
6059
private readonly string $tableNamePrefix,
6160
) {
61+
$this->documentUriPathFinder = new DocumentUriPathFinder($this->dbal, $this->tableNamePrefix);
6262
}
6363

6464
public function setUp(): void
@@ -101,7 +101,6 @@ private function determineRequiredSqlStatements(): array
101101
public function resetState(): void
102102
{
103103
$this->truncateDatabaseTables();
104-
$this->stateAccessor = null;
105104
}
106105

107106
private function truncateDatabaseTables(): void
@@ -136,13 +135,7 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void
136135

137136
public function getState(): DocumentUriPathFinder
138137
{
139-
if (!$this->stateAccessor) {
140-
$this->stateAccessor = new DocumentUriPathFinder($this->dbal, $this->tableNamePrefix);
141-
142-
// !!! Bugfix #4253: during projection replay/update, it is crucial to have caches disabled.
143-
$this->stateAccessor->disableCache();
144-
}
145-
return $this->stateAccessor;
138+
return $this->documentUriPathFinder;
146139
}
147140

148141
private function whenRootNodeAggregateWithNodeWasCreated(RootNodeAggregateWithNodeWasCreated $event): void
@@ -174,7 +167,7 @@ private function whenRootNodeAggregateDimensionsWereUpdated(RootNodeAggregateDim
174167
// Zero-dimensional means DimensionSpacePoint::fromArray([])->hash
175168
assert(is_string($anyPointHash));
176169

177-
$nodeInSomeDimension = $this->tryGetNode(fn () => $this->getState()->getByIdAndDimensionSpacePointHash(
170+
$nodeInSomeDimension = $this->tryGetNode(fn () => $this->documentUriPathFinder->getByIdAndDimensionSpacePointHash(
178171
$event->nodeAggregateId,
179172
$anyPointHash
180173
));
@@ -223,7 +216,7 @@ private function whenNodeAggregateWithNodeWasCreated(NodeAggregateWithNodeWasCre
223216
}
224217

225218
foreach ($event->succeedingSiblingsForCoverage->toDimensionSpacePointSet() as $dimensionSpacePoint) {
226-
$parentNode = $this->tryGetNode(fn () => $this->getState()->getByIdAndDimensionSpacePointHash(
219+
$parentNode = $this->tryGetNode(fn () => $this->documentUriPathFinder->getByIdAndDimensionSpacePointHash(
227220
$event->parentNodeAggregateId,
228221
$dimensionSpacePoint->hash
229222
));
@@ -236,7 +229,7 @@ private function whenNodeAggregateWithNodeWasCreated(NodeAggregateWithNodeWasCre
236229

237230
$succeedingSiblingNodeAggregateId = $event->succeedingSiblingsForCoverage->getSucceedingSiblingIdForDimensionSpacePoint($dimensionSpacePoint);
238231
if ($succeedingSiblingNodeAggregateId === null) {
239-
$precedingNode = $this->tryGetNode(fn () => $this->getState()->getLastChildNode(
232+
$precedingNode = $this->tryGetNode(fn () => $this->documentUriPathFinder->getLastChildNode(
240233
$parentNode->getNodeAggregateId(),
241234
$dimensionSpacePoint->hash
242235
));
@@ -248,7 +241,7 @@ private function whenNodeAggregateWithNodeWasCreated(NodeAggregateWithNodeWasCre
248241
]);
249242
}
250243
} else {
251-
$precedingNode = $this->tryGetNode(fn () => $this->getState()->getPrecedingNode(
244+
$precedingNode = $this->tryGetNode(fn () => $this->documentUriPathFinder->getPrecedingNode(
252245
$succeedingSiblingNodeAggregateId,
253246
$parentNode->getNodeAggregateId(),
254247
$dimensionSpacePoint->hash
@@ -377,7 +370,7 @@ private function copyVariants(
377370
OriginDimensionSpacePoint $targetOrigin,
378371
InterdimensionalSiblings $interdimensionalSiblings,
379372
): void {
380-
$sourceNode = $this->tryGetNode(fn () => $this->getState()->getByIdAndDimensionSpacePointHash(
373+
$sourceNode = $this->tryGetNode(fn () => $this->documentUriPathFinder->getByIdAndDimensionSpacePointHash(
381374
$nodeAggregateId,
382375
$sourceOrigin->hash
383376
));
@@ -397,7 +390,7 @@ private function copyVariants(
397390

398391
// check the parent in the "target" dimensionSpacePoint for the "URI prefix",
399392
// may be different, see neos/neos-development-collection#5090
400-
$parentNode = $this->tryGetNode(fn () => $this->getState()->getByIdAndDimensionSpacePointHash(
393+
$parentNode = $this->tryGetNode(fn () => $this->documentUriPathFinder->getByIdAndDimensionSpacePointHash(
401394
$sourceNode->getParentNodeAggregateId(),
402395
$interdimensionalSibling->dimensionSpacePoint->hash
403396
));
@@ -422,7 +415,7 @@ private function whenSubtreeWasTagged(SubtreeWasTagged $event): void
422415
return;
423416
}
424417
foreach ($event->affectedDimensionSpacePoints as $dimensionSpacePoint) {
425-
$node = $this->tryGetNode(fn () => $this->getState()->getByIdAndDimensionSpacePointHash(
418+
$node = $this->tryGetNode(fn () => $this->documentUriPathFinder->getByIdAndDimensionSpacePointHash(
426419
$event->nodeAggregateId,
427420
$dimensionSpacePoint->hash
428421
));
@@ -451,7 +444,7 @@ private function whenSubtreeWasUntagged(SubtreeWasUntagged $event): void
451444
}
452445

453446
foreach ($event->affectedDimensionSpacePoints as $dimensionSpacePoint) {
454-
$node = $this->tryGetNode(fn () => $this->getState()->getByIdAndDimensionSpacePointHash(
447+
$node = $this->tryGetNode(fn () => $this->documentUriPathFinder->getByIdAndDimensionSpacePointHash(
455448
$event->nodeAggregateId,
456449
$dimensionSpacePoint->hash
457450
));
@@ -479,7 +472,7 @@ private function whenNodeAggregateWasRemoved(NodeAggregateWasRemoved $event): vo
479472
return;
480473
}
481474
foreach ($event->affectedCoveredDimensionSpacePoints as $dimensionSpacePoint) {
482-
$node = $this->tryGetNode(fn () => $this->getState()->getByIdAndDimensionSpacePointHash(
475+
$node = $this->tryGetNode(fn () => $this->documentUriPathFinder->getByIdAndDimensionSpacePointHash(
483476
$event->nodeAggregateId,
484477
$dimensionSpacePoint->hash
485478
));
@@ -499,7 +492,6 @@ private function whenNodeAggregateWasRemoved(NodeAggregateWasRemoved $event): vo
499492
'nodeAggregateId' => $node->getNodeAggregateId()->value,
500493
'childNodeAggregateIdPathPrefix' => $node->getNodeAggregateIdPath() . '/%',
501494
]);
502-
$this->getState()->purgeCacheFor($node);
503495
}
504496
}
505497

@@ -520,7 +512,7 @@ private function whenNodePropertiesWereSet(NodePropertiesWereSet $event): void
520512
}
521513

522514
foreach ($event->affectedDimensionSpacePoints as $affectedDimensionSpacePoint) {
523-
$node = $this->tryGetNode(fn () => $this->getState()->getByIdAndDimensionSpacePointHash(
515+
$node = $this->tryGetNode(fn () => $this->documentUriPathFinder->getByIdAndDimensionSpacePointHash(
524516
$event->nodeAggregateId,
525517
$affectedDimensionSpacePoint->hash
526518
));
@@ -570,7 +562,6 @@ private function whenNodePropertiesWereSet(NodePropertiesWereSet $event): void
570562
'childNodeAggregateIdPathPrefix' => $node->getNodeAggregateIdPath() . '/%',
571563
]
572564
);
573-
$this->getState()->purgeCacheFor($node);
574565
}
575566
}
576567

@@ -581,7 +572,7 @@ private function whenNodeAggregateWasMoved(NodeAggregateWasMoved $event): void
581572
}
582573

583574
foreach ($event->succeedingSiblingsForCoverage as $succeedingSiblingForCoverage) {
584-
$node = $this->tryGetNode(fn () => $this->getState()->getByIdAndDimensionSpacePointHash(
575+
$node = $this->tryGetNode(fn () => $this->documentUriPathFinder->getByIdAndDimensionSpacePointHash(
585576
$event->nodeAggregateId,
586577
$succeedingSiblingForCoverage->dimensionSpacePoint->hash
587578
));
@@ -595,8 +586,6 @@ private function whenNodeAggregateWasMoved(NodeAggregateWasMoved $event): void
595586
$event->newParentNodeAggregateId,
596587
$succeedingSiblingForCoverage->nodeAggregateId
597588
);
598-
599-
$this->getState()->purgeCacheFor($node);
600589
}
601590
}
602591

@@ -612,7 +601,7 @@ private function moveNode(
612601
if (!$newParentNodeAggregateId || $newParentNodeAggregateId->equals($node->getParentNodeAggregateId())) {
613602
return;
614603
}
615-
$newParentNode = $this->tryGetNode(fn () => $this->getState()->getByIdAndDimensionSpacePointHash(
604+
$newParentNode = $this->tryGetNode(fn () => $this->documentUriPathFinder->getByIdAndDimensionSpacePointHash(
616605
$newParentNodeAggregateId,
617606
$node->getDimensionSpacePointHash()
618607
));
@@ -622,7 +611,7 @@ private function moveNode(
622611
return;
623612
}
624613

625-
$oldParentNode = $this->tryGetNode(fn () => $this->getState()->getByIdAndDimensionSpacePointHash(
614+
$oldParentNode = $this->tryGetNode(fn () => $this->documentUriPathFinder->getByIdAndDimensionSpacePointHash(
626615
$node->getParentNodeAggregateId(),
627616
$node->getDimensionSpacePointHash()
628617
));
@@ -868,7 +857,7 @@ private function connectNodeWithSiblings(
868857
?NodeAggregateId $newSucceedingNodeAggregateId,
869858
): void {
870859
if ($newSucceedingNodeAggregateId !== null) {
871-
$newPrecedingNode = $this->tryGetNode(fn () => $this->getState()->getPrecedingNode(
860+
$newPrecedingNode = $this->tryGetNode(fn () => $this->documentUriPathFinder->getPrecedingNode(
872861
$newSucceedingNodeAggregateId,
873862
$parentNodeAggregateId,
874863
$node->getDimensionSpacePointHash()
@@ -881,7 +870,7 @@ private function connectNodeWithSiblings(
881870
['precedingNodeAggregateId' => $node->getNodeAggregateId()->value]
882871
);
883872
} else {
884-
$newPrecedingNode = $this->tryGetNode(fn () => $this->getState()->getLastChildNodeNotBeing(
873+
$newPrecedingNode = $this->tryGetNode(fn () => $this->documentUriPathFinder->getLastChildNodeNotBeing(
885874
$parentNodeAggregateId,
886875
$node->getDimensionSpacePointHash(),
887876
$node->getNodeAggregateId()
@@ -985,9 +974,4 @@ private function whenDimensionShineThroughWasAdded(DimensionShineThroughWasAdded
985974
}
986975
}
987976
}
988-
989-
public function markStale(): void
990-
{
991-
$this->getState()->disableCache();
992-
}
993977
}

Neos.Neos/Classes/Package.php

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
use Neos\Neos\Domain\Model\Site;
3030
use Neos\Neos\Domain\Service\SiteService;
3131
use Neos\Neos\Fusion\Cache\AssetChangeHandlerForCacheFlushing;
32-
use Neos\Neos\Routing\Cache\RouteCacheFlusher;
3332

3433
/**
3534
* The Neos Package
@@ -110,13 +109,6 @@ function (
110109
'assignUploadedAssetToSiteAssetCollection'
111110
);
112111

113-
$dispatcher->connect(
114-
PersistenceManager::class,
115-
'allObjectsPersisted',
116-
RouteCacheFlusher::class,
117-
'commit'
118-
);
119-
120112
$dispatcher->connect(
121113
SiteService::class,
122114
'sitePruned',

0 commit comments

Comments
 (0)