Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/9.0' into bugfix/publish-only-ac…
Browse files Browse the repository at this point in the history
…ross-all-dimensions
  • Loading branch information
mhsdesign committed Dec 5, 2024
2 parents 7e07940 + 9c42da3 commit 6e9b3e7
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 8 deletions.
25 changes: 18 additions & 7 deletions Classes/Feature/WorkspaceCommandHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
use Neos\ContentRepository\Core\Feature\WorkspaceRebase\Command\RebaseWorkspace;
use Neos\ContentRepository\Core\Feature\WorkspaceRebase\Dto\RebaseErrorHandlingStrategy;
use Neos\ContentRepository\Core\Feature\WorkspaceRebase\Event\WorkspaceWasRebased;
use Neos\ContentRepository\Core\Feature\WorkspaceRebase\Exception\PartialWorkspaceRebaseFailed;
use Neos\ContentRepository\Core\Feature\WorkspaceRebase\Exception\WorkspaceRebaseFailed;
use Neos\ContentRepository\Core\SharedModel\Exception\ContentStreamAlreadyExists;
use Neos\ContentRepository\Core\SharedModel\Exception\ContentStreamDoesNotExistYet;
Expand Down Expand Up @@ -505,8 +506,14 @@ static function ($handle) use ($commandSimulator, $matchingCommands, $remainingC
yield $this->reopenContentStreamWithoutConstraintChecks(
$workspace->currentContentStreamId
);

throw WorkspaceRebaseFailed::duringPublish($commandSimulator->getConflictingEvents());
match ($workspace->status) {
// If the workspace is up-to-date it must be a problem regarding that the order of events cannot be changed
WorkspaceStatus::UP_TO_DATE =>
throw PartialWorkspaceRebaseFailed::duringPartialPublish($commandSimulator->getConflictingEvents()),
// If the workspace is outdated we cannot know for sure but suspect that the conflict arose due to changes in the base workspace.
WorkspaceStatus::OUTDATED =>
throw WorkspaceRebaseFailed::duringPublish($commandSimulator->getConflictingEvents())
};
}

// this could empty and a no-op for the rare case when a command returns empty events e.g. the node was already tagged with this subtree tag
Expand Down Expand Up @@ -605,7 +612,6 @@ private function handleDiscardIndividualNodesFromWorkspace(
// quick path everything was discarded
yield from $this->discardWorkspace(
$workspace,
$workspaceContentStreamVersion,
$baseWorkspace,
$baseWorkspaceContentStreamVersion,
$command->newContentStreamId
Expand All @@ -627,7 +633,14 @@ static function ($handle) use ($commandsToKeep): void {
yield $this->reopenContentStreamWithoutConstraintChecks(
$workspace->currentContentStreamId
);
throw WorkspaceRebaseFailed::duringDiscard($commandSimulator->getConflictingEvents());
match ($workspace->status) {
// If the workspace is up-to-date it must be a problem regarding that the order of events cannot be changed
WorkspaceStatus::UP_TO_DATE =>
throw PartialWorkspaceRebaseFailed::duringPartialDiscard($commandSimulator->getConflictingEvents()),
// If the workspace is outdated we cannot know for sure but suspect that the conflict arose due to changes in the base workspace.
WorkspaceStatus::OUTDATED =>
throw WorkspaceRebaseFailed::duringDiscard($commandSimulator->getConflictingEvents())
};
}

yield from $this->forkNewContentStreamAndApplyEvents(
Expand Down Expand Up @@ -671,12 +684,11 @@ private function handleDiscardWorkspace(
return;
}

$workspaceContentStreamVersion = $this->requireOpenContentStreamAndVersion($workspace, $commandHandlingDependencies);
$this->requireContentStreamToNotBeClosed($workspace->currentContentStreamId, $commandHandlingDependencies);
$baseWorkspaceContentStreamVersion = $this->requireOpenContentStreamAndVersion($baseWorkspace, $commandHandlingDependencies);

yield from $this->discardWorkspace(
$workspace,
$workspaceContentStreamVersion,
$baseWorkspace,
$baseWorkspaceContentStreamVersion,
$command->newContentStreamId
Expand All @@ -688,7 +700,6 @@ private function handleDiscardWorkspace(
*/
private function discardWorkspace(
Workspace $workspace,
Version $workspaceContentStreamVersion,
Workspace $baseWorkspace,
Version $baseWorkspaceContentStreamVersion,
ContentStreamId $newContentStream
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php

/*
* This file is part of the Neos.ContentRepository.Core package.
*
* (c) Contributors of the Neos Project - www.neos.io
*
* This package is Open Source Software. For the full copyright and license
* information, please view the LICENSE file which was distributed with this
* source code.
*/

declare(strict_types=1);

namespace Neos\ContentRepository\Core\Feature\WorkspaceRebase\Exception;

use Neos\ContentRepository\Core\Feature\WorkspaceRebase\ConflictingEvents;

/**
* Thrown if the partial publish/discard cannot work because the events cannot be reordered as filtered.
*
* This can happen for cases like attempting to publish a removal first and wanting as remaining change
* a node move out of the removed descendants or publishing a node variant creation before the node is created.
*
* We cannot reliably detect these cases in advance but in case the workspace is up-to-date its most likely such
* an ordering conflict.
*
* To solve the problem the partial operation should be retried with a different filter _or_ a full publish/discard is required.
*
* If the workspace is outdated we cannot know for sure but suspect first that the conflict arose due to changes
* in the base workspace, thus we throw {@see WorkspaceRebaseFailed} instead.
* A forced rebase then might not solve the problem if It's because the order of events cannot be changed.
* But attempting a second partial publish/discard (with up-to-date workspace) this exception will be thrown and can be reacted upon.
*
* @see WorkspaceRebaseFailed which is thrown instead if the workspace is also outdated
* @api this exception contains information which events cannot be reordered
*/
final class PartialWorkspaceRebaseFailed extends \RuntimeException
{
private function __construct(
public readonly ConflictingEvents $conflictingEvents,
string $message,
int $code,
?\Throwable $previous,
) {
parent::__construct($message, $code, $previous);
}

public static function duringPartialPublish(ConflictingEvents $conflictingEvents): self
{
return new self(
$conflictingEvents,
sprintf('Publication failed, events cannot be reordered as filtered: %s', self::renderMessage($conflictingEvents)),
1729974980,
$conflictingEvents->first()?->getException()
);
}

public static function duringPartialDiscard(ConflictingEvents $conflictingEvents): self
{
return new self(
$conflictingEvents,
sprintf('Discard failed, events cannot be reordered as filtered: %s', self::renderMessage($conflictingEvents)),
1729974982,
$conflictingEvents->first()?->getException()
);
}

private static function renderMessage(ConflictingEvents $conflictingEvents): string
{
$firstConflict = $conflictingEvents->first();
return sprintf('"%s" and %d further ordering conflicts', $firstConflict?->getException()->getMessage(), count($conflictingEvents) - 1);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
/**
* @api this exception contains information about what exactly went wrong during rebase
*/
final class WorkspaceRebaseFailed extends \Exception
final class WorkspaceRebaseFailed extends \RuntimeException
{
private function __construct(
public readonly ConflictingEvents $conflictingEvents,
Expand Down

0 comments on commit 6e9b3e7

Please sign in to comment.