Skip to content

Commit

Permalink
WIP: Reintroduced initial EventMigrationService
Browse files Browse the repository at this point in the history
During extending phpstan to more packages (neos#4650) the migration was dropped.
The code had become already outdated by then as the api was changed a lot.
This service should function as boilerplate for new migrations.

WIP: Try to fix previous `EventMigrationService`

After neos#4405 a lot of things changed.

WIP: Write migration for workspace rename

untested.
  • Loading branch information
mhsdesign committed Mar 13, 2024
1 parent 6c998f8 commit 7e41bb6
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,20 @@ public function migratePropertiesToUnsetCommand(string $contentRepository = 'def
$eventMigrationService = $this->contentRepositoryRegistry->buildService($contentRepositoryId, $this->eventMigrationServiceFactory);
$eventMigrationService->migratePropertiesToUnset($this->outputLine(...));
}

/**
* Add the workspace name to the events meta-data, so it can be replayed.
*
* Needed for #4708: https://github.com/neos/neos-development-collection/pull/4708
*
* Included in February 2023 - before Neos 9.0 Beta 3.
*
* @param string $contentRepository Identifier of the Content Repository to set up
*/
public function fillWorkspaceNameInCommandPayloadOfEventMetaDataCommand(string $contentRepository = 'default'): void
{
$contentRepositoryId = ContentRepositoryId::fromString($contentRepository);
$eventMigrationService = $this->contentRepositoryRegistry->buildService($contentRepositoryId, $this->eventMigrationServiceFactory);
$eventMigrationService->fillWorkspaceNameInCommandPayloadOfEventMetaData($this->outputLine(...));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
use Neos\ContentRepository\Core\Feature\NodeModification\Command\SetSerializedNodeProperties;
use Neos\ContentRepository\Core\Projection\CatchUpOptions;
use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphProjection;
use Neos\ContentRepository\Core\Projection\Workspace\WorkspaceFinder;
use Neos\ContentRepository\Core\Projection\Workspace\WorkspaceProjection;
use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId;
use Neos\ContentRepositoryRegistry\Command\MigrateEventsCommandController;
use Neos\ContentRepositoryRegistry\Factory\EventStore\DoctrineEventStoreFactory;
use Neos\EventStore\EventStoreInterface;
Expand Down Expand Up @@ -222,6 +225,86 @@ public function migratePropertiesToUnset(\Closure $outputFn)
}
}


/**
* Add the workspace name to the events meta-data, so it can be replayed.
*
* Needed for #4708: https://github.com/neos/neos-development-collection/pull/4708
*
* Included in February 2023 - before Neos 9.0 Beta 3.
*
* @param \Closure $outputFn
* @return void
*/
public function fillWorkspaceNameInCommandPayloadOfEventMetaData(\Closure $outputFn)
{

$backupEventTableName = DoctrineEventStoreFactory::databaseTableName($this->contentRepositoryId)
. '_bak_' . date('Y_m_d_H_i_s');
$outputFn('Backup: copying events table to %s', [$backupEventTableName]);

$this->copyEventTable($backupEventTableName);

$outputFn('Backup completed. Resetting WorkspaceProjection.');
$this->contentRepository->resetProjectionState(WorkspaceProjection::class);

$workspaceProjection = $this->projections->get(WorkspaceProjection::class);
$workspaceFinder = $workspaceProjection->getState();
assert($workspaceFinder instanceof WorkspaceFinder);

$streamName = VirtualStreamName::all();
$eventStream = $this->eventStore->load($streamName);
foreach ($eventStream as $eventEnvelope) {
if (!$eventEnvelope->event->metadata) {
continue;
}
$eventMetaData = $eventEnvelope->event->metadata->value;

if (!in_array($eventMetaData['commandClass'] ?? null, [
// todo extend list
SetSerializedNodeProperties::class
])) {
continue;
}

if (!isset($eventMetaData['commandPayload']['contentStreamId']) || isset($eventMetaData['commandPayload']['workspaceName'])) {
continue;
}

// Replay the projection until before the current event
$this->contentRepository->catchUpProjection(WorkspaceProjection::class, CatchUpOptions::create(maximumSequenceNumber: $eventEnvelope->sequenceNumber->previous()));

// now we can ask the read model
$workspace = $workspaceFinder->findOneByCurrentContentStreamId(ContentStreamId::fromString($eventMetaData['commandPayload']['contentStreamId']));

// ... and update the event
if (!$workspace) {
// todo does not exist, but as the value is not important when rebasing, as bernhard said, we will just enter a dummy.
$eventMetaData['commandPayload']['workspaceName'] = 'dummystring';
} else {
$eventMetaData['commandPayload']['workspaceName'] = $workspace->workspaceName->value;
}
unset($eventMetaData['commandPayload']['contentStreamId']);

$outputFn(
'Rewriting %s: (%s, ContentStreamId: %s) => WorkspaceName: %s',
[
$eventEnvelope->sequenceNumber->value,
$eventEnvelope->event->type->value,
$eventMetaData['commandPayload']['contentStreamId'],
$eventMetaData['commandPayload']['workspaceName']
]
);

$this->updateEventMetaData($eventEnvelope->sequenceNumber, $eventMetaData);
}

$outputFn('Rewriting completed. Now catching up the WorkspaceProjection to final state.');
$this->contentRepository->catchUpProjection(WorkspaceProjection::class, CatchUpOptions::create());

$outputFn('All done.');
}

/**
* @param array<mixed> $payload
*/
Expand Down

0 comments on commit 7e41bb6

Please sign in to comment.