diff --git a/Classes/CommandHandler/CommandHandlerInterface.php b/Classes/CommandHandler/CommandHandlerInterface.php index 5d6da59a..5d1dbe0b 100644 --- a/Classes/CommandHandler/CommandHandlerInterface.php +++ b/Classes/CommandHandler/CommandHandlerInterface.php @@ -9,8 +9,7 @@ /** * Common interface for all Content Repository command handlers * - * Note: The Content Repository instance is passed to the handle() method for it to do soft-constraint checks or - * trigger "sub commands" + * The {@see CommandHandlingDependencies} are available during handling to do soft-constraint checks * * @internal no public API, because commands are no extension points of the CR */ @@ -19,6 +18,11 @@ interface CommandHandlerInterface public function canHandle(CommandInterface $command): bool; /** + * "simple" command handlers return EventsToPublish directly + * + * For the case of the workspace command handler who need to publish to many streams and "close" the content-stream directly, + * it's allowed to yield the events to interact with the control flow of event publishing. + * * @return EventsToPublish|\Generator */ public function handle(CommandInterface $command, CommandHandlingDependencies $commandHandlingDependencies): EventsToPublish|\Generator; diff --git a/Classes/CommandHandler/CommandSimulator.php b/Classes/CommandHandler/CommandSimulator.php index 65355319..718186ac 100644 --- a/Classes/CommandHandler/CommandSimulator.php +++ b/Classes/CommandHandler/CommandSimulator.php @@ -4,7 +4,6 @@ namespace Neos\ContentRepository\Core\CommandHandler; -use Neos\ContentRepository\Core\ContentRepository; use Neos\ContentRepository\Core\EventStore\DecoratedEvent; use Neos\ContentRepository\Core\EventStore\EventInterface; use Neos\ContentRepository\Core\EventStore\EventNormalizer; @@ -21,7 +20,24 @@ use Neos\EventStore\Model\EventStream\VirtualStreamName; /** - * Implementation detail of {@see ContentRepository::handle}, when rebasing or partially publishing + * The CommandSimulator is used during the publishing process, for partial publishing and workspace rebasing. + * + * For this case, we want to apply commands including their constraint checks step by step, to see whether this + * set of commands applies cleanly without errors, and which events would be created by them, but we do NOT + * want to commit the updated projections or events. + * + * Internally, we do the following: + * - Create a database transaction in the GraphProjection which we will roll back lateron (to dry-run + * projection updates) (via {@see CommandSimulator::run()}). + * - Create an InMemoryEventStore which buffers created events by command handlers. + * - execute all commands via {@see CommandSimulator::handle()} + * - -> this will do all constraint checks based on the projection in the open transaction (so it sees + * previously modified projection state which is not committed) + * - -> it will run the command handlers, buffer all emitted events in the InMemoryEventStore + * -> note to avoid full recursion the workspace command handler is not included in the bus + * - -> update the GraphProjection, but WITHOUT committing the transaction. + * + * This is quite performant because we do not need to fork a new content stream. * * @internal */ @@ -54,7 +70,8 @@ public function run(callable $fn): mixed */ private function handle(RebaseableCommand $rebaseableCommand): void { - // FIXME: Check if workspace already matches and skip this ($command->workspaceName === workspaceNameToSimulateIn) ... + // FIXME: Check if workspace already matches and skip this, e.g. $commandInWorkspace = $command->getWorkspaceName()->equals($this->workspaceNameToSimulateIn) ? $command : $command->createCopyForWorkspace($this->workspaceNameToSimulateIn); + // when https://github.com/neos/neos-development-collection/pull/5298 is merged $commandInWorkspace = $rebaseableCommand->originalCommand->createCopyForWorkspace($this->workspaceNameToSimulateIn); $eventsToPublish = $this->commandBus->handle($commandInWorkspace); diff --git a/Classes/Projection/ProjectionInterface.php b/Classes/Projection/ProjectionInterface.php index 01ac2376..22c65ced 100644 --- a/Classes/Projection/ProjectionInterface.php +++ b/Classes/Projection/ProjectionInterface.php @@ -47,6 +47,4 @@ public function getCheckpointStorage(): CheckpointStorageInterface; public function getState(): ProjectionStateInterface; public function reset(): void; - - // public function temporaryChanges(\Closure $fn): void; }