Skip to content

Commit

Permalink
WIP: remove hacky loop detection in findAncestorNodeAggregateIds by…
Browse files Browse the repository at this point in the history
… applying event in test directly
  • Loading branch information
mhsdesign committed Sep 24, 2024
1 parent 4db7389 commit 127afd0
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,24 @@
use Doctrine\DBAL\Exception as DBALException;
use Doctrine\DBAL\Exception\InvalidArgumentException;
use Neos\ContentGraph\DoctrineDbalAdapter\ContentGraphTableNames;
use Neos\ContentGraph\DoctrineDbalAdapter\DoctrineDbalContentGraphProjection;
use Neos\ContentGraph\DoctrineDbalAdapter\DoctrineDbalProjectionIntegrityViolationDetectionRunnerFactory;
use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\NodeFactory;
use Neos\ContentGraph\DoctrineDbalAdapter\Tests\Behavior\Features\Bootstrap\Helpers\TestingNodeAggregateId;
use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePoint;
use Neos\ContentRepository\Core\DimensionSpace\OriginDimensionSpacePoint;
use Neos\ContentRepository\Core\EventStore\EventNormalizer;
use Neos\ContentRepository\Core\EventStore\EventPersister;
use Neos\ContentRepository\Core\Feature\ContentStreamEventStreamName;
use Neos\ContentRepository\Core\Feature\SubtreeTagging\Dto\SubtreeTag;
use Neos\ContentRepository\Core\Projection\Projections;
use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId;
use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId;
use Neos\ContentRepository\TestSuite\Behavior\Features\Bootstrap\CRTestSuiteRuntimeVariables;
use Neos\Error\Messages\Error;
use Neos\Error\Messages\Result;
use Neos\EventStore\Model\Event;
use Neos\EventStore\Model\EventEnvelope;
use PHPUnit\Framework\Assert;

/**
Expand Down Expand Up @@ -344,4 +351,45 @@ public function iExpectIntegrityViolationDetectionResultErrorNumberNToHaveCodeX(
$error->getCode()
);
}

/**
* @Given /^the event NodeAggregateWasMoved is hacky directly applied with payload:$/
* @param TableNode $payloadTable
* @throws \Exception
*/
public function applyNodeAggregateWasMoved(TableNode $payloadTable)
{
$eventPayload = $this->readPayloadTable($payloadTable);
$contentStreamId = ContentStreamId::fromString($eventPayload['contentStreamId']);
$streamName = ContentStreamEventStreamName::fromContentStreamId($contentStreamId);
$eventType = 'NodeAggregateWasMoved';

$artificiallyConstructedEvent = new Event(
Event\EventId::create(),
Event\EventType::fromString($eventType),
Event\EventData::fromString(json_encode($eventPayload)),
Event\EventMetadata::fromArray([])
);
/** @var EventPersister $eventPersister */
$eventPersister = (new \ReflectionClass($this->currentContentRepository))->getProperty('eventPersister')
->getValue($this->currentContentRepository);
/** @var EventNormalizer $eventNormalizer */
$eventNormalizer = (new \ReflectionClass($eventPersister))->getProperty('eventNormalizer')
->getValue($eventPersister);
/** @var Projections $projections */
$projections = (new \ReflectionClass($eventPersister))->getProperty('projections')
->getValue($eventPersister);

$event = $eventNormalizer->denormalize($artificiallyConstructedEvent);

$envelope = new EventEnvelope(
$artificiallyConstructedEvent,
$streamName->getEventStreamName(),
Event\Version::first(),
Event\SequenceNumber::none(),
new \DateTimeImmutable()
);

$projections->get(DoctrineDbalContentGraphProjection::class)->apply($event, $envelope);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -196,17 +196,8 @@ public function findAncestorNodeAggregateIds(NodeAggregateId $entryNodeAggregate
$ancestorNodeAggregateIds = [];
while ($stack !== []) {
$nodeAggregate = array_shift($stack);

// Prevent infinite loops
// NOTE: Normally, the content graph cannot contain cycles. However, during the
// testcase "Features/ProjectionIntegrityViolationDetection/AllNodesAreConnectedToARootNodePerSubgraph.feature"
// and in case of bugs, it could have actually cycles.
// The content cache catchup hook leverage this method and would otherwise be hanging up in an endless loop.
// That's why we track the seen NodeAggregateIds to be sure we don't travers them multiple times.
if (!in_array($nodeAggregate->nodeAggregateId, $ancestorNodeAggregateIds, false)) {
$ancestorNodeAggregateIds[] = $nodeAggregate->nodeAggregateId;
array_push($stack, ...iterator_to_array($this->findParentNodeAggregates($nodeAggregate->nodeAggregateId)));
}
$ancestorNodeAggregateIds[] = $nodeAggregate->nodeAggregateId;
array_push($stack, ...iterator_to_array($this->findParentNodeAggregates($nodeAggregate->nodeAggregateId)));
}
return NodeAggregateIds::fromArray($ancestorNodeAggregateIds);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,17 +191,8 @@ public function findAncestorNodeAggregateIds(NodeAggregateId $entryNodeAggregate
$ancestorNodeAggregateIds = [];
while ($stack !== []) {
$nodeAggregate = array_shift($stack);

// Prevent infinite loops
// NOTE: Normally, the content graph cannot contain cycles. However, during the
// testcase "Features/ProjectionIntegrityViolationDetection/AllNodesAreConnectedToARootNodePerSubgraph.feature"
// and in case of bugs, it could have actually cycles.
// The content cache catchup hook leverage this method and would otherwise be hanging up in an endless loop.
// That's why we track the seen NodeAggregateIds to be sure we don't travers them multiple times.
if (!in_array($nodeAggregate->nodeAggregateId, $ancestorNodeAggregateIds, false)) {
$ancestorNodeAggregateIds[] = $nodeAggregate->nodeAggregateId;
array_push($stack, ...iterator_to_array($this->findParentNodeAggregates($nodeAggregate->nodeAggregateId)));
}
$ancestorNodeAggregateIds[] = $nodeAggregate->nodeAggregateId;
array_push($stack, ...iterator_to_array($this->findParentNodeAggregates($nodeAggregate->nodeAggregateId)));
}
return NodeAggregateIds::fromArray($ancestorNodeAggregateIds);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ Feature: Run projection integrity violation detection regarding root connection
| parentNodeAggregateId | "sir-david-nodenborough" |
| nodeName | "child-document" |
| nodeAggregateClassification | "regular" |
And the event NodeAggregateWasMoved was published with payload:
# we must apply the event directly as the state is so corrupt that catchup hooks might fail like the content cache flusher
And the event NodeAggregateWasMoved is hacky directly applied with payload:
| Key | Value |
| workspaceName | "live" |
| contentStreamId | "cs-identifier" |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ protected function publishEvent(string $eventType, StreamName $streamName, array
/** @var EventPersister $eventPersister */
$eventPersister = (new \ReflectionClass($this->currentContentRepository))->getProperty('eventPersister')
->getValue($this->currentContentRepository);
/** @var EventNormalizer $eventPersister */
/** @var EventNormalizer $eventNormalizer */
$eventNormalizer = (new \ReflectionClass($eventPersister))->getProperty('eventNormalizer')
->getValue($eventPersister);
$event = $eventNormalizer->denormalize($artificiallyConstructedEvent);
Expand Down

0 comments on commit 127afd0

Please sign in to comment.