From d06833943ba40940bd1a7e082d972dc4a5af4a5c Mon Sep 17 00:00:00 2001
From: mhsdesign <85400359+mhsdesign@users.noreply.github.com>
Date: Thu, 14 Nov 2024 11:25:17 +0100
Subject: [PATCH] TASK: Remove `fixReplay` command
we would have to delete too many events that were legit as well, like a move AFTER a deletion https://github.com/neos/neos-development-collection/issues/5364
---
.../NeosBetaMigrationCommandController.php | 113 ------------------
1 file changed, 113 deletions(-)
diff --git a/Neos.ContentRepositoryRegistry/Classes/Command/NeosBetaMigrationCommandController.php b/Neos.ContentRepositoryRegistry/Classes/Command/NeosBetaMigrationCommandController.php
index b565b6734d..ac63222d7f 100644
--- a/Neos.ContentRepositoryRegistry/Classes/Command/NeosBetaMigrationCommandController.php
+++ b/Neos.ContentRepositoryRegistry/Classes/Command/NeosBetaMigrationCommandController.php
@@ -6,12 +6,10 @@
use Doctrine\DBAL\ArrayParameterType;
use Doctrine\DBAL\Connection;
-use Neos\ContentGraph\DoctrineDbalAdapter\DoctrineDbalContentGraphProjection;
use Neos\ContentRepository\Core\Factory\ContentRepositoryServiceFactoryDependencies;
use Neos\ContentRepository\Core\Factory\ContentRepositoryServiceFactoryInterface;
use Neos\ContentRepository\Core\Factory\ContentRepositoryServiceInterface;
use Neos\ContentRepository\Core\Feature\ContentStreamEventStreamName;
-use Neos\ContentRepository\Core\Projection\CatchUpOptions;
use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId;
use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName;
use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry;
@@ -20,14 +18,12 @@
use Neos\EventStore\Model\Event\EventMetadata;
use Neos\EventStore\Model\Event\EventType;
use Neos\EventStore\Model\Event\EventTypes;
-use Neos\EventStore\Model\Event\SequenceNumber;
use Neos\EventStore\Model\EventEnvelope;
use Neos\EventStore\Model\Events;
use Neos\EventStore\Model\EventStream\EventStreamFilter;
use Neos\EventStore\Model\EventStream\ExpectedVersion;
use Neos\Flow\Annotations as Flow;
use Neos\Flow\Cli\CommandController;
-use Symfony\Component\Console\Helper\ProgressBar;
class NeosBetaMigrationCommandController extends CommandController
{
@@ -92,88 +88,6 @@ public function reorderNodeAggregateWasRemovedCommand(string $contentRepository
$this->outputLine('Reordered %d removals. Please replay and rebase your other workspaces.', [count($eventsToReorder)]);
}
- public function fixReplayCommand(string $contentRepository = 'default', bool $resetProjection = true): void
- {
- $contentRepositoryId = ContentRepositoryId::fromString($contentRepository);
- $contentRepository = $this->contentRepositoryRegistry->get($contentRepositoryId);
-
- $this->backup($contentRepositoryId);
-
-
- $progressBar = new ProgressBar($this->output->getOutput());
-
- $progressBar->start($this->highestSequenceNumber($contentRepositoryId)->value, 1);
- $options = CatchUpOptions::create(progressCallback: fn () => $progressBar->advance());
-
- if ($resetProjection) {
- $contentRepository->resetProjectionState(DoctrineDbalContentGraphProjection::class);
- }
-
- $automaticRemovedSequenceNumbers = [];
- $manualRemovedSequenceNumbers = [];
-
- do {
- try {
- $contentRepository->catchUpProjection(DoctrineDbalContentGraphProjection::class, $options);
- } catch (\Throwable $e) {
- $this->outputLine();
-
- if (preg_match('/^Exception while catching up to sequence number (\d+)/', $e->getMessage(), $matches) !== 1) {
- $this->outputLine('Could not replay because of unexpected error');
- $this->outputLine('Removed %d other events: %s', [count($automaticRemovedSequenceNumbers), join(', ', $automaticRemovedSequenceNumbers)]);
- throw $e;
- }
- $failedSequenceNumber = SequenceNumber::fromInteger((int)$matches[1]);
-
- $eventRow = $this->getEventEnvelopeData($failedSequenceNumber, $contentRepositoryId);
-
- if ($eventRow['metadata'] !== null) {
- $this->outputLine('Did not delete event %s because it doesnt seem to be auto generated', [$failedSequenceNumber->value]);
- $this->outputLine('The exception: %s', [$e->getMessage()]);
- $this->outputLine(json_encode($eventRow, JSON_PRETTY_PRINT));
- $this->outputLine();
- if ($this->output->askConfirmation(sprintf('> still delete it %d? (y/n) ', $failedSequenceNumber->value), false)) {
- $manualRemovedSequenceNumbers[] = $failedSequenceNumber->value;
- $this->deleteEvent($failedSequenceNumber, $contentRepositoryId);
- continue;
- }
- $this->outputLine('Removed %d other events: %s', [count($automaticRemovedSequenceNumbers), join(', ', $automaticRemovedSequenceNumbers)]);
- throw $e;
- }
-
- $this->outputLine('Deleted event %s because it seems to be invalid and auto generated', [$failedSequenceNumber->value]);
- $this->outputLine(json_encode($eventRow));
-
- $automaticRemovedSequenceNumbers[] = $failedSequenceNumber->value;
- $this->deleteEvent($failedSequenceNumber, $contentRepositoryId);
-
- $this->outputLine();
- continue;
- }
-
- $progressBar->finish();
-
- $this->outputLine();
- $this->outputLine('Replay was successfully.');
- $this->outputLine('Removed %d automatic events: %s', [count($automaticRemovedSequenceNumbers), join(', ', $automaticRemovedSequenceNumbers)]);
- if ($manualRemovedSequenceNumbers) {
- $this->outputLine('Also removed %d events manually: %s', [count($manualRemovedSequenceNumbers), join(', ', $manualRemovedSequenceNumbers)]);
- }
-
- return;
-
- } while (true);
- }
-
- public function highestSequenceNumber(ContentRepositoryId $contentRepositoryId): SequenceNumber
- {
- $eventTableName = DoctrineEventStoreFactory::databaseTableName($contentRepositoryId);
- return SequenceNumber::fromInteger((int)$this->connection->fetchOne(
- 'SELECT sequencenumber FROM ' . $eventTableName . ' ORDER BY sequencenumber ASC'
- ));
- }
-
-
private function backup(ContentRepositoryId $contentRepositoryId): void
{
$backupEventTableName = DoctrineEventStoreFactory::databaseTableName($contentRepositoryId)
@@ -182,33 +96,6 @@ private function backup(ContentRepositoryId $contentRepositoryId): void
$this->outputLine(sprintf('Copied events table to %s', $backupEventTableName));
}
- /**
- * @return array
- */
- private function getEventEnvelopeData(SequenceNumber $sequenceNumber, ContentRepositoryId $contentRepositoryId): array
- {
- $eventTableName = DoctrineEventStoreFactory::databaseTableName($contentRepositoryId);
- return $this->connection->fetchAssociative(
- 'SELECT * FROM ' . $eventTableName . ' WHERE sequencenumber=:sequenceNumber',
- [
- 'sequenceNumber' => $sequenceNumber->value,
- ]
- );
- }
-
- private function deleteEvent(SequenceNumber $sequenceNumber, ContentRepositoryId $contentRepositoryId): void
- {
- $eventTableName = DoctrineEventStoreFactory::databaseTableName($contentRepositoryId);
- $this->connection->beginTransaction();
- $this->connection->executeStatement(
- 'DELETE FROM ' . $eventTableName . ' WHERE sequencenumber=:sequenceNumber',
- [
- 'sequenceNumber' => $sequenceNumber->value
- ]
- );
- $this->connection->commit();
- }
-
private function copyEventTable(string $backupEventTableName, ContentRepositoryId $contentRepositoryId): void
{
$eventTableName = DoctrineEventStoreFactory::databaseTableName($contentRepositoryId);