From 3a2fc46f2de9eb4195f4629b9564dc5e06a9383c Mon Sep 17 00:00:00 2001 From: Bastian Waidelich Date: Thu, 11 Apr 2024 17:56:23 +0200 Subject: [PATCH 01/21] WIP: FEATURE: Rework CR CatchUp mechanism --- .../Features/Bootstrap/FeatureContext.php | 1 - .../HierarchyIntegrityIsProvided.feature | 2 - ...odesHaveAtMostOneParentPerSubgraph.feature | 2 - .../ReferenceIntegrityIsProvided.feature | 3 - .../SiblingsAreDistinctlySorted.feature | 3 - .../SubtreeTagsAreInherited.feature | 3 - .../TetheredNodesAreNamed.feature | 3 - .../DoctrineDbalContentGraphProjection.php | 671 ++++++++---------- .../Domain/Projection/Feature/NodeMove.php | 78 +- .../Domain/Projection/Feature/NodeRemoval.php | 20 +- .../Projection/Feature/NodeVariation.php | 526 +++++++------- .../Domain/Projection/HierarchyRelation.php | 26 +- .../src/Domain/Projection/NodeRecord.php | 50 +- .../Feature/ContentStreamForking.php | 59 +- .../Domain/Projection/Feature/CopyOnWrite.php | 5 - .../Projection/Feature/NodeCreation.php | 105 ++- .../Projection/Feature/NodeModification.php | 39 +- .../Projection/Feature/NodeReferencing.php | 71 +- .../Domain/Projection/Feature/NodeRemoval.php | 121 ++-- .../Projection/Feature/NodeRenaming.php | 35 +- .../Projection/Feature/NodeTypeChange.php | 35 +- .../Projection/Feature/NodeVariation.php | 252 ++++--- .../Projection/Feature/SubtreeTagging.php | 59 +- .../Projection/HypergraphProjection.php | 52 +- ...erformanceMeasurementCommandController.php | 11 +- .../RaceTrackerCatchUpHook.php | 3 +- .../Behavior/Bootstrap/FeatureContext.php | 1 - ...AggregateWithNode_ConstraintChecks.feature | 2 - ...ggregateWithNode_WithoutDimensions.feature | 6 - ...TetheredChildren_WithoutDimensions.feature | 2 - ...AndTetheredChildren_WithDimensions.feature | 2 - ...deAggregateWithNode_WithDimensions.feature | 6 - ...AggregateWithNode_ConstraintChecks.feature | 3 - ...de_ConstraintChecks_WithDimensions.feature | 3 - ...ggregateWithNode_WithoutDimensions.feature | 13 - ...deAggregateWithNode_WithDimensions.feature | 2 - ...ComplexDefaultAndInitialProperties.feature | 4 - ...eWithNode_NodeTypeConstraintChecks.feature | 8 - ...CreateNodeVariant_ConstraintChecks.feature | 2 - ...02-CreateNodeSpecializationVariant.feature | 7 - ...03-CreateNodeGeneralizationVariant.feature | 15 - .../04-CreateNodePeerVariant.feature | 16 - ...SetNodeProperties_ConstraintChecks.feature | 2 - .../02-SetNodeProperties.feature | 6 - ...3-SetNodeProperties_PropertyScopes.feature | 5 - ...SetNodeReferences_ConstraintChecks.feature | 3 - ...etNodeReferences_WithoutDimensions.feature | 16 - ...3-SetNodeReferences_WithDimensions.feature | 3 - ...4-SetNodeReferences_PropertyScopes.feature | 5 - ...odeVariation_After_NodeReferencing.feature | 14 - ...ableNodeAggregate_ConstraintChecks.feature | 3 - ...bleNodeAggregate_WithoutDimensions.feature | 5 - ...isableNodeAggregate_WithDimensions.feature | 7 - ...ableNodeAggregate_ConstraintChecks.feature | 2 - ...bleNodeAggregate_WithoutDimensions.feature | 14 - ...EnableNodeAggregate_WithDimensions.feature | 11 - ...DisabledAncestor_WithoutDimensions.feature | 4 - ...ithDisabledAncestor_WithDimensions.feature | 5 - ...09-CreateNodeVariantOfDisabledNode.feature | 20 - ...moveNodeAggregate_ConstraintChecks.feature | 2 - ...oveNodeAggregate_WithoutDimensions.feature | 8 - ...RemoveNodeAggregate_WithDimensions.feature | 10 - .../04-VariantRecreation.feature | 9 - .../05-CreateNodeAfterDeletion.feature | 3 - ...SpecializationVariantAfterDeletion.feature | 4 - .../08-NodeMove/MoveNodeAggregate.feature | 7 - ...eringDisableStateWithoutDimensions.feature | 17 - ...MoveNodeAggregateWithoutDimensions.feature | 11 - ...NodeAggregate_NewParent_Dimensions.feature | 18 - ...deAggregate_NoNewParent_Dimensions.feature | 26 - ...loseContentStream_ConstraintChecks.feature | 1 - ...ForkContentStream_ConstraintChecks.feature | 1 - ...WithDisabledNodesWithoutDimensions.feature | 5 - ...ForkContentStreamWithoutDimensions.feature | 4 - .../NodeReferencesOnForkContentStream.feature | 5 - .../AddDimensionShineThrough.feature | 5 - .../AddNewProperty_NoDimensions.feature | 4 - .../ChangePropertyValue_Dimensions.feature | 6 - .../ChangePropertyValue_NoDimensions.feature | 3 - .../Filter_NodeName_NoDimensions.feature | 5 - ...lter_PropertyNotEmpty_NoDimensions.feature | 6 - .../Filter_PropertyValue_NoDimensions.feature | 6 - .../Migration/MoveDimensionSpacePoint.feature | 4 - .../NodeTypeAdjustment_Dimensions.feature | 3 - .../NodeTypeAdjustment_NoDimensions.feature | 3 - .../Migration/RemoveNodes_Dimensions.feature | 4 - .../RemoveProperty_NoDimensions.feature | 3 - .../RenameNodeAggregate_Dimensions.feature | 4 - .../RenameProperty_NoDimensions.feature | 3 - .../StripTagsOnProperty_NoDimensions.feature | 3 - .../NodeCopying/CopyNode_NoDimensions.feature | 4 - .../NodePropertyConversion.feature | 6 - .../RemoveNodeAggregateAfterDisabling.feature | 6 - .../RemoveNodeAggregateWithDimensions.feature | 8 - .../NodeRemoval/RemoveNodesFromAggregate.wip | 14 - ...NodeAggregateName_ConstraintChecks.feature | 2 - .../ChangeNodeAggregateName.feature | 5 - ...eNodeAggregateType_BasicErrorCases.feature | 8 - ...geNodeAggregateType_DeleteStrategy.feature | 15 - ...odeAggregateType_HappyPathStrategy.feature | 10 - .../NodeTraversal/AncestorNodes.feature | 4 - .../Features/NodeTraversal/ChildNodes.feature | 3 - .../NodeTraversal/ClosestNode.feature | 4 - .../Features/NodeTraversal/CountNodes.feature | 3 - .../NodeTraversal/DescendantNodes.feature | 3 - .../NodeTraversal/FindNodeById.feature | 3 - .../NodeTraversal/FindNodeByPath.feature | 3 - .../FindNodeByPathAsNodeName.feature | 3 - .../NodeTraversal/FindParentNode.feature | 3 - .../NodeTraversal/FindRootNodeByType.feature | 3 - .../NodeTraversal/FindSubtree.feature | 3 - .../Features/NodeTraversal/References.feature | 3 - .../NodeTraversal/RetrieveNodePath.feature | 3 - .../NodeTraversal/SiblingNodes.feature | 3 - .../Features/NodeTraversal/Timestamps.feature | 16 - ...AreConnectedToARootNodePerSubgraph.feature | 3 - .../AllNodesCoverTheirOrigin.feature | 3 - .../IntactContentGraph.feature | 2 - ...ateIdentifiersAreUniquePerSubgraph.feature | 3 - ...istentlyClassifiedPerContentStream.feature | 3 - ...eConsistentlyTypedPerContentStream.feature | 3 - .../ReferenceIntegrityIsProvided.feature | 4 - ...AggregateDimensions_WithDimensions.feature | 9 - .../DimensionMismatch.feature | 3 - .../DisallowedChildNode.feature | 6 - ...sallowedChildNodesAndTetheredNodes.feature | 2 - .../StructureAdjustment/Properties.feature | 5 - .../StructureAdjustment/TetheredNodes.feature | 2 - .../TetheredNodesReordering.feature | 3 - .../UnknownNodeType.feature | 2 - .../TagSubtree_WithDimensions.feature | 12 - .../TagSubtree_WithoutDimensions.feature | 8 - .../01-ConstraintChecks.feature | 6 - .../02-BasicFeatures.feature | 9 - .../02-RebasingWithAutoCreatedNodes.feature | 6 - .../03-RebasingWithConflictingChanges.feature | 13 - .../02-PublishWorkspace.feature | 17 - .../01-ConstraintChecks.feature | 5 - .../02-BasicFeatures.feature | 4 - .../03-MoreBasicFeatures.feature | 7 - .../04-AllFeaturePublication.feature | 28 +- ...PublishMovedNodesWithoutDimensions.feature | 9 - .../02-DiscardWorkspace.feature | 16 - ...NodeOperationsOnMultipleWorkspaces.feature | 6 - .../Workspaces/PruneContentStreams.feature | 15 - .../RemoveNodeAggregateWithDimensions.wip | 8 - .../Workspaces/RemoveNodesFromAggregate.wip | 14 - ...ingleNodeOperationsOnLiveWorkspace.feature | 4 - .../WorkspaceWritingDuringPublication.php | 17 +- .../setup-is-running-flag | 0 .../Classes/CommandHandler/CommandResult.php | 79 --- .../CommandHandler/PendingProjections.php | 133 ---- .../Classes/ContentRepository.php | 93 ++- .../Classes/EventStore/EventPersister.php | 25 +- .../Feature/WorkspaceCommandHandler.php | 59 +- .../Infrastructure/DbalCheckpointStorage.php | 48 +- .../Projection/CatchUpHookInterface.php | 1 - .../ContentGraph/ContentGraphProjection.php | 14 +- .../ContentStream/ContentStreamProjection.php | 34 +- .../ProjectionCatchUpTriggerInterface.php | 4 +- .../Projection/ProjectionInterface.php | 13 +- .../Workspace/WorkspaceProjection.php | 29 +- .../Service/ContentRepositoryBootstrapper.php | 4 +- .../Classes/Service/ContentStreamPruner.php | 10 +- .../Service/WorkspaceMaintenanceService.php | 2 +- Neos.ContentRepository.Core/composer.json | 4 +- .../Features/Bootstrap/FeatureContext.php | 1 - .../Behavior/Features/Export/Export.feature | 2 - .../Behavior/Bootstrap/FeatureContext.php | 1 - .../src/NodeMigrationService.php | 2 +- ...nsionShineThroughTransformationFactory.php | 5 +- .../AddNewPropertyTransformationFactory.php | 9 +- .../ChangeNodeTypeTransformationFactory.php | 5 +- ...angePropertyValueTransformationFactory.php | 7 +- .../GlobalTransformationInterface.php | 4 +- ...mensionSpacePointTransformationFactory.php | 5 +- ...eAggregateBasedTransformationInterface.php | 3 +- .../NodeBasedTransformationInterface.php | 3 +- .../RemoveNodeTransformationFactory.php | 7 +- .../RemovePropertyTransformationFactory.php | 7 +- ...nameNodeAggregateTransformationFactory.php | 5 +- .../RenamePropertyTransformationFactory.php | 7 +- ...ripTagsOnPropertyTransformationFactory.php | 7 +- .../src/Transformation/Transformations.php | 6 +- .../src/StructureAdjustmentService.php | 2 +- .../Bootstrap/CRTestSuiteRuntimeVariables.php | 3 - .../Features/Bootstrap/CRTestSuiteTrait.php | 22 +- .../Features/ContentStreamClosing.php | 2 +- .../Features/ContentStreamForking.php | 2 +- .../Bootstrap/Features/NodeCopying.php | 2 +- .../Bootstrap/Features/NodeCreation.php | 11 +- .../Bootstrap/Features/NodeDisabling.php | 4 +- .../Bootstrap/Features/NodeModification.php | 2 +- .../Features/Bootstrap/Features/NodeMove.php | 2 +- .../Bootstrap/Features/NodeReferencing.php | 2 +- .../Bootstrap/Features/NodeRemoval.php | 2 +- .../Bootstrap/Features/NodeRenaming.php | 2 +- .../Bootstrap/Features/NodeTypeChange.php | 2 +- .../Bootstrap/Features/NodeVariation.php | 2 +- .../Bootstrap/Features/SubtreeTagging.php | 4 +- .../Bootstrap/Features/WorkspaceCreation.php | 23 +- .../Features/WorkspaceDiscarding.php | 4 +- .../Features/WorkspacePublishing.php | 4 +- ...ricCommandExecutionAndEventPublication.php | 4 +- .../Command/ContentCommandController.php | 23 +- ...cessProjectionCatchUpCommandController.php | 37 - .../CatchUpTriggerWithSynchronousOption.php | 75 -- .../DefaultCatchUpTrigger.php | 30 + ...DefaultProjectionCatchUpTriggerFactory.php | 23 + .../SubprocessProjectionCatchUpTrigger.php | 43 -- ...processProjectionCatchUpTriggerFactory.php | 22 - .../Classes/Service/EventMigrationService.php | 4 - .../Configuration/Settings.yaml | 2 +- .../Projection/AssetUsageProjection.php | 28 +- .../Command/WorkspaceCommandController.php | 6 +- .../Management/WorkspacesController.php | 16 +- .../Controller/Service/NodesController.php | 24 +- .../Domain/Service/SiteServiceInternals.php | 4 +- .../Classes/Domain/Workspace/Workspace.php | 16 +- .../Projection/DocumentUriPathProjection.php | 33 +- ...phProjectorCatchUpHookForCacheFlushing.php | 4 +- .../ChangeProjection.php | 185 ++--- .../Service/EditorContentStreamZookeeper.php | 2 +- .../Features/Bootstrap/FeatureContext.php | 1 - .../Features/Bootstrap/RoutingTrait.php | 12 - .../Features/FrontendRouting/Basic.feature | 7 - .../FrontendRouting/Dimensions.feature | 24 - .../FrontendRouting/DisableNodes.feature | 27 - .../Lowlevel_ProjectionTests.feature | 17 - .../FrontendRouting/MultiSiteLinking.feature | 2 - .../FrontendRouting/RouteCache.feature | 9 - .../FrontendRouting/Shortcuts.feature | 23 - .../TetheredSiteChildDocuments.feature | 4 - .../FrontendRouting/UnknownNodeTypes.feature | 2 - .../Features/Fusion/ContentCase.feature | 1 - .../Features/Fusion/ContentCollection.feature | 2 - .../Features/Fusion/ConvertUris.feature | 1 - .../Features/Fusion/FlowQuery.feature | 1 - .../Behavior/Features/Fusion/Menu.feature | 1 - .../Behavior/Bootstrap/FeatureContext.php | 2 - .../Behavior/Features/HandleExceeded.feature | 2 - composer.json | 2 + 242 files changed, 1443 insertions(+), 3053 deletions(-) create mode 100644 Neos.ContentRepository.BehavioralTests/Tests/Functional/Feature/WorkspacePublication/setup-is-running-flag delete mode 100644 Neos.ContentRepository.Core/Classes/CommandHandler/CommandResult.php delete mode 100644 Neos.ContentRepository.Core/Classes/CommandHandler/PendingProjections.php delete mode 100644 Neos.ContentRepositoryRegistry/Classes/Command/SubprocessProjectionCatchUpCommandController.php delete mode 100644 Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/CatchUpTriggerWithSynchronousOption.php create mode 100644 Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/DefaultCatchUpTrigger.php create mode 100644 Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/DefaultProjectionCatchUpTriggerFactory.php delete mode 100644 Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/SubprocessProjectionCatchUpTrigger.php delete mode 100644 Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/SubprocessProjectionCatchUpTriggerFactory.php diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Bootstrap/FeatureContext.php b/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Bootstrap/FeatureContext.php index 27d68c397cc..3df89de8c1f 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Bootstrap/FeatureContext.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Bootstrap/FeatureContext.php @@ -44,7 +44,6 @@ public function __construct() self::bootstrapFlow(); $this->contentRepositoryRegistry = $this->getObject(ContentRepositoryRegistry::class); - $this->setupCRTestSuiteTrait(); $this->setupDbalGraphAdapterIntegrityViolationTrait(); } diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Projection/ProjectionIntegrityViolationDetection/HierarchyIntegrityIsProvided.feature b/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Projection/ProjectionIntegrityViolationDetection/HierarchyIntegrityIsProvided.feature index bb7eeccc08b..d3de2f419e4 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Projection/ProjectionIntegrityViolationDetection/HierarchyIntegrityIsProvided.feature +++ b/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Projection/ProjectionIntegrityViolationDetection/HierarchyIntegrityIsProvided.feature @@ -19,7 +19,6 @@ Feature: Run integrity violation detection regarding hierarchy relations and nod | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | @@ -35,7 +34,6 @@ Feature: Run integrity violation detection regarding hierarchy relations and nod | parentNodeAggregateId | "lady-eleonode-rootford" | | nodeName | "child-document" | | nodeAggregateClassification | "regular" | - And the graph projection is fully up to date Scenario: Detach a hierarchy relation from its parent When I add the following hierarchy relation: diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Projection/ProjectionIntegrityViolationDetection/NodesHaveAtMostOneParentPerSubgraph.feature b/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Projection/ProjectionIntegrityViolationDetection/NodesHaveAtMostOneParentPerSubgraph.feature index 0cb73f49e4b..ccc0403a404 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Projection/ProjectionIntegrityViolationDetection/NodesHaveAtMostOneParentPerSubgraph.feature +++ b/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Projection/ProjectionIntegrityViolationDetection/NodesHaveAtMostOneParentPerSubgraph.feature @@ -19,7 +19,6 @@ Feature: Run integrity violation detection regarding parent relations | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"de"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | @@ -55,7 +54,6 @@ Feature: Run integrity violation detection regarding parent relations | parentNodeAggregateId | "sir-david-nodenborough" | | nodeName | "child-document" | | nodeAggregateClassification | "regular" | - And the graph projection is fully up to date Scenario: Set a second parent for Nody McNodeface And I add the following hierarchy relation: diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Projection/ProjectionIntegrityViolationDetection/ReferenceIntegrityIsProvided.feature b/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Projection/ProjectionIntegrityViolationDetection/ReferenceIntegrityIsProvided.feature index 3267be5d085..45eaddce388 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Projection/ProjectionIntegrityViolationDetection/ReferenceIntegrityIsProvided.feature +++ b/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Projection/ProjectionIntegrityViolationDetection/ReferenceIntegrityIsProvided.feature @@ -22,7 +22,6 @@ Feature: Run integrity violation detection regarding reference relations | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"de"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | @@ -46,7 +45,6 @@ Feature: Run integrity violation detection regarding reference relations | coveredDimensionSpacePoints | [{"language":"de"},{"language":"gsw"},{"language":"fr"}] | | parentNodeAggregateId | "lady-eleonode-rootford" | | nodeAggregateClassification | "regular" | - And the graph projection is fully up to date Scenario: Detach a reference relation from its source When the command SetNodeReferences is executed with payload: @@ -55,7 +53,6 @@ Feature: Run integrity violation detection regarding reference relations | sourceNodeAggregateId | "source-nodandaise" | | referenceName | "referenceProperty" | | references | [{"target": "anthony-destinode"}] | - And the graph projection is fully up to date And I detach the following reference relation from its source: | Key | Value | | contentStreamId | "cs-identifier" | diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Projection/ProjectionIntegrityViolationDetection/SiblingsAreDistinctlySorted.feature b/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Projection/ProjectionIntegrityViolationDetection/SiblingsAreDistinctlySorted.feature index 75f7032d08c..c684a6fa527 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Projection/ProjectionIntegrityViolationDetection/SiblingsAreDistinctlySorted.feature +++ b/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Projection/ProjectionIntegrityViolationDetection/SiblingsAreDistinctlySorted.feature @@ -19,13 +19,11 @@ Feature: Run integrity violation detection regarding sibling sorting | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"de"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date Scenario: Create two siblings and set the sorting to the same value When the event NodeAggregateWithNodeWasCreated was published with payload: @@ -46,7 +44,6 @@ Feature: Run integrity violation detection regarding sibling sorting | coveredDimensionSpacePoints | [{"language":"de"},{"language":"gsw"},{"language":"fr"}] | | parentNodeAggregateId | "lady-eleonode-rootford" | | nodeAggregateClassification | "regular" | - And the graph projection is fully up to date And I set the following position: | Key | Value | | contentStreamId | "cs-identifier" | diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Projection/ProjectionIntegrityViolationDetection/SubtreeTagsAreInherited.feature b/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Projection/ProjectionIntegrityViolationDetection/SubtreeTagsAreInherited.feature index 1c424425d1f..d120cd07926 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Projection/ProjectionIntegrityViolationDetection/SubtreeTagsAreInherited.feature +++ b/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Projection/ProjectionIntegrityViolationDetection/SubtreeTagsAreInherited.feature @@ -19,13 +19,11 @@ Feature: Run integrity violation detection regarding subtree tag inheritance | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"de"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date Scenario: Create nodes, disable the topmost and remove some restriction edges manually When the event NodeAggregateWithNodeWasCreated was published with payload: @@ -64,7 +62,6 @@ Feature: Run integrity violation detection regarding subtree tag inheritance | nodeAggregateId | "sir-david-nodenborough" | | affectedDimensionSpacePoints | [{"language":"de"},{"language":"gsw"},{"language":"fr"}] | | tag | "disabled" | - And the graph projection is fully up to date And I remove the following subtree tag: | Key | Value | | contentStreamId | "cs-identifier" | diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Projection/ProjectionIntegrityViolationDetection/TetheredNodesAreNamed.feature b/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Projection/ProjectionIntegrityViolationDetection/TetheredNodesAreNamed.feature index 3068aaa7edf..792d59ba779 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Projection/ProjectionIntegrityViolationDetection/TetheredNodesAreNamed.feature +++ b/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Projection/ProjectionIntegrityViolationDetection/TetheredNodesAreNamed.feature @@ -19,7 +19,6 @@ Feature: Run projection integrity violation detection regarding naming of tether | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"de"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | @@ -35,7 +34,6 @@ Feature: Run projection integrity violation detection regarding naming of tether | parentNodeAggregateId | "lady-eleonode-rootford" | | nodeName | "document" | | nodeAggregateClassification | "regular" | - And the graph projection is fully up to date Scenario: Create node variants of different type When the event NodeAggregateWithNodeWasCreated was published with payload: @@ -48,7 +46,6 @@ Feature: Run projection integrity violation detection regarding naming of tether | parentNodeAggregateId | "sir-david-nodenborough" | | nodeName | "to-be-hacked-to-null" | | nodeAggregateClassification | "tethered" | - And the graph projection is fully up to date And I change the following hierarchy relation's name: | Key | Value | | contentStreamId | "cs-identifier" | diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php index a3a92150aa8..2f9b00fe47d 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php @@ -62,6 +62,9 @@ use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; use Neos\EventStore\Model\Event\SequenceNumber; use Neos\EventStore\Model\EventEnvelope; +use React\Promise\PromiseInterface; + +use function React\Promise\resolve; /** * @implements ProjectionInterface @@ -158,7 +161,7 @@ public function status(): ProjectionStatus return ProjectionStatus::ok(); } - public function reset(): void + public function reset(): PromiseInterface { $this->truncateDatabaseTables(); @@ -169,6 +172,7 @@ public function reset(): void foreach ($contentGraph->getSubgraphs() as $subgraph) { $subgraph->inMemoryCache->enable(); } + return resolve(null); } private function truncateDatabaseTables(): void @@ -180,31 +184,7 @@ private function truncateDatabaseTables(): void $connection->executeQuery('TRUNCATE table ' . $this->tableNamePrefix . '_dimensionspacepoints'); } - public function canHandle(EventInterface $event): bool - { - return in_array($event::class, [ - RootNodeAggregateWithNodeWasCreated::class, - RootNodeAggregateDimensionsWereUpdated::class, - NodeAggregateWithNodeWasCreated::class, - NodeAggregateNameWasChanged::class, - ContentStreamWasForked::class, - ContentStreamWasRemoved::class, - NodePropertiesWereSet::class, - NodeReferencesWereSet::class, - NodeAggregateTypeWasChanged::class, - DimensionSpacePointWasMoved::class, - DimensionShineThroughWasAdded::class, - NodeAggregateWasRemoved::class, - NodeAggregateWasMoved::class, - NodeSpecializationVariantWasCreated::class, - NodeGeneralizationVariantWasCreated::class, - NodePeerVariantWasCreated::class, - SubtreeWasTagged::class, - SubtreeWasUntagged::class, - ]); - } - - public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void + public function apply(EventInterface $event, EventEnvelope $eventEnvelope): PromiseInterface { match ($event::class) { RootNodeAggregateWithNodeWasCreated::class => $this->whenRootNodeAggregateWithNodeWasCreated($event, $eventEnvelope), @@ -225,8 +205,9 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void NodePeerVariantWasCreated::class => $this->whenNodePeerVariantWasCreated($event, $eventEnvelope), SubtreeWasTagged::class => $this->whenSubtreeWasTagged($event), SubtreeWasUntagged::class => $this->whenSubtreeWasUntagged($event), - default => throw new \InvalidArgumentException(sprintf('Unsupported event %s', get_debug_type($event))), + default => null, }; + return resolve(null); } public function getCheckpointStorage(): DbalCheckpointStorage @@ -261,34 +242,32 @@ public function markStale(): void */ private function whenRootNodeAggregateWithNodeWasCreated(RootNodeAggregateWithNodeWasCreated $event, EventEnvelope $eventEnvelope): void { - $this->transactional(function () use ($event, $eventEnvelope) { - $originDimensionSpacePoint = OriginDimensionSpacePoint::createWithoutDimensions(); - $node = NodeRecord::createNewInDatabase( - $this->getDatabaseConnection(), - $this->tableNamePrefix, - $event->nodeAggregateId, - $originDimensionSpacePoint->coordinates, - $originDimensionSpacePoint->hash, - SerializedPropertyValues::createEmpty(), - $event->nodeTypeName, - $event->nodeAggregateClassification, + $originDimensionSpacePoint = OriginDimensionSpacePoint::createWithoutDimensions(); + $node = NodeRecord::createNewInDatabase( + $this->getDatabaseConnection(), + $this->tableNamePrefix, + $event->nodeAggregateId, + $originDimensionSpacePoint->coordinates, + $originDimensionSpacePoint->hash, + SerializedPropertyValues::createEmpty(), + $event->nodeTypeName, + $event->nodeAggregateClassification, + null, + Timestamps::create( + $eventEnvelope->recordedAt, + self::initiatingDateTime($eventEnvelope), null, - Timestamps::create( - $eventEnvelope->recordedAt, - self::initiatingDateTime($eventEnvelope), - null, - null, - ), - ); + null, + ), + ); - $this->connectHierarchy( - $event->contentStreamId, - NodeRelationAnchorPoint::forRootEdge(), - $node->relationAnchorPoint, - $event->coveredDimensionSpacePoints, - null - ); - }); + $this->connectHierarchy( + $event->contentStreamId, + NodeRelationAnchorPoint::forRootEdge(), + $node->relationAnchorPoint, + $event->coveredDimensionSpacePoints, + null + ); } /** @@ -308,28 +287,26 @@ private function whenRootNodeAggregateDimensionsWereUpdated(RootNodeAggregateDim return; } - $this->transactional(function () use ($rootNodeAnchorPoint, $event) { - // delete all hierarchy edges of the root node - $this->getDatabaseConnection()->executeUpdate(' - DELETE FROM ' . $this->tableNamePrefix . '_hierarchyrelation - WHERE - parentnodeanchor = :parentNodeAnchor - AND childnodeanchor = :childNodeAnchor - AND contentstreamid = :contentStreamId - ', [ - 'parentNodeAnchor' => NodeRelationAnchorPoint::forRootEdge()->value, - 'childNodeAnchor' => $rootNodeAnchorPoint->value, - 'contentStreamId' => $event->contentStreamId->value, - ]); - // recreate hierarchy edges for the root node - $this->connectHierarchy( - $event->contentStreamId, - NodeRelationAnchorPoint::forRootEdge(), - $rootNodeAnchorPoint, - $event->coveredDimensionSpacePoints, - null - ); - }); + // delete all hierarchy edges of the root node + $this->getDatabaseConnection()->executeUpdate(' + DELETE FROM ' . $this->tableNamePrefix . '_hierarchyrelation + WHERE + parentnodeanchor = :parentNodeAnchor + AND childnodeanchor = :childNodeAnchor + AND contentstreamid = :contentStreamId + ', [ + 'parentNodeAnchor' => NodeRelationAnchorPoint::forRootEdge()->value, + 'childNodeAnchor' => $rootNodeAnchorPoint->value, + 'contentStreamId' => $event->contentStreamId->value, + ]); + // recreate hierarchy edges for the root node + $this->connectHierarchy( + $event->contentStreamId, + NodeRelationAnchorPoint::forRootEdge(), + $rootNodeAnchorPoint, + $event->coveredDimensionSpacePoints, + null + ); } /** @@ -337,20 +314,18 @@ private function whenRootNodeAggregateDimensionsWereUpdated(RootNodeAggregateDim */ private function whenNodeAggregateWithNodeWasCreated(NodeAggregateWithNodeWasCreated $event, EventEnvelope $eventEnvelope): void { - $this->transactional(function () use ($event, $eventEnvelope) { - $this->createNodeWithHierarchy( - $event->contentStreamId, - $event->nodeAggregateId, - $event->nodeTypeName, - $event->parentNodeAggregateId, - $event->originDimensionSpacePoint, - $event->succeedingSiblingsForCoverage, - $event->initialPropertyValues, - $event->nodeAggregateClassification, - $event->nodeName, - $eventEnvelope, - ); - }); + $this->createNodeWithHierarchy( + $event->contentStreamId, + $event->nodeAggregateId, + $event->nodeTypeName, + $event->parentNodeAggregateId, + $event->originDimensionSpacePoint, + $event->succeedingSiblingsForCoverage, + $event->initialPropertyValues, + $event->nodeAggregateClassification, + $event->nodeName, + $eventEnvelope, + ); } /** @@ -358,30 +333,28 @@ private function whenNodeAggregateWithNodeWasCreated(NodeAggregateWithNodeWasCre */ private function whenNodeAggregateNameWasChanged(NodeAggregateNameWasChanged $event, EventEnvelope $eventEnvelope): void { - $this->transactional(function () use ($event, $eventEnvelope) { - $this->getDatabaseConnection()->executeStatement(' - UPDATE ' . $this->tableNamePrefix . '_hierarchyrelation h - INNER JOIN ' . $this->tableNamePrefix . '_node n on - h.childnodeanchor = n.relationanchorpoint - SET - h.name = :newName, - n.lastmodified = :lastModified, - n.originallastmodified = :originalLastModified - - WHERE - n.nodeaggregateid = :nodeAggregateId - and h.contentstreamid = :contentStreamId - ', [ - 'newName' => $event->newNodeName->value, - 'nodeAggregateId' => $event->nodeAggregateId->value, - 'contentStreamId' => $event->contentStreamId->value, - 'lastModified' => $eventEnvelope->recordedAt, - 'originalLastModified' => self::initiatingDateTime($eventEnvelope), - ], [ - 'lastModified' => Types::DATETIME_IMMUTABLE, - 'originalLastModified' => Types::DATETIME_IMMUTABLE, - ]); - }); + $this->getDatabaseConnection()->executeStatement(' + UPDATE ' . $this->tableNamePrefix . '_hierarchyrelation h + INNER JOIN ' . $this->tableNamePrefix . '_node n on + h.childnodeanchor = n.relationanchorpoint + SET + h.name = :newName, + n.lastmodified = :lastModified, + n.originallastmodified = :originalLastModified + + WHERE + n.nodeaggregateid = :nodeAggregateId + and h.contentstreamid = :contentStreamId + ', [ + 'newName' => $event->newNodeName->value, + 'nodeAggregateId' => $event->nodeAggregateId->value, + 'contentStreamId' => $event->contentStreamId->value, + 'lastModified' => $eventEnvelope->recordedAt, + 'originalLastModified' => self::initiatingDateTime($eventEnvelope), + ], [ + 'lastModified' => Types::DATETIME_IMMUTABLE, + 'originalLastModified' => Types::DATETIME_IMMUTABLE, + ]); } /** @@ -591,76 +564,70 @@ private function getRelationPositionAfterRecalculation( */ private function whenContentStreamWasForked(ContentStreamWasForked $event): void { - $this->transactional(function () use ($event) { - - // - // 1) Copy HIERARCHY RELATIONS (this is the MAIN OPERATION here) - // - $this->getDatabaseConnection()->executeUpdate(' - INSERT INTO ' . $this->tableNamePrefix . '_hierarchyrelation ( - parentnodeanchor, - childnodeanchor, - `name`, - position, - dimensionspacepointhash, - subtreetags, - contentstreamid - ) - SELECT - h.parentnodeanchor, - h.childnodeanchor, - h.name, - h.position, - h.dimensionspacepointhash, - h.subtreetags, - "' . $event->newContentStreamId->value . '" AS contentstreamid - FROM - ' . $this->tableNamePrefix . '_hierarchyrelation h - WHERE h.contentstreamid = :sourceContentStreamId - ', [ - 'sourceContentStreamId' => $event->sourceContentStreamId->value - ]); + // + // 1) Copy HIERARCHY RELATIONS (this is the MAIN OPERATION here) + // + $this->getDatabaseConnection()->executeUpdate(' + INSERT INTO ' . $this->tableNamePrefix . '_hierarchyrelation ( + parentnodeanchor, + childnodeanchor, + `name`, + position, + dimensionspacepointhash, + subtreetags, + contentstreamid + ) + SELECT + h.parentnodeanchor, + h.childnodeanchor, + h.name, + h.position, + h.dimensionspacepointhash, + h.subtreetags, + "' . $event->newContentStreamId->value . '" AS contentstreamid + FROM + ' . $this->tableNamePrefix . '_hierarchyrelation h + WHERE h.contentstreamid = :sourceContentStreamId + ', [ + 'sourceContentStreamId' => $event->sourceContentStreamId->value + ]); - // NOTE: as reference edges are attached to Relation Anchor Points (and they are lazily copy-on-written), - // we do not need to copy reference edges here (but we need to do it during copy on write). - }); + // NOTE: as reference edges are attached to Relation Anchor Points (and they are lazily copy-on-written), + // we do not need to copy reference edges here (but we need to do it during copy on write). } private function whenContentStreamWasRemoved(ContentStreamWasRemoved $event): void { - $this->transactional(function () use ($event) { - - // Drop hierarchy relations - $this->getDatabaseConnection()->executeUpdate(' - DELETE FROM ' . $this->tableNamePrefix . '_hierarchyrelation - WHERE - contentstreamid = :contentStreamId - ', [ - 'contentStreamId' => $event->contentStreamId->value - ]); + // Drop hierarchy relations + $this->getDatabaseConnection()->executeUpdate(' + DELETE FROM ' . $this->tableNamePrefix . '_hierarchyrelation + WHERE + contentstreamid = :contentStreamId + ', [ + 'contentStreamId' => $event->contentStreamId->value + ]); - // Drop non-referenced nodes (which do not have a hierarchy relation anymore) - $this->getDatabaseConnection()->executeUpdate(' - DELETE FROM ' . $this->tableNamePrefix . '_node - WHERE NOT EXISTS - ( - SELECT 1 FROM ' . $this->tableNamePrefix . '_hierarchyrelation - WHERE ' . $this->tableNamePrefix . '_hierarchyrelation.childnodeanchor - = ' . $this->tableNamePrefix . '_node.relationanchorpoint - ) - '); - - // Drop non-referenced reference relations (i.e. because the referenced nodes are gone by now) - $this->getDatabaseConnection()->executeUpdate(' - DELETE FROM ' . $this->tableNamePrefix . '_referencerelation - WHERE NOT EXISTS - ( - SELECT 1 FROM ' . $this->tableNamePrefix . '_node - WHERE ' . $this->tableNamePrefix . '_node.relationanchorpoint - = ' . $this->tableNamePrefix . '_referencerelation.nodeanchorpoint - ) - '); - }); + // Drop non-referenced nodes (which do not have a hierarchy relation anymore) + $this->getDatabaseConnection()->executeUpdate(' + DELETE FROM ' . $this->tableNamePrefix . '_node + WHERE NOT EXISTS + ( + SELECT 1 FROM ' . $this->tableNamePrefix . '_hierarchyrelation + WHERE ' . $this->tableNamePrefix . '_hierarchyrelation.childnodeanchor + = ' . $this->tableNamePrefix . '_node.relationanchorpoint + ) + '); + + // Drop non-referenced reference relations (i.e. because the referenced nodes are gone by now) + $this->getDatabaseConnection()->executeUpdate(' + DELETE FROM ' . $this->tableNamePrefix . '_referencerelation + WHERE NOT EXISTS + ( + SELECT 1 FROM ' . $this->tableNamePrefix . '_node + WHERE ' . $this->tableNamePrefix . '_node.relationanchorpoint + = ' . $this->tableNamePrefix . '_referencerelation.nodeanchorpoint + ) + '); } /** @@ -668,102 +635,98 @@ private function whenContentStreamWasRemoved(ContentStreamWasRemoved $event): vo */ private function whenNodePropertiesWereSet(NodePropertiesWereSet $event, EventEnvelope $eventEnvelope): void { - $this->transactional(function () use ($event, $eventEnvelope) { - $anchorPoint = $this->projectionContentGraph + $anchorPoint = $this->projectionContentGraph + ->getAnchorPointForNodeAndOriginDimensionSpacePointAndContentStream( + $event->getNodeAggregateId(), + $event->getOriginDimensionSpacePoint(), + $event->getContentStreamId() + ); + if (is_null($anchorPoint)) { + throw new \InvalidArgumentException( + 'Cannot update node with copy on write since no anchor point could be resolved for node ' + . $event->getNodeAggregateId()->value . ' in content stream ' + . $event->getContentStreamId()->value, + 1645303332 + ); + } + $this->updateNodeRecordWithCopyOnWrite( + $event->getContentStreamId(), + $anchorPoint, + function (NodeRecord $node) use ($event, $eventEnvelope) { + $node->properties = $node->properties + ->merge($event->propertyValues) + ->unsetProperties($event->propertiesToUnset); + $node->timestamps = $node->timestamps->with( + lastModified: $eventEnvelope->recordedAt, + originalLastModified: self::initiatingDateTime($eventEnvelope) + ); + } + ); + } + + /** + * @throws \Throwable + */ + private function whenNodeReferencesWereSet(NodeReferencesWereSet $event, EventEnvelope $eventEnvelope): void + { + foreach ($event->affectedSourceOriginDimensionSpacePoints as $originDimensionSpacePoint) { + $nodeAnchorPoint = $this->projectionContentGraph ->getAnchorPointForNodeAndOriginDimensionSpacePointAndContentStream( - $event->getNodeAggregateId(), - $event->getOriginDimensionSpacePoint(), - $event->getContentStreamId() + $event->sourceNodeAggregateId, + $originDimensionSpacePoint, + $event->contentStreamId ); - if (is_null($anchorPoint)) { + + if (is_null($nodeAnchorPoint)) { throw new \InvalidArgumentException( - 'Cannot update node with copy on write since no anchor point could be resolved for node ' + 'Could not apply event of type "' . get_class($event) + . '" since no anchor point could be resolved for node ' . $event->getNodeAggregateId()->value . ' in content stream ' . $event->getContentStreamId()->value, - 1645303332 + 1658580583 ); } + $this->updateNodeRecordWithCopyOnWrite( - $event->getContentStreamId(), - $anchorPoint, - function (NodeRecord $node) use ($event, $eventEnvelope) { - $node->properties = $node->properties - ->merge($event->propertyValues) - ->unsetProperties($event->propertiesToUnset); + $event->contentStreamId, + $nodeAnchorPoint, + function (NodeRecord $node) use ($eventEnvelope) { $node->timestamps = $node->timestamps->with( lastModified: $eventEnvelope->recordedAt, originalLastModified: self::initiatingDateTime($eventEnvelope) ); } ); - }); - } - /** - * @throws \Throwable - */ - private function whenNodeReferencesWereSet(NodeReferencesWereSet $event, EventEnvelope $eventEnvelope): void - { - $this->transactional(function () use ($event, $eventEnvelope) { - foreach ($event->affectedSourceOriginDimensionSpacePoints as $originDimensionSpacePoint) { - $nodeAnchorPoint = $this->projectionContentGraph - ->getAnchorPointForNodeAndOriginDimensionSpacePointAndContentStream( - $event->sourceNodeAggregateId, - $originDimensionSpacePoint, - $event->contentStreamId - ); - - if (is_null($nodeAnchorPoint)) { - throw new \InvalidArgumentException( - 'Could not apply event of type "' . get_class($event) - . '" since no anchor point could be resolved for node ' - . $event->getNodeAggregateId()->value . ' in content stream ' - . $event->getContentStreamId()->value, - 1658580583 - ); - } - - $this->updateNodeRecordWithCopyOnWrite( - $event->contentStreamId, - $nodeAnchorPoint, - function (NodeRecord $node) use ($eventEnvelope) { - $node->timestamps = $node->timestamps->with( - lastModified: $eventEnvelope->recordedAt, - originalLastModified: self::initiatingDateTime($eventEnvelope) - ); - } + $nodeAnchorPoint = $this->projectionContentGraph + ->getAnchorPointForNodeAndOriginDimensionSpacePointAndContentStream( + $event->sourceNodeAggregateId, + $originDimensionSpacePoint, + $event->contentStreamId ); - $nodeAnchorPoint = $this->projectionContentGraph - ->getAnchorPointForNodeAndOriginDimensionSpacePointAndContentStream( - $event->sourceNodeAggregateId, - $originDimensionSpacePoint, - $event->contentStreamId - ); + // remove old + $this->getDatabaseConnection()->delete($this->tableNamePrefix . '_referencerelation', [ + 'nodeanchorpoint' => $nodeAnchorPoint?->value, + 'name' => $event->referenceName->value + ]); - // remove old - $this->getDatabaseConnection()->delete($this->tableNamePrefix . '_referencerelation', [ + // set new + $position = 0; + /** @var SerializedNodeReference $reference */ + foreach ($event->references as $reference) { + $this->getDatabaseConnection()->insert($this->tableNamePrefix . '_referencerelation', [ + 'name' => $event->referenceName->value, + 'position' => $position, 'nodeanchorpoint' => $nodeAnchorPoint?->value, - 'name' => $event->referenceName->value + 'destinationnodeaggregateid' => $reference->targetNodeAggregateId->value, + 'properties' => $reference->properties + ? \json_encode($reference->properties, JSON_THROW_ON_ERROR & JSON_FORCE_OBJECT) + : null ]); - - // set new - $position = 0; - /** @var SerializedNodeReference $reference */ - foreach ($event->references as $reference) { - $this->getDatabaseConnection()->insert($this->tableNamePrefix . '_referencerelation', [ - 'name' => $event->referenceName->value, - 'position' => $position, - 'nodeanchorpoint' => $nodeAnchorPoint?->value, - 'destinationnodeaggregateid' => $reference->targetNodeAggregateId->value, - 'properties' => $reference->properties - ? \json_encode($reference->properties, JSON_THROW_ON_ERROR & JSON_FORCE_OBJECT) - : null - ]); - $position++; - } + $position++; } - }); + } } /** @@ -829,22 +792,20 @@ protected function copyNodeToDimensionSpacePoint( private function whenNodeAggregateTypeWasChanged(NodeAggregateTypeWasChanged $event, EventEnvelope $eventEnvelope): void { - $this->transactional(function () use ($event, $eventEnvelope) { - $anchorPoints = $this->projectionContentGraph->getAnchorPointsForNodeAggregateInContentStream($event->nodeAggregateId, $event->contentStreamId); - foreach ($anchorPoints as $anchorPoint) { - $this->updateNodeRecordWithCopyOnWrite( - $event->contentStreamId, - $anchorPoint, - function (NodeRecord $node) use ($event, $eventEnvelope) { - $node->nodeTypeName = $event->newNodeTypeName; - $node->timestamps = $node->timestamps->with( - lastModified: $eventEnvelope->recordedAt, - originalLastModified: self::initiatingDateTime($eventEnvelope) - ); - } - ); - } - }); + $anchorPoints = $this->projectionContentGraph->getAnchorPointsForNodeAggregateInContentStream($event->nodeAggregateId, $event->contentStreamId); + foreach ($anchorPoints as $anchorPoint) { + $this->updateNodeRecordWithCopyOnWrite( + $event->contentStreamId, + $anchorPoint, + function (NodeRecord $node) use ($event, $eventEnvelope) { + $node->nodeTypeName = $event->newNodeTypeName; + $node->timestamps = $node->timestamps->with( + lastModified: $eventEnvelope->recordedAt, + originalLastModified: self::initiatingDateTime($eventEnvelope) + ); + } + ); + } } private function updateNodeRecordWithCopyOnWrite( @@ -936,105 +897,93 @@ private function copyReferenceRelations( private function whenDimensionSpacePointWasMoved(DimensionSpacePointWasMoved $event): void { - $this->transactional(function () use ($event) { - $this->dimensionSpacePointsRepository->insertDimensionSpacePoint($event->target); - - // the ordering is important - we first update the OriginDimensionSpacePoints, as we need the - // hierarchy relations for this query. Then, we update the Hierarchy Relations. - - // 1) originDimensionSpacePoint on Node - $rel = $this->getDatabaseConnection()->executeQuery( - 'SELECT n.relationanchorpoint, n.origindimensionspacepointhash - FROM ' . $this->tableNamePrefix . '_node n - INNER JOIN ' . $this->tableNamePrefix . '_hierarchyrelation h - ON h.childnodeanchor = n.relationanchorpoint - - AND h.contentstreamid = :contentStreamId - AND h.dimensionspacepointhash = :dimensionSpacePointHash - -- find only nodes which have their ORIGIN at the source DimensionSpacePoint, - -- as we need to rewrite these origins (using copy on write) - AND n.origindimensionspacepointhash = :dimensionSpacePointHash - ', - [ - 'dimensionSpacePointHash' => $event->source->hash, - 'contentStreamId' => $event->contentStreamId->value - ] + $this->dimensionSpacePointsRepository->insertDimensionSpacePoint($event->target); + + // the ordering is important - we first update the OriginDimensionSpacePoints, as we need the + // hierarchy relations for this query. Then, we update the Hierarchy Relations. + + // 1) originDimensionSpacePoint on Node + $rel = $this->getDatabaseConnection()->executeQuery( + 'SELECT n.relationanchorpoint, n.origindimensionspacepointhash + FROM ' . $this->tableNamePrefix . '_node n + INNER JOIN ' . $this->tableNamePrefix . '_hierarchyrelation h + ON h.childnodeanchor = n.relationanchorpoint + + AND h.contentstreamid = :contentStreamId + AND h.dimensionspacepointhash = :dimensionSpacePointHash + -- find only nodes which have their ORIGIN at the source DimensionSpacePoint, + -- as we need to rewrite these origins (using copy on write) + AND n.origindimensionspacepointhash = :dimensionSpacePointHash + ', + [ + 'dimensionSpacePointHash' => $event->source->hash, + 'contentStreamId' => $event->contentStreamId->value + ] + ); + while ($res = $rel->fetchAssociative()) { + $relationAnchorPoint = NodeRelationAnchorPoint::fromInteger($res['relationanchorpoint']); + $this->updateNodeRecordWithCopyOnWrite( + $event->contentStreamId, + $relationAnchorPoint, + function (NodeRecord $nodeRecord) use ($event) { + $nodeRecord->originDimensionSpacePoint = $event->target->coordinates; + $nodeRecord->originDimensionSpacePointHash = $event->target->hash; + } ); - while ($res = $rel->fetchAssociative()) { - $relationAnchorPoint = NodeRelationAnchorPoint::fromInteger($res['relationanchorpoint']); - $this->updateNodeRecordWithCopyOnWrite( - $event->contentStreamId, - $relationAnchorPoint, - function (NodeRecord $nodeRecord) use ($event) { - $nodeRecord->originDimensionSpacePoint = $event->target->coordinates; - $nodeRecord->originDimensionSpacePointHash = $event->target->hash; - } - ); - } + } - // 2) hierarchy relations - $this->getDatabaseConnection()->executeStatement( - ' - UPDATE ' . $this->tableNamePrefix . '_hierarchyrelation h - SET - h.dimensionspacepointhash = :newDimensionSpacePointHash - WHERE - h.dimensionspacepointhash = :originalDimensionSpacePointHash - AND h.contentstreamid = :contentStreamId - ', - [ - 'originalDimensionSpacePointHash' => $event->source->hash, - 'newDimensionSpacePointHash' => $event->target->hash, - 'contentStreamId' => $event->contentStreamId->value - ] - ); - }); + // 2) hierarchy relations + $this->getDatabaseConnection()->executeStatement( + ' + UPDATE ' . $this->tableNamePrefix . '_hierarchyrelation h + SET + h.dimensionspacepointhash = :newDimensionSpacePointHash + WHERE + h.dimensionspacepointhash = :originalDimensionSpacePointHash + AND h.contentstreamid = :contentStreamId + ', + [ + 'originalDimensionSpacePointHash' => $event->source->hash, + 'newDimensionSpacePointHash' => $event->target->hash, + 'contentStreamId' => $event->contentStreamId->value + ] + ); } private function whenDimensionShineThroughWasAdded(DimensionShineThroughWasAdded $event): void { - $this->transactional(function () use ($event) { - $this->dimensionSpacePointsRepository->insertDimensionSpacePoint($event->target); - - // 1) hierarchy relations - $this->getDatabaseConnection()->executeStatement( - ' - INSERT INTO ' . $this->tableNamePrefix . '_hierarchyrelation ( - parentnodeanchor, - childnodeanchor, - `name`, - position, - subtreetags, - dimensionspacepointhash, - contentstreamid - ) - SELECT - h.parentnodeanchor, - h.childnodeanchor, - h.name, - h.position, - h.subtreetags, - :newDimensionSpacePointHash AS dimensionspacepointhash, - h.contentstreamid - FROM - ' . $this->tableNamePrefix . '_hierarchyrelation h - WHERE h.contentstreamid = :contentStreamId - AND h.dimensionspacepointhash = :sourceDimensionSpacePointHash', - [ - 'contentStreamId' => $event->contentStreamId->value, - 'sourceDimensionSpacePointHash' => $event->source->hash, - 'newDimensionSpacePointHash' => $event->target->hash, - ] - ); - }); - } - - /** - * @throws \Throwable - */ - private function transactional(\Closure $operations): void - { - $this->getDatabaseConnection()->transactional($operations); + $this->dimensionSpacePointsRepository->insertDimensionSpacePoint($event->target); + + // 1) hierarchy relations + $this->getDatabaseConnection()->executeStatement( + ' + INSERT INTO ' . $this->tableNamePrefix . '_hierarchyrelation ( + parentnodeanchor, + childnodeanchor, + `name`, + position, + subtreetags, + dimensionspacepointhash, + contentstreamid + ) + SELECT + h.parentnodeanchor, + h.childnodeanchor, + h.name, + h.position, + h.subtreetags, + :newDimensionSpacePointHash AS dimensionspacepointhash, + h.contentstreamid + FROM + ' . $this->tableNamePrefix . '_hierarchyrelation h + WHERE h.contentstreamid = :contentStreamId + AND h.dimensionspacepointhash = :sourceDimensionSpacePointHash', + [ + 'contentStreamId' => $event->contentStreamId->value, + 'sourceDimensionSpacePointHash' => $event->source->hash, + 'newDimensionSpacePointHash' => $event->target->hash, + ] + ); } private function getDatabaseConnection(): Connection diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/Feature/NodeMove.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/Feature/NodeMove.php index f779ad9ff64..7634e5d6071 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/Feature/NodeMove.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/Feature/NodeMove.php @@ -38,48 +38,46 @@ abstract protected function getTableNamePrefix(): string; */ private function whenNodeAggregateWasMoved(NodeAggregateWasMoved $event): void { - $this->transactional(function () use ($event) { - foreach ($event->nodeMoveMappings as $moveNodeMapping) { - // for each materialized node in the DB which we want to adjust, we have one MoveNodeMapping. - $nodeToBeMoved = $this->getProjectionContentGraph()->findNodeByIds( - $event->contentStreamId, - $event->nodeAggregateId, - $moveNodeMapping->movedNodeOrigin - ); - - if (is_null($nodeToBeMoved)) { - throw EventCouldNotBeAppliedToContentGraph::becauseTheSourceNodeIsMissing(get_class($event)); - } + foreach ($event->nodeMoveMappings as $moveNodeMapping) { + // for each materialized node in the DB which we want to adjust, we have one MoveNodeMapping. + $nodeToBeMoved = $this->getProjectionContentGraph()->findNodeByIds( + $event->contentStreamId, + $event->nodeAggregateId, + $moveNodeMapping->movedNodeOrigin + ); + + if (is_null($nodeToBeMoved)) { + throw EventCouldNotBeAppliedToContentGraph::becauseTheSourceNodeIsMissing(get_class($event)); + } - foreach ($moveNodeMapping->newLocations as $newLocation) { - assert($newLocation instanceof CoverageNodeMoveMapping); - - $affectedDimensionSpacePoints = new DimensionSpacePointSet([ - $newLocation->coveredDimensionSpacePoint - ]); - - // do the move (depending on how the move target is specified) - $newParentNodeAggregateId = match ($newLocation->destination::class) { - SucceedingSiblingNodeMoveDestination::class => $this->moveNodeBeforeSucceedingSibling( - $event->contentStreamId, - $nodeToBeMoved, - $newLocation->coveredDimensionSpacePoint, - $newLocation->destination - ), - ParentNodeMoveDestination::class => $newLocation->destination->nodeAggregateId, - }; - if ($newLocation->destination instanceof ParentNodeMoveDestination) { - $this->moveNodeIntoParent( - $event->contentStreamId, - $nodeToBeMoved, - $newLocation->coveredDimensionSpacePoint, - $newLocation->destination - ); - } - $this->moveSubtreeTags($event->contentStreamId, $event->nodeAggregateId, $newParentNodeAggregateId, $newLocation->coveredDimensionSpacePoint); + foreach ($moveNodeMapping->newLocations as $newLocation) { + assert($newLocation instanceof CoverageNodeMoveMapping); + + $affectedDimensionSpacePoints = new DimensionSpacePointSet([ + $newLocation->coveredDimensionSpacePoint + ]); + + // do the move (depending on how the move target is specified) + $newParentNodeAggregateId = match ($newLocation->destination::class) { + SucceedingSiblingNodeMoveDestination::class => $this->moveNodeBeforeSucceedingSibling( + $event->contentStreamId, + $nodeToBeMoved, + $newLocation->coveredDimensionSpacePoint, + $newLocation->destination + ), + ParentNodeMoveDestination::class => $newLocation->destination->nodeAggregateId, + }; + if ($newLocation->destination instanceof ParentNodeMoveDestination) { + $this->moveNodeIntoParent( + $event->contentStreamId, + $nodeToBeMoved, + $newLocation->coveredDimensionSpacePoint, + $newLocation->destination + ); } + $this->moveSubtreeTags($event->contentStreamId, $event->nodeAggregateId, $newParentNodeAggregateId, $newLocation->coveredDimensionSpacePoint); } - }); + } } /** @@ -241,6 +239,4 @@ private function findIngoingHierarchyRelationToBeMoved( abstract protected function getDatabaseConnection(): Connection; - - abstract protected function transactional(\Closure $operations): void; } diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/Feature/NodeRemoval.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/Feature/NodeRemoval.php index 86fbb00b696..cd70130001e 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/Feature/NodeRemoval.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/Feature/NodeRemoval.php @@ -31,17 +31,15 @@ private function whenNodeAggregateWasRemoved(NodeAggregateWasRemoved $event): vo { // the focus here is to be correct; that's why the method is not overly performant (for now at least). We might // lateron find tricks to improve performance - $this->transactional(function () use ($event) { - $ingoingRelations = $this->getProjectionContentGraph()->findIngoingHierarchyRelationsForNodeAggregate( - $event->contentStreamId, - $event->nodeAggregateId, - $event->affectedCoveredDimensionSpacePoints - ); + $ingoingRelations = $this->getProjectionContentGraph()->findIngoingHierarchyRelationsForNodeAggregate( + $event->contentStreamId, + $event->nodeAggregateId, + $event->affectedCoveredDimensionSpacePoints + ); - foreach ($ingoingRelations as $ingoingRelation) { - $this->removeRelationRecursivelyFromDatabaseIncludingNonReferencedNodes($ingoingRelation); - } - }); + foreach ($ingoingRelations as $ingoingRelation) { + $this->removeRelationRecursivelyFromDatabaseIncludingNonReferencedNodes($ingoingRelation); + } } /** @@ -85,6 +83,4 @@ protected function removeRelationRecursivelyFromDatabaseIncludingNonReferencedNo } abstract protected function getDatabaseConnection(): Connection; - - abstract protected function transactional(\Closure $operations): void; } diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/Feature/NodeVariation.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/Feature/NodeVariation.php index 27b2322512e..71aa3b71b38 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/Feature/NodeVariation.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/Feature/NodeVariation.php @@ -40,111 +40,109 @@ abstract protected function getTableNamePrefix(): string; */ private function whenNodeSpecializationVariantWasCreated(NodeSpecializationVariantWasCreated $event, EventEnvelope $eventEnvelope): void { - $this->transactional(function () use ($event, $eventEnvelope) { - // Do the actual specialization - $sourceNode = $this->getProjectionContentGraph()->findNodeInAggregate( + // Do the actual specialization + $sourceNode = $this->getProjectionContentGraph()->findNodeInAggregate( + $event->contentStreamId, + $event->nodeAggregateId, + $event->sourceOrigin->toDimensionSpacePoint() + ); + if (is_null($sourceNode)) { + throw EventCouldNotBeAppliedToContentGraph::becauseTheSourceNodeIsMissing(get_class($event)); + } + + $specializedNode = $this->copyNodeToDimensionSpacePoint( + $sourceNode, + $event->specializationOrigin, + $eventEnvelope + ); + + $uncoveredDimensionSpacePoints = $event->specializationSiblings->toDimensionSpacePointSet()->points; + foreach ( + $this->getProjectionContentGraph()->findIngoingHierarchyRelationsForNodeAggregate( $event->contentStreamId, - $event->nodeAggregateId, - $event->sourceOrigin->toDimensionSpacePoint() + $sourceNode->nodeAggregateId, + $event->specializationSiblings->toDimensionSpacePointSet() + ) as $hierarchyRelation + ) { + $hierarchyRelation->assignNewChildNode( + $specializedNode->relationAnchorPoint, + $this->getDatabaseConnection(), + $this->tableNamePrefix ); - if (is_null($sourceNode)) { - throw EventCouldNotBeAppliedToContentGraph::becauseTheSourceNodeIsMissing(get_class($event)); - } - - $specializedNode = $this->copyNodeToDimensionSpacePoint( - $sourceNode, - $event->specializationOrigin, - $eventEnvelope + unset($uncoveredDimensionSpacePoints[$hierarchyRelation->dimensionSpacePointHash]); + } + if (!empty($uncoveredDimensionSpacePoints)) { + $sourceParent = $this->projectionContentGraph->findParentNode( + $event->contentStreamId, + $event->nodeAggregateId, + $event->sourceOrigin, ); - - $uncoveredDimensionSpacePoints = $event->specializationSiblings->toDimensionSpacePointSet()->points; - foreach ( - $this->getProjectionContentGraph()->findIngoingHierarchyRelationsForNodeAggregate( - $event->contentStreamId, - $sourceNode->nodeAggregateId, - $event->specializationSiblings->toDimensionSpacePointSet() - ) as $hierarchyRelation - ) { - $hierarchyRelation->assignNewChildNode( - $specializedNode->relationAnchorPoint, - $this->getDatabaseConnection(), - $this->tableNamePrefix - ); - unset($uncoveredDimensionSpacePoints[$hierarchyRelation->dimensionSpacePointHash]); + if (is_null($sourceParent)) { + throw EventCouldNotBeAppliedToContentGraph::becauseTheSourceParentNodeIsMissing(get_class($event)); } - if (!empty($uncoveredDimensionSpacePoints)) { - $sourceParent = $this->projectionContentGraph->findParentNode( + foreach ($uncoveredDimensionSpacePoints as $uncoveredDimensionSpacePoint) { + $parentNode = $this->projectionContentGraph->findNodeInAggregate( $event->contentStreamId, - $event->nodeAggregateId, - $event->sourceOrigin, + $sourceParent->nodeAggregateId, + $uncoveredDimensionSpacePoint ); - if (is_null($sourceParent)) { - throw EventCouldNotBeAppliedToContentGraph::becauseTheSourceParentNodeIsMissing(get_class($event)); + if (is_null($parentNode)) { + throw EventCouldNotBeAppliedToContentGraph::becauseTheTargetParentNodeIsMissing( + get_class($event) + ); } - foreach ($uncoveredDimensionSpacePoints as $uncoveredDimensionSpacePoint) { - $parentNode = $this->projectionContentGraph->findNodeInAggregate( + $parentSubtreeTags = $this->subtreeTagsForHierarchyRelation($event->contentStreamId, $parentNode->relationAnchorPoint, $uncoveredDimensionSpacePoint); + + $specializationSucceedingSiblingNodeAggregateId = $event->specializationSiblings + ->getSucceedingSiblingIdForDimensionSpacePoint($uncoveredDimensionSpacePoint); + $specializationSucceedingSiblingNode = $specializationSucceedingSiblingNodeAggregateId + ? $this->getProjectionContentGraph()->findNodeInAggregate( $event->contentStreamId, - $sourceParent->nodeAggregateId, + $specializationSucceedingSiblingNodeAggregateId, $uncoveredDimensionSpacePoint - ); - if (is_null($parentNode)) { - throw EventCouldNotBeAppliedToContentGraph::becauseTheTargetParentNodeIsMissing( - get_class($event) - ); - } - $parentSubtreeTags = $this->subtreeTagsForHierarchyRelation($event->contentStreamId, $parentNode->relationAnchorPoint, $uncoveredDimensionSpacePoint); - - $specializationSucceedingSiblingNodeAggregateId = $event->specializationSiblings - ->getSucceedingSiblingIdForDimensionSpacePoint($uncoveredDimensionSpacePoint); - $specializationSucceedingSiblingNode = $specializationSucceedingSiblingNodeAggregateId - ? $this->getProjectionContentGraph()->findNodeInAggregate( - $event->contentStreamId, - $specializationSucceedingSiblingNodeAggregateId, - $uncoveredDimensionSpacePoint - ) - : null; + ) + : null; - $hierarchyRelation = new HierarchyRelation( + $hierarchyRelation = new HierarchyRelation( + $parentNode->relationAnchorPoint, + $specializedNode->relationAnchorPoint, + $sourceNode->nodeName, + $event->contentStreamId, + $uncoveredDimensionSpacePoint, + $uncoveredDimensionSpacePoint->hash, + $this->projectionContentGraph->determineHierarchyRelationPosition( $parentNode->relationAnchorPoint, $specializedNode->relationAnchorPoint, - $sourceNode->nodeName, + $specializationSucceedingSiblingNode?->relationAnchorPoint, $event->contentStreamId, - $uncoveredDimensionSpacePoint, - $uncoveredDimensionSpacePoint->hash, - $this->projectionContentGraph->determineHierarchyRelationPosition( - $parentNode->relationAnchorPoint, - $specializedNode->relationAnchorPoint, - $specializationSucceedingSiblingNode?->relationAnchorPoint, - $event->contentStreamId, - $uncoveredDimensionSpacePoint - ), - NodeTags::create(SubtreeTags::createEmpty(), $parentSubtreeTags->all()), - ); - $hierarchyRelation->addToDatabase($this->getDatabaseConnection(), $this->getTableNamePrefix()); - } - } - - foreach ( - $this->getProjectionContentGraph()->findOutgoingHierarchyRelationsForNodeAggregate( - $event->contentStreamId, - $sourceNode->nodeAggregateId, - $event->specializationSiblings->toDimensionSpacePointSet() - ) as $hierarchyRelation - ) { - $hierarchyRelation->assignNewParentNode( - $specializedNode->relationAnchorPoint, - null, - $this->getDatabaseConnection(), - $this->getTableNamePrefix() + $uncoveredDimensionSpacePoint + ), + NodeTags::create(SubtreeTags::createEmpty(), $parentSubtreeTags->all()), ); + $hierarchyRelation->addToDatabase($this->getDatabaseConnection(), $this->getTableNamePrefix()); } + } - // Copy Reference Edges - $this->copyReferenceRelations( - $sourceNode->relationAnchorPoint, - $specializedNode->relationAnchorPoint + foreach ( + $this->getProjectionContentGraph()->findOutgoingHierarchyRelationsForNodeAggregate( + $event->contentStreamId, + $sourceNode->nodeAggregateId, + $event->specializationSiblings->toDimensionSpacePointSet() + ) as $hierarchyRelation + ) { + $hierarchyRelation->assignNewParentNode( + $specializedNode->relationAnchorPoint, + null, + $this->getDatabaseConnection(), + $this->getTableNamePrefix() ); - }); + } + + // Copy Reference Edges + $this->copyReferenceRelations( + $sourceNode->relationAnchorPoint, + $specializedNode->relationAnchorPoint + ); } /** @@ -154,119 +152,117 @@ private function whenNodeSpecializationVariantWasCreated(NodeSpecializationVaria */ public function whenNodeGeneralizationVariantWasCreated(NodeGeneralizationVariantWasCreated $event, EventEnvelope $eventEnvelope): void { - $this->transactional(function () use ($event, $eventEnvelope) { - // do the generalization - $sourceNode = $this->getProjectionContentGraph()->findNodeInAggregate( + // do the generalization + $sourceNode = $this->getProjectionContentGraph()->findNodeInAggregate( + $event->contentStreamId, + $event->nodeAggregateId, + $event->sourceOrigin->toDimensionSpacePoint() + ); + if (is_null($sourceNode)) { + throw EventCouldNotBeAppliedToContentGraph::becauseTheSourceNodeIsMissing(get_class($event)); + } + $sourceParentNode = $this->getProjectionContentGraph()->findParentNode( + $event->contentStreamId, + $event->nodeAggregateId, + $event->sourceOrigin + ); + if (is_null($sourceParentNode)) { + throw EventCouldNotBeAppliedToContentGraph::becauseTheSourceParentNodeIsMissing(get_class($event)); + } + $generalizedNode = $this->copyNodeToDimensionSpacePoint( + $sourceNode, + $event->generalizationOrigin, + $eventEnvelope + ); + + $unassignedIngoingDimensionSpacePoints = $event->variantSucceedingSiblings->toDimensionSpacePointSet(); + foreach ( + $this->getProjectionContentGraph()->findIngoingHierarchyRelationsForNodeAggregate( $event->contentStreamId, $event->nodeAggregateId, - $event->sourceOrigin->toDimensionSpacePoint() + $event->variantSucceedingSiblings->toDimensionSpacePointSet() + ) as $existingIngoingHierarchyRelation + ) { + $existingIngoingHierarchyRelation->assignNewChildNode( + $generalizedNode->relationAnchorPoint, + $this->getDatabaseConnection(), + $this->tableNamePrefix ); - if (is_null($sourceNode)) { - throw EventCouldNotBeAppliedToContentGraph::becauseTheSourceNodeIsMissing(get_class($event)); - } - $sourceParentNode = $this->getProjectionContentGraph()->findParentNode( + $unassignedIngoingDimensionSpacePoints = $unassignedIngoingDimensionSpacePoints->getDifference( + new DimensionSpacePointSet([ + $existingIngoingHierarchyRelation->dimensionSpacePoint + ]) + ); + } + + foreach ( + $this->getProjectionContentGraph()->findOutgoingHierarchyRelationsForNodeAggregate( $event->contentStreamId, $event->nodeAggregateId, - $event->sourceOrigin - ); - if (is_null($sourceParentNode)) { - throw EventCouldNotBeAppliedToContentGraph::becauseTheSourceParentNodeIsMissing(get_class($event)); - } - $generalizedNode = $this->copyNodeToDimensionSpacePoint( - $sourceNode, - $event->generalizationOrigin, - $eventEnvelope + $event->variantSucceedingSiblings->toDimensionSpacePointSet() + ) as $existingOutgoingHierarchyRelation + ) { + $existingOutgoingHierarchyRelation->assignNewParentNode( + $generalizedNode->relationAnchorPoint, + null, + $this->getDatabaseConnection(), + $this->getTableNamePrefix() ); + } - $unassignedIngoingDimensionSpacePoints = $event->variantSucceedingSiblings->toDimensionSpacePointSet(); - foreach ( - $this->getProjectionContentGraph()->findIngoingHierarchyRelationsForNodeAggregate( - $event->contentStreamId, - $event->nodeAggregateId, - $event->variantSucceedingSiblings->toDimensionSpacePointSet() - ) as $existingIngoingHierarchyRelation - ) { - $existingIngoingHierarchyRelation->assignNewChildNode( - $generalizedNode->relationAnchorPoint, - $this->getDatabaseConnection(), - $this->tableNamePrefix - ); - $unassignedIngoingDimensionSpacePoints = $unassignedIngoingDimensionSpacePoints->getDifference( - new DimensionSpacePointSet([ - $existingIngoingHierarchyRelation->dimensionSpacePoint - ]) + if (count($unassignedIngoingDimensionSpacePoints) > 0) { + $projectionContentGraph = $this->getProjectionContentGraph(); + $ingoingSourceHierarchyRelation = $projectionContentGraph->findIngoingHierarchyRelationsForNode( + $sourceNode->relationAnchorPoint, + $event->contentStreamId, + new DimensionSpacePointSet([$event->sourceOrigin->toDimensionSpacePoint()]) + )[$event->sourceOrigin->hash] ?? null; + if (is_null($ingoingSourceHierarchyRelation)) { + throw EventCouldNotBeAppliedToContentGraph::becauseTheIngoingSourceHierarchyRelationIsMissing( + get_class($event) ); } - - foreach ( - $this->getProjectionContentGraph()->findOutgoingHierarchyRelationsForNodeAggregate( + // the null case is caught by the NodeAggregate or its command handler + foreach ($unassignedIngoingDimensionSpacePoints as $unassignedDimensionSpacePoint) { + // The parent node aggregate might be varied as well, + // so we need to find a parent node for each covered dimension space point + $generalizationParentNode = $this->getProjectionContentGraph()->findNodeInAggregate( $event->contentStreamId, - $event->nodeAggregateId, - $event->variantSucceedingSiblings->toDimensionSpacePointSet() - ) as $existingOutgoingHierarchyRelation - ) { - $existingOutgoingHierarchyRelation->assignNewParentNode( - $generalizedNode->relationAnchorPoint, - null, - $this->getDatabaseConnection(), - $this->getTableNamePrefix() + $sourceParentNode->nodeAggregateId, + $unassignedDimensionSpacePoint ); - } - - if (count($unassignedIngoingDimensionSpacePoints) > 0) { - $projectionContentGraph = $this->getProjectionContentGraph(); - $ingoingSourceHierarchyRelation = $projectionContentGraph->findIngoingHierarchyRelationsForNode( - $sourceNode->relationAnchorPoint, - $event->contentStreamId, - new DimensionSpacePointSet([$event->sourceOrigin->toDimensionSpacePoint()]) - )[$event->sourceOrigin->hash] ?? null; - if (is_null($ingoingSourceHierarchyRelation)) { - throw EventCouldNotBeAppliedToContentGraph::becauseTheIngoingSourceHierarchyRelationIsMissing( + if (is_null($generalizationParentNode)) { + throw EventCouldNotBeAppliedToContentGraph::becauseTheTargetParentNodeIsMissing( get_class($event) ); } - // the null case is caught by the NodeAggregate or its command handler - foreach ($unassignedIngoingDimensionSpacePoints as $unassignedDimensionSpacePoint) { - // The parent node aggregate might be varied as well, - // so we need to find a parent node for each covered dimension space point - $generalizationParentNode = $this->getProjectionContentGraph()->findNodeInAggregate( + + $generalizationSucceedingSiblingNodeAggregateId = $event->variantSucceedingSiblings + ->getSucceedingSiblingIdForDimensionSpacePoint($unassignedDimensionSpacePoint); + $generalizationSucceedingSiblingNode = $generalizationSucceedingSiblingNodeAggregateId + ? $this->getProjectionContentGraph()->findNodeInAggregate( $event->contentStreamId, - $sourceParentNode->nodeAggregateId, + $generalizationSucceedingSiblingNodeAggregateId, $unassignedDimensionSpacePoint - ); - if (is_null($generalizationParentNode)) { - throw EventCouldNotBeAppliedToContentGraph::becauseTheTargetParentNodeIsMissing( - get_class($event) - ); - } - - $generalizationSucceedingSiblingNodeAggregateId = $event->variantSucceedingSiblings - ->getSucceedingSiblingIdForDimensionSpacePoint($unassignedDimensionSpacePoint); - $generalizationSucceedingSiblingNode = $generalizationSucceedingSiblingNodeAggregateId - ? $this->getProjectionContentGraph()->findNodeInAggregate( - $event->contentStreamId, - $generalizationSucceedingSiblingNodeAggregateId, - $unassignedDimensionSpacePoint - ) - : null; + ) + : null; - $this->copyHierarchyRelationToDimensionSpacePoint( - $ingoingSourceHierarchyRelation, - $event->contentStreamId, - $unassignedDimensionSpacePoint, - $generalizationParentNode->relationAnchorPoint, - $generalizedNode->relationAnchorPoint, - $generalizationSucceedingSiblingNode?->relationAnchorPoint - ); - } + $this->copyHierarchyRelationToDimensionSpacePoint( + $ingoingSourceHierarchyRelation, + $event->contentStreamId, + $unassignedDimensionSpacePoint, + $generalizationParentNode->relationAnchorPoint, + $generalizedNode->relationAnchorPoint, + $generalizationSucceedingSiblingNode?->relationAnchorPoint + ); } + } - // Copy Reference Edges - $this->copyReferenceRelations( - $sourceNode->relationAnchorPoint, - $generalizedNode->relationAnchorPoint - ); - }); + // Copy Reference Edges + $this->copyReferenceRelations( + $sourceNode->relationAnchorPoint, + $generalizedNode->relationAnchorPoint + ); } /** @@ -274,102 +270,100 @@ public function whenNodeGeneralizationVariantWasCreated(NodeGeneralizationVarian */ public function whenNodePeerVariantWasCreated(NodePeerVariantWasCreated $event, EventEnvelope $eventEnvelope): void { - $this->transactional(function () use ($event, $eventEnvelope) { - // Do the peer variant creation itself - $sourceNode = $this->getProjectionContentGraph()->findNodeInAggregate( + // Do the peer variant creation itself + $sourceNode = $this->getProjectionContentGraph()->findNodeInAggregate( + $event->contentStreamId, + $event->nodeAggregateId, + $event->sourceOrigin->toDimensionSpacePoint() + ); + if (is_null($sourceNode)) { + throw EventCouldNotBeAppliedToContentGraph::becauseTheSourceNodeIsMissing(get_class($event)); + } + $peerNode = $this->copyNodeToDimensionSpacePoint( + $sourceNode, + $event->peerOrigin, + $eventEnvelope + ); + + $unassignedIngoingDimensionSpacePoints = $event->peerSucceedingSiblings->toDimensionSpacePointSet(); + foreach ( + $this->getProjectionContentGraph()->findIngoingHierarchyRelationsForNodeAggregate( $event->contentStreamId, $event->nodeAggregateId, - $event->sourceOrigin->toDimensionSpacePoint() + $event->peerSucceedingSiblings->toDimensionSpacePointSet() + ) as $existingIngoingHierarchyRelation + ) { + $existingIngoingHierarchyRelation->assignNewChildNode( + $peerNode->relationAnchorPoint, + $this->getDatabaseConnection(), + $this->tableNamePrefix ); - if (is_null($sourceNode)) { - throw EventCouldNotBeAppliedToContentGraph::becauseTheSourceNodeIsMissing(get_class($event)); - } - $peerNode = $this->copyNodeToDimensionSpacePoint( - $sourceNode, - $event->peerOrigin, - $eventEnvelope + $unassignedIngoingDimensionSpacePoints = $unassignedIngoingDimensionSpacePoints->getDifference( + new DimensionSpacePointSet([ + $existingIngoingHierarchyRelation->dimensionSpacePoint + ]) ); + } - $unassignedIngoingDimensionSpacePoints = $event->peerSucceedingSiblings->toDimensionSpacePointSet(); - foreach ( - $this->getProjectionContentGraph()->findIngoingHierarchyRelationsForNodeAggregate( - $event->contentStreamId, - $event->nodeAggregateId, - $event->peerSucceedingSiblings->toDimensionSpacePointSet() - ) as $existingIngoingHierarchyRelation - ) { - $existingIngoingHierarchyRelation->assignNewChildNode( - $peerNode->relationAnchorPoint, - $this->getDatabaseConnection(), - $this->tableNamePrefix - ); - $unassignedIngoingDimensionSpacePoints = $unassignedIngoingDimensionSpacePoints->getDifference( - new DimensionSpacePointSet([ - $existingIngoingHierarchyRelation->dimensionSpacePoint - ]) - ); - } - - foreach ( - $this->getProjectionContentGraph()->findOutgoingHierarchyRelationsForNodeAggregate( - $event->contentStreamId, - $event->nodeAggregateId, - $event->peerSucceedingSiblings->toDimensionSpacePointSet() - ) as $existingOutgoingHierarchyRelation - ) { - $existingOutgoingHierarchyRelation->assignNewParentNode( - $peerNode->relationAnchorPoint, - null, - $this->getDatabaseConnection(), - $this->getTableNamePrefix() - ); - } - - $sourceParentNode = $this->getProjectionContentGraph()->findParentNode( + foreach ( + $this->getProjectionContentGraph()->findOutgoingHierarchyRelationsForNodeAggregate( $event->contentStreamId, $event->nodeAggregateId, - $event->sourceOrigin + $event->peerSucceedingSiblings->toDimensionSpacePointSet() + ) as $existingOutgoingHierarchyRelation + ) { + $existingOutgoingHierarchyRelation->assignNewParentNode( + $peerNode->relationAnchorPoint, + null, + $this->getDatabaseConnection(), + $this->getTableNamePrefix() ); - if (is_null($sourceParentNode)) { - throw EventCouldNotBeAppliedToContentGraph::becauseTheSourceParentNodeIsMissing(get_class($event)); + } + + $sourceParentNode = $this->getProjectionContentGraph()->findParentNode( + $event->contentStreamId, + $event->nodeAggregateId, + $event->sourceOrigin + ); + if (is_null($sourceParentNode)) { + throw EventCouldNotBeAppliedToContentGraph::becauseTheSourceParentNodeIsMissing(get_class($event)); + } + foreach ($unassignedIngoingDimensionSpacePoints as $coveredDimensionSpacePoint) { + // The parent node aggregate might be varied as well, + // so we need to find a parent node for each covered dimension space point + $peerParentNode = $this->getProjectionContentGraph()->findNodeInAggregate( + $event->contentStreamId, + $sourceParentNode->nodeAggregateId, + $coveredDimensionSpacePoint + ); + if (is_null($peerParentNode)) { + throw EventCouldNotBeAppliedToContentGraph::becauseTheTargetParentNodeIsMissing(get_class($event)); } - foreach ($unassignedIngoingDimensionSpacePoints as $coveredDimensionSpacePoint) { - // The parent node aggregate might be varied as well, - // so we need to find a parent node for each covered dimension space point - $peerParentNode = $this->getProjectionContentGraph()->findNodeInAggregate( + $peerSucceedingSiblingNodeAggregateId = $event->peerSucceedingSiblings + ->getSucceedingSiblingIdForDimensionSpacePoint($coveredDimensionSpacePoint); + $peerSucceedingSiblingNode = $peerSucceedingSiblingNodeAggregateId + ? $this->getProjectionContentGraph()->findNodeInAggregate( $event->contentStreamId, - $sourceParentNode->nodeAggregateId, + $peerSucceedingSiblingNodeAggregateId, $coveredDimensionSpacePoint - ); - if (is_null($peerParentNode)) { - throw EventCouldNotBeAppliedToContentGraph::becauseTheTargetParentNodeIsMissing(get_class($event)); - } - $peerSucceedingSiblingNodeAggregateId = $event->peerSucceedingSiblings - ->getSucceedingSiblingIdForDimensionSpacePoint($coveredDimensionSpacePoint); - $peerSucceedingSiblingNode = $peerSucceedingSiblingNodeAggregateId - ? $this->getProjectionContentGraph()->findNodeInAggregate( - $event->contentStreamId, - $peerSucceedingSiblingNodeAggregateId, - $coveredDimensionSpacePoint - ) - : null; - - $this->connectHierarchy( - $event->contentStreamId, - $peerParentNode->relationAnchorPoint, - $peerNode->relationAnchorPoint, - new DimensionSpacePointSet([$coveredDimensionSpacePoint]), - $peerSucceedingSiblingNode?->relationAnchorPoint, - $sourceNode->nodeName - ); - } + ) + : null; - // Copy Reference Edges - $this->copyReferenceRelations( - $sourceNode->relationAnchorPoint, - $peerNode->relationAnchorPoint + $this->connectHierarchy( + $event->contentStreamId, + $peerParentNode->relationAnchorPoint, + $peerNode->relationAnchorPoint, + new DimensionSpacePointSet([$coveredDimensionSpacePoint]), + $peerSucceedingSiblingNode?->relationAnchorPoint, + $sourceNode->nodeName ); - }); + } + + // Copy Reference Edges + $this->copyReferenceRelations( + $sourceNode->relationAnchorPoint, + $peerNode->relationAnchorPoint + ); } abstract protected function copyNodeToDimensionSpacePoint( @@ -402,6 +396,4 @@ abstract protected function copyReferenceRelations( ): void; abstract protected function getDatabaseConnection(): Connection; - - abstract protected function transactional(\Closure $operations): void; } diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/HierarchyRelation.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/HierarchyRelation.php index 8bc02f1e7d3..688ef876c9f 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/HierarchyRelation.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/HierarchyRelation.php @@ -45,22 +45,18 @@ public function __construct( */ public function addToDatabase(Connection $databaseConnection, string $tableNamePrefix): void { - $databaseConnection->transactional(function ($databaseConnection) use ( - $tableNamePrefix - ) { - $dimensionSpacePoints = new DimensionSpacePointsRepository($databaseConnection, $tableNamePrefix); - $dimensionSpacePoints->insertDimensionSpacePoint($this->dimensionSpacePoint); + $dimensionSpacePoints = new DimensionSpacePointsRepository($databaseConnection, $tableNamePrefix); + $dimensionSpacePoints->insertDimensionSpacePoint($this->dimensionSpacePoint); - $databaseConnection->insert($tableNamePrefix . '_hierarchyrelation', [ - 'parentnodeanchor' => $this->parentNodeAnchor->value, - 'childnodeanchor' => $this->childNodeAnchor->value, - 'name' => $this->name?->value, - 'contentstreamid' => $this->contentStreamId->value, - 'dimensionspacepointhash' => $this->dimensionSpacePointHash, - 'position' => $this->position, - 'subtreetags' => json_encode($this->subtreeTags, JSON_THROW_ON_ERROR | JSON_FORCE_OBJECT), - ]); - }); + $databaseConnection->insert($tableNamePrefix . '_hierarchyrelation', [ + 'parentnodeanchor' => $this->parentNodeAnchor->value, + 'childnodeanchor' => $this->childNodeAnchor->value, + 'name' => $this->name?->value, + 'contentstreamid' => $this->contentStreamId->value, + 'dimensionspacepointhash' => $this->dimensionSpacePointHash, + 'position' => $this->position, + 'subtreetags' => json_encode($this->subtreeTags, JSON_THROW_ON_ERROR | JSON_FORCE_OBJECT), + ]); } /** diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/NodeRecord.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/NodeRecord.php index fbc75314807..e4dee7d51c7 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/NodeRecord.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/NodeRecord.php @@ -139,38 +139,26 @@ public static function createNewInDatabase( ?NodeName $nodeName, Timestamps $timestamps, ): self { - $relationAnchorPoint = $databaseConnection->transactional(function ($databaseConnection) use ( - $tableNamePrefix, - $nodeAggregateId, - $originDimensionSpacePoint, - $originDimensionSpacePointHash, - $properties, - $nodeTypeName, - $classification, - $timestamps - ) { - $dimensionSpacePoints = new DimensionSpacePointsRepository($databaseConnection, $tableNamePrefix); - $dimensionSpacePoints->insertDimensionSpacePointByHashAndCoordinates($originDimensionSpacePointHash, $originDimensionSpacePoint); - - $databaseConnection->insert($tableNamePrefix . '_node', [ - 'nodeaggregateid' => $nodeAggregateId->value, - 'origindimensionspacepointhash' => $originDimensionSpacePointHash, - 'properties' => json_encode($properties), - 'nodetypename' => $nodeTypeName->value, - 'classification' => $classification->value, - 'created' => $timestamps->created, - 'originalcreated' => $timestamps->originalCreated, - 'lastmodified' => $timestamps->lastModified, - 'originallastmodified' => $timestamps->originalLastModified, - ], [ - 'created' => Types::DATETIME_IMMUTABLE, - 'originalcreated' => Types::DATETIME_IMMUTABLE, - 'lastmodified' => Types::DATETIME_IMMUTABLE, - 'originallastmodified' => Types::DATETIME_IMMUTABLE, - ]); + $dimensionSpacePoints = new DimensionSpacePointsRepository($databaseConnection, $tableNamePrefix); + $dimensionSpacePoints->insertDimensionSpacePointByHashAndCoordinates($originDimensionSpacePointHash, $originDimensionSpacePoint); - return NodeRelationAnchorPoint::fromInteger((int)$databaseConnection->lastInsertId()); - }); + $databaseConnection->insert($tableNamePrefix . '_node', [ + 'nodeaggregateid' => $nodeAggregateId->value, + 'origindimensionspacepointhash' => $originDimensionSpacePointHash, + 'properties' => json_encode($properties), + 'nodetypename' => $nodeTypeName->value, + 'classification' => $classification->value, + 'created' => $timestamps->created, + 'originalcreated' => $timestamps->originalCreated, + 'lastmodified' => $timestamps->lastModified, + 'originallastmodified' => $timestamps->originalLastModified, + ], [ + 'created' => Types::DATETIME_IMMUTABLE, + 'originalcreated' => Types::DATETIME_IMMUTABLE, + 'lastmodified' => Types::DATETIME_IMMUTABLE, + 'originallastmodified' => Types::DATETIME_IMMUTABLE, + ]); + $relationAnchorPoint = NodeRelationAnchorPoint::fromInteger((int)$databaseConnection->lastInsertId()); return new self( $relationAnchorPoint, diff --git a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/ContentStreamForking.php b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/ContentStreamForking.php index a9bf6076af0..dcb59cd51e0 100644 --- a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/ContentStreamForking.php +++ b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/ContentStreamForking.php @@ -29,40 +29,33 @@ trait ContentStreamForking */ private function whenContentStreamWasForked(ContentStreamWasForked $event): void { - $this->transactional(function () use ($event) { - $parameters = [ - 'sourceContentStreamId' => $event->sourceContentStreamId->value, - 'targetContentStreamId' => $event->newContentStreamId->value - ]; - - $this->getDatabaseConnection()->executeQuery(/** @lang PostgreSQL */ - 'INSERT INTO ' . $this->tableNamePrefix . '_hierarchyhyperrelation - (contentstreamid, parentnodeanchor, - dimensionspacepoint, dimensionspacepointhash, childnodeanchors) - SELECT :targetContentStreamId, parentnodeanchor, - dimensionspacepoint, dimensionspacepointhash, childnodeanchors - FROM ' . $this->tableNamePrefix . '_hierarchyhyperrelation source - WHERE source.contentstreamid = :sourceContentStreamId', - $parameters - ); - - $this->getDatabaseConnection()->executeQuery(/** @lang PostgreSQL */ - 'INSERT INTO ' . $this->tableNamePrefix . '_restrictionhyperrelation - (contentstreamid, dimensionspacepointhash, - originnodeaggregateid, affectednodeaggregateids) - SELECT :targetContentStreamId, dimensionspacepointhash, - originnodeaggregateid, affectednodeaggregateids - FROM ' . $this->tableNamePrefix . '_restrictionhyperrelation source - WHERE source.contentstreamid = :sourceContentStreamId', - $parameters - ); - }); + $parameters = [ + 'sourceContentStreamId' => $event->sourceContentStreamId->value, + 'targetContentStreamId' => $event->newContentStreamId->value + ]; + + $this->getDatabaseConnection()->executeQuery(/** @lang PostgreSQL */ + 'INSERT INTO ' . $this->tableNamePrefix . '_hierarchyhyperrelation + (contentstreamid, parentnodeanchor, + dimensionspacepoint, dimensionspacepointhash, childnodeanchors) + SELECT :targetContentStreamId, parentnodeanchor, + dimensionspacepoint, dimensionspacepointhash, childnodeanchors + FROM ' . $this->tableNamePrefix . '_hierarchyhyperrelation source + WHERE source.contentstreamid = :sourceContentStreamId', + $parameters + ); + + $this->getDatabaseConnection()->executeQuery(/** @lang PostgreSQL */ + 'INSERT INTO ' . $this->tableNamePrefix . '_restrictionhyperrelation + (contentstreamid, dimensionspacepointhash, + originnodeaggregateid, affectednodeaggregateids) + SELECT :targetContentStreamId, dimensionspacepointhash, + originnodeaggregateid, affectednodeaggregateids + FROM ' . $this->tableNamePrefix . '_restrictionhyperrelation source + WHERE source.contentstreamid = :sourceContentStreamId', + $parameters + ); } - /** - * @throws \Throwable - */ - abstract protected function transactional(\Closure $operations): void; - abstract protected function getDatabaseConnection(): Connection; } diff --git a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/CopyOnWrite.php b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/CopyOnWrite.php index 5b282272e7d..4ea0b24e3a4 100644 --- a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/CopyOnWrite.php +++ b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/CopyOnWrite.php @@ -136,10 +136,5 @@ private function copyOutgoingReferenceRelations( abstract protected function getProjectionHypergraph(): ProjectionHypergraph; - /** - * @throws \Throwable - */ - abstract protected function transactional(\Closure $operations): void; - abstract protected function getDatabaseConnection(): Connection; } diff --git a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/NodeCreation.php b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/NodeCreation.php index e5bb9f35b24..fdf40c46fe0 100644 --- a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/NodeCreation.php +++ b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/NodeCreation.php @@ -57,16 +57,14 @@ private function whenRootNodeAggregateWithNodeWasCreated(RootNodeAggregateWithNo null ); - $this->transactional(function () use ($node, $event) { - $node->addToDatabase($this->getDatabaseConnection(), $this->tableNamePrefix); - $this->connectToHierarchy( - $event->contentStreamId, - NodeRelationAnchorPoint::forRootHierarchyRelation(), - $node->relationAnchorPoint, - $event->coveredDimensionSpacePoints, - null - ); - }); + $node->addToDatabase($this->getDatabaseConnection(), $this->tableNamePrefix); + $this->connectToHierarchy( + $event->contentStreamId, + NodeRelationAnchorPoint::forRootHierarchyRelation(), + $node->relationAnchorPoint, + $event->coveredDimensionSpacePoints, + null + ); } /** @@ -87,58 +85,56 @@ public function whenNodeAggregateWithNodeWasCreated(NodeAggregateWithNodeWasCrea $event->nodeName ); - $this->transactional(function () use ($node, $event) { - $node->addToDatabase($this->getDatabaseConnection(), $this->tableNamePrefix); - foreach ($event->succeedingSiblingsForCoverage->toDimensionSpacePointSet() as $dimensionSpacePoint) { - $hierarchyRelation = $this->getProjectionHypergraph()->findChildHierarchyHyperrelationRecord( + $node->addToDatabase($this->getDatabaseConnection(), $this->tableNamePrefix); + foreach ($event->succeedingSiblingsForCoverage->toDimensionSpacePointSet() as $dimensionSpacePoint) { + $hierarchyRelation = $this->getProjectionHypergraph()->findChildHierarchyHyperrelationRecord( + $event->contentStreamId, + $dimensionSpacePoint, + $event->parentNodeAggregateId + ); + if ($hierarchyRelation) { + $succeedingSiblingNodeAnchor = null; + $succeedingSiblingNodeAggregateId = $event->succeedingSiblingsForCoverage->getSucceedingSiblingIdForDimensionSpacePoint($dimensionSpacePoint); + if ($succeedingSiblingNodeAggregateId) { + $succeedingSiblingNode = $this->getProjectionHypergraph()->findNodeRecordByCoverage( + $event->contentStreamId, + $dimensionSpacePoint, + $succeedingSiblingNodeAggregateId + ); + $succeedingSiblingNodeAnchor = $succeedingSiblingNode?->relationAnchorPoint; + } + $hierarchyRelation->addChildNodeAnchor( + $node->relationAnchorPoint, + $succeedingSiblingNodeAnchor, + $this->getDatabaseConnection(), + $this->tableNamePrefix + ); + } else { + $parentNode = $this->getProjectionHypergraph()->findNodeRecordByCoverage( $event->contentStreamId, $dimensionSpacePoint, $event->parentNodeAggregateId ); - if ($hierarchyRelation) { - $succeedingSiblingNodeAnchor = null; - $succeedingSiblingNodeAggregateId = $event->succeedingSiblingsForCoverage->getSucceedingSiblingIdForDimensionSpacePoint($dimensionSpacePoint); - if ($succeedingSiblingNodeAggregateId) { - $succeedingSiblingNode = $this->getProjectionHypergraph()->findNodeRecordByCoverage( - $event->contentStreamId, - $dimensionSpacePoint, - $succeedingSiblingNodeAggregateId - ); - $succeedingSiblingNodeAnchor = $succeedingSiblingNode?->relationAnchorPoint; - } - $hierarchyRelation->addChildNodeAnchor( - $node->relationAnchorPoint, - $succeedingSiblingNodeAnchor, - $this->getDatabaseConnection(), - $this->tableNamePrefix + if (is_null($parentNode)) { + throw EventCouldNotBeAppliedToContentGraph::becauseTheTargetParentNodeIsMissing( + get_class($event) ); - } else { - $parentNode = $this->getProjectionHypergraph()->findNodeRecordByCoverage( - $event->contentStreamId, - $dimensionSpacePoint, - $event->parentNodeAggregateId - ); - if (is_null($parentNode)) { - throw EventCouldNotBeAppliedToContentGraph::becauseTheTargetParentNodeIsMissing( - get_class($event) - ); - } - $hierarchyRelation = new HierarchyHyperrelationRecord( - $event->contentStreamId, - $parentNode->relationAnchorPoint, - $dimensionSpacePoint, - NodeRelationAnchorPoints::fromArray([$node->relationAnchorPoint]) - ); - $hierarchyRelation->addToDatabase($this->getDatabaseConnection(), $this->tableNamePrefix); } - $this->connectToRestrictionRelations( + $hierarchyRelation = new HierarchyHyperrelationRecord( $event->contentStreamId, + $parentNode->relationAnchorPoint, $dimensionSpacePoint, - $event->parentNodeAggregateId, - $event->nodeAggregateId + NodeRelationAnchorPoints::fromArray([$node->relationAnchorPoint]) ); + $hierarchyRelation->addToDatabase($this->getDatabaseConnection(), $this->tableNamePrefix); } - }); + $this->connectToRestrictionRelations( + $event->contentStreamId, + $dimensionSpacePoint, + $event->parentNodeAggregateId, + $event->nodeAggregateId + ); + } } /** @@ -204,10 +200,5 @@ protected function connectToRestrictionRelations( abstract protected function getProjectionHypergraph(): ProjectionHypergraph; - /** - * @throws \Throwable - */ - abstract protected function transactional(\Closure $operations): void; - abstract protected function getDatabaseConnection(): Connection; } diff --git a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/NodeModification.php b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/NodeModification.php index ff287ecfda3..47a88fdcff5 100644 --- a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/NodeModification.php +++ b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/NodeModification.php @@ -34,33 +34,26 @@ trait NodeModification */ private function whenNodePropertiesWereSet(NodePropertiesWereSet $event): void { - $this->transactional(function () use ($event) { - $nodeRecord = $this->getProjectionHypergraph()->findNodeRecordByOrigin( - $event->contentStreamId, - $event->originDimensionSpacePoint, - $event->nodeAggregateId - ); - if (is_null($nodeRecord)) { - throw EventCouldNotBeAppliedToContentGraph::becauseTheSourceNodeIsMissing(get_class($event)); + $nodeRecord = $this->getProjectionHypergraph()->findNodeRecordByOrigin( + $event->contentStreamId, + $event->originDimensionSpacePoint, + $event->nodeAggregateId + ); + if (is_null($nodeRecord)) { + throw EventCouldNotBeAppliedToContentGraph::becauseTheSourceNodeIsMissing(get_class($event)); + } + $this->copyOnWrite( + $event->contentStreamId, + $nodeRecord, + function (NodeRecord $node) use ($event) { + $node->properties = $node->properties + ->merge($event->propertyValues) + ->unsetProperties($event->propertiesToUnset); } - $this->copyOnWrite( - $event->contentStreamId, - $nodeRecord, - function (NodeRecord $node) use ($event) { - $node->properties = $node->properties - ->merge($event->propertyValues) - ->unsetProperties($event->propertiesToUnset); - } - ); - }); + ); } abstract protected function getProjectionHypergraph(): ProjectionHypergraph; - /** - * @throws \Throwable - */ - abstract protected function transactional(\Closure $operations): void; - abstract protected function getDatabaseConnection(): Connection; } diff --git a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/NodeReferencing.php b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/NodeReferencing.php index 4becf3ef57a..0f18c42294f 100644 --- a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/NodeReferencing.php +++ b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/NodeReferencing.php @@ -35,54 +35,47 @@ trait NodeReferencing */ private function whenNodeReferencesWereSet(NodeReferencesWereSet $event): void { - $this->transactional(function () use ($event) { - foreach ($event->affectedSourceOriginDimensionSpacePoints as $originDimensionSpacePoint) { - $nodeRecord = $this->getProjectionHypergraph()->findNodeRecordByOrigin( + foreach ($event->affectedSourceOriginDimensionSpacePoints as $originDimensionSpacePoint) { + $nodeRecord = $this->getProjectionHypergraph()->findNodeRecordByOrigin( + $event->contentStreamId, + $originDimensionSpacePoint, + $event->sourceNodeAggregateId + ); + + if ($nodeRecord) { + $anchorPoint = $this->copyOnWrite( $event->contentStreamId, - $originDimensionSpacePoint, - $event->sourceNodeAggregateId + $nodeRecord, + function (NodeRecord $node) { + } ); - if ($nodeRecord) { - $anchorPoint = $this->copyOnWrite( - $event->contentStreamId, - $nodeRecord, - function (NodeRecord $node) { - } - ); + // remove old + $this->getDatabaseConnection()->delete($this->tableNamePrefix . '_referencerelation', [ + 'sourcenodeanchor' => $anchorPoint->value, + 'name' => $event->referenceName->value + ]); - // remove old - $this->getDatabaseConnection()->delete($this->tableNamePrefix . '_referencerelation', [ - 'sourcenodeanchor' => $anchorPoint->value, - 'name' => $event->referenceName->value - ]); - - // set new - $position = 0; - foreach ($event->references as $reference) { - $referenceRecord = new ReferenceRelationRecord( - $anchorPoint, - $event->referenceName, - $position, - $reference->properties, - $reference->targetNodeAggregateId - ); - $referenceRecord->addToDatabase($this->getDatabaseConnection(), $this->tableNamePrefix); - $position++; - } - } else { - throw EventCouldNotBeAppliedToContentGraph::becauseTheSourceNodeIsMissing(get_class($event)); + // set new + $position = 0; + foreach ($event->references as $reference) { + $referenceRecord = new ReferenceRelationRecord( + $anchorPoint, + $event->referenceName, + $position, + $reference->properties, + $reference->targetNodeAggregateId + ); + $referenceRecord->addToDatabase($this->getDatabaseConnection(), $this->tableNamePrefix); + $position++; } + } else { + throw EventCouldNotBeAppliedToContentGraph::becauseTheSourceNodeIsMissing(get_class($event)); } - }); + } } abstract protected function getProjectionHypergraph(): ProjectionHypergraph; - /** - * @throws \Throwable - */ - abstract protected function transactional(\Closure $operations): void; - abstract protected function getDatabaseConnection(): Connection; } diff --git a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/NodeRemoval.php b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/NodeRemoval.php index cfa2938e061..0dccdae301a 100644 --- a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/NodeRemoval.php +++ b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/NodeRemoval.php @@ -38,73 +38,71 @@ trait NodeRemoval */ private function whenNodeAggregateWasRemoved(NodeAggregateWasRemoved $event): void { - $this->transactional(function () use ($event) { - $affectedRelationAnchorPoints = []; - // first step: remove hierarchy relations - foreach ($event->affectedCoveredDimensionSpacePoints as $dimensionSpacePoint) { - $nodeRecord = $this->getProjectionHypergraph()->findNodeRecordByCoverage( - $event->getContentStreamId(), - $dimensionSpacePoint, - $event->getNodeAggregateId() - ); - if (is_null($nodeRecord)) { - throw EventCouldNotBeAppliedToContentGraph::becauseTheSourceNodeIsMissing(get_class($event)); - } + $affectedRelationAnchorPoints = []; + // first step: remove hierarchy relations + foreach ($event->affectedCoveredDimensionSpacePoints as $dimensionSpacePoint) { + $nodeRecord = $this->getProjectionHypergraph()->findNodeRecordByCoverage( + $event->getContentStreamId(), + $dimensionSpacePoint, + $event->getNodeAggregateId() + ); + if (is_null($nodeRecord)) { + throw EventCouldNotBeAppliedToContentGraph::becauseTheSourceNodeIsMissing(get_class($event)); + } - /** @var HierarchyHyperrelationRecord $ingoingHierarchyRelation */ - $ingoingHierarchyRelation = $this->getProjectionHypergraph() - ->findHierarchyHyperrelationRecordByChildNodeAnchor( - $event->getContentStreamId(), - $dimensionSpacePoint, - $nodeRecord->relationAnchorPoint - ); - $ingoingHierarchyRelation->removeChildNodeAnchor( - $nodeRecord->relationAnchorPoint, - $this->getDatabaseConnection(), - $this->tableNamePrefix - ); - $this->removeFromRestrictions( + /** @var HierarchyHyperrelationRecord $ingoingHierarchyRelation */ + $ingoingHierarchyRelation = $this->getProjectionHypergraph() + ->findHierarchyHyperrelationRecordByChildNodeAnchor( $event->getContentStreamId(), $dimensionSpacePoint, - $event->getNodeAggregateId() + $nodeRecord->relationAnchorPoint ); + $ingoingHierarchyRelation->removeChildNodeAnchor( + $nodeRecord->relationAnchorPoint, + $this->getDatabaseConnection(), + $this->tableNamePrefix + ); + $this->removeFromRestrictions( + $event->getContentStreamId(), + $dimensionSpacePoint, + $event->getNodeAggregateId() + ); - $affectedRelationAnchorPoints[] = $nodeRecord->relationAnchorPoint; + $affectedRelationAnchorPoints[] = $nodeRecord->relationAnchorPoint; - $this->cascadeHierarchy( - $event->getContentStreamId(), - $dimensionSpacePoint, - $nodeRecord->relationAnchorPoint, - $affectedRelationAnchorPoints - ); - } + $this->cascadeHierarchy( + $event->getContentStreamId(), + $dimensionSpacePoint, + $nodeRecord->relationAnchorPoint, + $affectedRelationAnchorPoints + ); + } - // second step: remove orphaned nodes - $this->getDatabaseConnection()->executeStatement( - /** @lang PostgreSQL */ - ' - WITH deletedNodes AS ( - DELETE FROM ' . $this->tableNamePrefix . '_node n - WHERE n.relationanchorpoint IN ( - SELECT relationanchorpoint FROM ' . $this->tableNamePrefix . '_node - LEFT JOIN ' . $this->tableNamePrefix . '_hierarchyhyperrelation h - ON n.relationanchorpoint = ANY(h.childnodeanchors) - WHERE n.relationanchorpoint IN (:affectedRelationAnchorPoints) - AND h.contentstreamid IS NULL - ) - RETURNING relationanchorpoint + // second step: remove orphaned nodes + $this->getDatabaseConnection()->executeStatement( + /** @lang PostgreSQL */ + ' + WITH deletedNodes AS ( + DELETE FROM ' . $this->tableNamePrefix . '_node n + WHERE n.relationanchorpoint IN ( + SELECT relationanchorpoint FROM ' . $this->tableNamePrefix . '_node + LEFT JOIN ' . $this->tableNamePrefix . '_hierarchyhyperrelation h + ON n.relationanchorpoint = ANY(h.childnodeanchors) + WHERE n.relationanchorpoint IN (:affectedRelationAnchorPoints) + AND h.contentstreamid IS NULL ) - DELETE FROM ' . $this->tableNamePrefix . '_referencerelation r - WHERE sourcenodeanchor IN (SELECT relationanchorpoint FROM deletedNodes) - ', - [ - 'affectedRelationAnchorPoints' => $affectedRelationAnchorPoints - ], - [ - 'affectedRelationAnchorPoints' => Connection::PARAM_STR_ARRAY - ] - ); - }); + RETURNING relationanchorpoint + ) + DELETE FROM ' . $this->tableNamePrefix . '_referencerelation r + WHERE sourcenodeanchor IN (SELECT relationanchorpoint FROM deletedNodes) + ', + [ + 'affectedRelationAnchorPoints' => $affectedRelationAnchorPoints + ], + [ + 'affectedRelationAnchorPoints' => Connection::PARAM_STR_ARRAY + ] + ); } /** @@ -184,10 +182,5 @@ private function removeFromRestrictions( abstract protected function getProjectionHypergraph(): ProjectionHypergraph; - /** - * @throws \Throwable - */ - abstract protected function transactional(\Closure $operations): void; - abstract protected function getDatabaseConnection(): Connection; } diff --git a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/NodeRenaming.php b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/NodeRenaming.php index ecb405421ac..be697cf4419 100644 --- a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/NodeRenaming.php +++ b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/NodeRenaming.php @@ -33,30 +33,23 @@ trait NodeRenaming */ private function whenNodeAggregateNameWasChanged(NodeAggregateNameWasChanged $event): void { - $this->transactional(function () use ($event) { - foreach ( - $this->getProjectionHyperGraph()->findNodeRecordsForNodeAggregate( - $event->contentStreamId, - $event->nodeAggregateId - ) as $originNode - ) { - $this->copyOnWrite( - $event->contentStreamId, - $originNode, - function (NodeRecord $nodeRecord) use ($event) { - $nodeRecord->nodeName = $event->newNodeName; - } - ); - } - }); + foreach ( + $this->getProjectionHyperGraph()->findNodeRecordsForNodeAggregate( + $event->contentStreamId, + $event->nodeAggregateId + ) as $originNode + ) { + $this->copyOnWrite( + $event->contentStreamId, + $originNode, + function (NodeRecord $nodeRecord) use ($event) { + $nodeRecord->nodeName = $event->newNodeName; + } + ); + } } abstract protected function getProjectionHyperGraph(): ProjectionHypergraph; - /** - * @throws \Throwable - */ - abstract protected function transactional(\Closure $operations): void; - abstract protected function getDatabaseConnection(): Connection; } diff --git a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/NodeTypeChange.php b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/NodeTypeChange.php index 2015342883e..10a558cefc7 100644 --- a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/NodeTypeChange.php +++ b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/NodeTypeChange.php @@ -33,30 +33,23 @@ trait NodeTypeChange */ private function whenNodeAggregateTypeWasChanged(NodeAggregateTypeWasChanged $event): void { - $this->transactional(function () use ($event) { - foreach ( - $this->getProjectionHyperGraph()->findNodeRecordsForNodeAggregate( - $event->contentStreamId, - $event->nodeAggregateId - ) as $originNode - ) { - $this->copyOnWrite( - $event->contentStreamId, - $originNode, - function (NodeRecord $nodeRecord) use ($event) { - $nodeRecord->nodeTypeName = $event->newNodeTypeName; - } - ); - } - }); + foreach ( + $this->getProjectionHyperGraph()->findNodeRecordsForNodeAggregate( + $event->contentStreamId, + $event->nodeAggregateId + ) as $originNode + ) { + $this->copyOnWrite( + $event->contentStreamId, + $originNode, + function (NodeRecord $nodeRecord) use ($event) { + $nodeRecord->nodeTypeName = $event->newNodeTypeName; + } + ); + } } abstract protected function getProjectionHyperGraph(): ProjectionHypergraph; - /** - * @throws \Throwable - */ - abstract protected function transactional(\Closure $operations): void; - abstract protected function getDatabaseConnection(): Connection; } diff --git a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/NodeVariation.php b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/NodeVariation.php index a90e1c50b31..4969ab5688a 100644 --- a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/NodeVariation.php +++ b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/NodeVariation.php @@ -38,8 +38,6 @@ trait NodeVariation { abstract protected function getProjectionHyperGraph(): ProjectionHypergraph; - abstract protected function transactional(\Closure $operations): void; - abstract protected function getDatabaseConnection(): Connection; /** @@ -47,161 +45,155 @@ abstract protected function getDatabaseConnection(): Connection; */ private function whenNodeSpecializationVariantWasCreated(NodeSpecializationVariantWasCreated $event): void { - $this->transactional(function () use ($event) { - $sourceNode = $this->getProjectionHyperGraph()->findNodeRecordByOrigin( + $sourceNode = $this->getProjectionHyperGraph()->findNodeRecordByOrigin( + $event->contentStreamId, + $event->sourceOrigin, + $event->nodeAggregateId + ); + if (is_null($sourceNode)) { + throw EventCouldNotBeAppliedToContentGraph::becauseTheSourceNodeIsMissing((get_class($event))); + } + $specializedNode = $this->copyNodeToOriginDimensionSpacePoint( + $sourceNode, + $event->specializationOrigin + ); + + $oldCoveringNode = $this->projectionHypergraph->findNodeRecordByCoverage( + $event->contentStreamId, + $event->specializationOrigin->toDimensionSpacePoint(), + $event->nodeAggregateId + ); + if ($oldCoveringNode instanceof NodeRecord) { + $this->assignNewChildNodeToAffectedHierarchyRelations( $event->contentStreamId, - $event->sourceOrigin, - $event->nodeAggregateId + $oldCoveringNode->relationAnchorPoint, + $specializedNode->relationAnchorPoint, + $event->specializationSiblings->toDimensionSpacePointSet() ); - if (is_null($sourceNode)) { - throw EventCouldNotBeAppliedToContentGraph::becauseTheSourceNodeIsMissing((get_class($event))); - } - $specializedNode = $this->copyNodeToOriginDimensionSpacePoint( - $sourceNode, - $event->specializationOrigin + $this->assignNewParentNodeToAffectedHierarchyRelations( + $event->contentStreamId, + $oldCoveringNode->relationAnchorPoint, + $specializedNode->relationAnchorPoint, + $event->specializationSiblings->toDimensionSpacePointSet() ); - - $oldCoveringNode = $this->projectionHypergraph->findNodeRecordByCoverage( + } else { + // the dimension space point is not yet covered by the node aggregate, + // but it is known that the source's parent node aggregate does + $sourceParent = $this->projectionHypergraph->findParentNodeRecordByOrigin( $event->contentStreamId, - $event->specializationOrigin->toDimensionSpacePoint(), + $event->sourceOrigin, $event->nodeAggregateId ); - if ($oldCoveringNode instanceof NodeRecord) { - $this->assignNewChildNodeToAffectedHierarchyRelations( - $event->contentStreamId, - $oldCoveringNode->relationAnchorPoint, - $specializedNode->relationAnchorPoint, - $event->specializationSiblings->toDimensionSpacePointSet() + if (is_null($sourceParent)) { + throw EventCouldNotBeAppliedToContentGraph::becauseTheSourceParentNodeIsMissing( + (get_class($event)) ); - $this->assignNewParentNodeToAffectedHierarchyRelations( + } + foreach ($event->specializationSiblings->toDimensionSpacePointSet() as $specializedDimensionSpacePoint) { + $parentNode = $this->projectionHypergraph->findNodeRecordByCoverage( $event->contentStreamId, - $oldCoveringNode->relationAnchorPoint, - $specializedNode->relationAnchorPoint, - $event->specializationSiblings->toDimensionSpacePointSet() + $specializedDimensionSpacePoint, + $sourceParent->nodeAggregateId ); - } else { - // the dimension space point is not yet covered by the node aggregate, - // but it is known that the source's parent node aggregate does - $sourceParent = $this->projectionHypergraph->findParentNodeRecordByOrigin( + if (is_null($parentNode)) { + throw EventCouldNotBeAppliedToContentGraph::becauseTheTargetParentNodeIsMissing( + (get_class($event)) + ); + } + $parentRelation = $this->projectionHypergraph->findHierarchyHyperrelationRecordByParentNodeAnchor( $event->contentStreamId, - $event->sourceOrigin, - $event->nodeAggregateId + $specializedDimensionSpacePoint, + $parentNode->relationAnchorPoint ); - if (is_null($sourceParent)) { - throw EventCouldNotBeAppliedToContentGraph::becauseTheSourceParentNodeIsMissing( + if (is_null($parentRelation)) { + throw EventCouldNotBeAppliedToContentGraph::becauseTheIngoingSourceHierarchyRelationIsMissing( (get_class($event)) ); } - foreach ($event->specializationSiblings->toDimensionSpacePointSet() as $specializedDimensionSpacePoint) { - $parentNode = $this->projectionHypergraph->findNodeRecordByCoverage( - $event->contentStreamId, - $specializedDimensionSpacePoint, - $sourceParent->nodeAggregateId - ); - if (is_null($parentNode)) { - throw EventCouldNotBeAppliedToContentGraph::becauseTheTargetParentNodeIsMissing( - (get_class($event)) - ); - } - $parentRelation = $this->projectionHypergraph->findHierarchyHyperrelationRecordByParentNodeAnchor( - $event->contentStreamId, - $specializedDimensionSpacePoint, - $parentNode->relationAnchorPoint - ); - if (is_null($parentRelation)) { - throw EventCouldNotBeAppliedToContentGraph::becauseTheIngoingSourceHierarchyRelationIsMissing( - (get_class($event)) - ); - } - $parentRelation->addChildNodeAnchor( - $specializedNode->relationAnchorPoint, - null, - $this->getDatabaseConnection(), - $this->tableNamePrefix - ); - } + $parentRelation->addChildNodeAnchor( + $specializedNode->relationAnchorPoint, + null, + $this->getDatabaseConnection(), + $this->tableNamePrefix + ); } + } - $this->copyReferenceRelations( - $sourceNode->relationAnchorPoint, - $specializedNode->relationAnchorPoint - ); - }); + $this->copyReferenceRelations( + $sourceNode->relationAnchorPoint, + $specializedNode->relationAnchorPoint + ); } private function whenNodeGeneralizationVariantWasCreated(NodeGeneralizationVariantWasCreated $event): void { - $this->transactional(function () use ($event) { - $sourceNode = $this->getProjectionHyperGraph()->findNodeRecordByOrigin( - $event->contentStreamId, - $event->sourceOrigin, - $event->nodeAggregateId - ); - if (!$sourceNode) { - throw EventCouldNotBeAppliedToContentGraph::becauseTheSourceNodeIsMissing(get_class($event)); - } - $generalizedNode = $this->copyNodeToOriginDimensionSpacePoint( - $sourceNode, - $event->generalizationOrigin - ); + $sourceNode = $this->getProjectionHyperGraph()->findNodeRecordByOrigin( + $event->contentStreamId, + $event->sourceOrigin, + $event->nodeAggregateId + ); + if (!$sourceNode) { + throw EventCouldNotBeAppliedToContentGraph::becauseTheSourceNodeIsMissing(get_class($event)); + } + $generalizedNode = $this->copyNodeToOriginDimensionSpacePoint( + $sourceNode, + $event->generalizationOrigin + ); - $this->replaceNodeRelationAnchorPoint( - $event->contentStreamId, - $event->nodeAggregateId, - $event->variantSucceedingSiblings->toDimensionSpacePointSet(), - $generalizedNode->relationAnchorPoint - ); - $this->addMissingHierarchyRelations( - $event->contentStreamId, - $event->nodeAggregateId, - $event->sourceOrigin, - $generalizedNode->relationAnchorPoint, - $event->variantSucceedingSiblings->toDimensionSpacePointSet(), - get_class($event) - ); - $this->copyReferenceRelations( - $sourceNode->relationAnchorPoint, - $generalizedNode->relationAnchorPoint - ); - }); + $this->replaceNodeRelationAnchorPoint( + $event->contentStreamId, + $event->nodeAggregateId, + $event->variantSucceedingSiblings->toDimensionSpacePointSet(), + $generalizedNode->relationAnchorPoint + ); + $this->addMissingHierarchyRelations( + $event->contentStreamId, + $event->nodeAggregateId, + $event->sourceOrigin, + $generalizedNode->relationAnchorPoint, + $event->variantSucceedingSiblings->toDimensionSpacePointSet(), + get_class($event) + ); + $this->copyReferenceRelations( + $sourceNode->relationAnchorPoint, + $generalizedNode->relationAnchorPoint + ); } private function whenNodePeerVariantWasCreated(NodePeerVariantWasCreated $event): void { - $this->transactional(function () use ($event) { - $sourceNode = $this->getProjectionHyperGraph()->findNodeRecordByOrigin( - $event->contentStreamId, - $event->sourceOrigin, - $event->nodeAggregateId - ); - if (!$sourceNode) { - throw EventCouldNotBeAppliedToContentGraph::becauseTheSourceNodeIsMissing(get_class($event)); - } - $peerNode = $this->copyNodeToOriginDimensionSpacePoint( - $sourceNode, - $event->peerOrigin - ); + $sourceNode = $this->getProjectionHyperGraph()->findNodeRecordByOrigin( + $event->contentStreamId, + $event->sourceOrigin, + $event->nodeAggregateId + ); + if (!$sourceNode) { + throw EventCouldNotBeAppliedToContentGraph::becauseTheSourceNodeIsMissing(get_class($event)); + } + $peerNode = $this->copyNodeToOriginDimensionSpacePoint( + $sourceNode, + $event->peerOrigin + ); - $this->replaceNodeRelationAnchorPoint( - $event->contentStreamId, - $event->nodeAggregateId, - $event->peerSucceedingSiblings->toDimensionSpacePointSet(), - $peerNode->relationAnchorPoint - ); - $this->addMissingHierarchyRelations( - $event->contentStreamId, - $event->nodeAggregateId, - $event->sourceOrigin, - $peerNode->relationAnchorPoint, - $event->peerSucceedingSiblings->toDimensionSpacePointSet(), - get_class($event) - ); - $this->copyReferenceRelations( - $sourceNode->relationAnchorPoint, - $peerNode->relationAnchorPoint - ); - }); + $this->replaceNodeRelationAnchorPoint( + $event->contentStreamId, + $event->nodeAggregateId, + $event->peerSucceedingSiblings->toDimensionSpacePointSet(), + $peerNode->relationAnchorPoint + ); + $this->addMissingHierarchyRelations( + $event->contentStreamId, + $event->nodeAggregateId, + $event->sourceOrigin, + $peerNode->relationAnchorPoint, + $event->peerSucceedingSiblings->toDimensionSpacePointSet(), + get_class($event) + ); + $this->copyReferenceRelations( + $sourceNode->relationAnchorPoint, + $peerNode->relationAnchorPoint + ); } /** diff --git a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/SubtreeTagging.php b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/SubtreeTagging.php index 6ce6ddd541c..98a1bf96e45 100644 --- a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/SubtreeTagging.php +++ b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/SubtreeTagging.php @@ -32,27 +32,25 @@ trait SubtreeTagging */ private function whenSubtreeWasTagged(SubtreeWasTagged $event): void { - $this->transactional(function () use ($event) { - $descendantNodeAggregateIdsByAffectedDimensionSpacePoint - = $this->getProjectionHypergraph()->findDescendantNodeAggregateIds( - $event->contentStreamId, - $event->affectedDimensionSpacePoints, - $event->nodeAggregateId - ); + $descendantNodeAggregateIdsByAffectedDimensionSpacePoint + = $this->getProjectionHypergraph()->findDescendantNodeAggregateIds( + $event->contentStreamId, + $event->affectedDimensionSpacePoints, + $event->nodeAggregateId + ); - /** @codingStandardsIgnoreStart */ - foreach ($descendantNodeAggregateIdsByAffectedDimensionSpacePoint as $dimensionSpacePointHash => $descendantNodeAggregateIds) { - /** @codingStandardsIgnoreEnd */ - $restrictionRelation = new RestrictionHyperrelationRecord( - $event->contentStreamId, - $dimensionSpacePointHash, - $event->nodeAggregateId, - $descendantNodeAggregateIds - ); + /** @codingStandardsIgnoreStart */ + foreach ($descendantNodeAggregateIdsByAffectedDimensionSpacePoint as $dimensionSpacePointHash => $descendantNodeAggregateIds) { + /** @codingStandardsIgnoreEnd */ + $restrictionRelation = new RestrictionHyperrelationRecord( + $event->contentStreamId, + $dimensionSpacePointHash, + $event->nodeAggregateId, + $descendantNodeAggregateIds + ); - $restrictionRelation->addToDatabase($this->getDatabaseConnection(), $this->tableNamePrefix); - } - }); + $restrictionRelation->addToDatabase($this->getDatabaseConnection(), $this->tableNamePrefix); + } } /** @@ -60,24 +58,17 @@ private function whenSubtreeWasTagged(SubtreeWasTagged $event): void */ private function whenSubtreeWasUntagged(SubtreeWasUntagged $event): void { - $this->transactional(function () use ($event) { - $restrictionRelations = $this->getProjectionHypergraph()->findOutgoingRestrictionRelations( - $event->contentStreamId, - $event->affectedDimensionSpacePoints, - $event->nodeAggregateId, - ); - foreach ($restrictionRelations as $restrictionRelation) { - $restrictionRelation->removeFromDatabase($this->getDatabaseConnection(), $this->tableNamePrefix); - } - }); + $restrictionRelations = $this->getProjectionHypergraph()->findOutgoingRestrictionRelations( + $event->contentStreamId, + $event->affectedDimensionSpacePoints, + $event->nodeAggregateId, + ); + foreach ($restrictionRelations as $restrictionRelation) { + $restrictionRelation->removeFromDatabase($this->getDatabaseConnection(), $this->tableNamePrefix); + } } abstract protected function getProjectionHypergraph(): ProjectionHypergraph; - /** - * @throws \Throwable - */ - abstract protected function transactional(\Closure $operations): void; - abstract protected function getDatabaseConnection(): Connection; } diff --git a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/HypergraphProjection.php b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/HypergraphProjection.php index 114df60ed58..68d5e6b103c 100644 --- a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/HypergraphProjection.php +++ b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/HypergraphProjection.php @@ -52,6 +52,9 @@ use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId; use Neos\EventStore\Model\Event\SequenceNumber; use Neos\EventStore\Model\EventEnvelope; +use React\Promise\PromiseInterface; + +use function React\Promise\resolve; /** * The alternate reality-aware hypergraph projector for the PostgreSQL backend via Doctrine DBAL @@ -153,7 +156,7 @@ private function determineRequiredSqlStatements(): array return DbalSchemaDiff::determineRequiredSqlStatements($connection, $schema); } - public function reset(): void + public function reset(): PromiseInterface { $this->truncateDatabaseTables(); @@ -164,6 +167,7 @@ public function reset(): void //foreach ($contentGraph->getSubgraphs() as $subgraph) { // $subgraph->inMemoryCache->enable(); //} + return resolve(null); } private function truncateDatabaseTables(): void @@ -175,40 +179,7 @@ private function truncateDatabaseTables(): void $connection->executeQuery('TRUNCATE table ' . $this->tableNamePrefix . '_restrictionhyperrelation'); } - public function canHandle(EventInterface $event): bool - { - return in_array($event::class, [ - // ContentStreamForking - ContentStreamWasForked::class, - // NodeCreation - RootNodeAggregateWithNodeWasCreated::class, - NodeAggregateWithNodeWasCreated::class, - // SubtreeTagging - SubtreeWasTagged::class, - SubtreeWasUntagged::class, - // NodeModification - NodePropertiesWereSet::class, - // NodeReferencing - NodeReferencesWereSet::class, - // NodeRemoval - NodeAggregateWasRemoved::class, - // NodeRenaming - NodeAggregateNameWasChanged::class, - // NodeTypeChange - NodeAggregateTypeWasChanged::class, - // NodeVariation - NodeSpecializationVariantWasCreated::class, - NodeGeneralizationVariantWasCreated::class, - NodePeerVariantWasCreated::class, - // TODO: not yet supported: - //ContentStreamWasRemoved::class, - //DimensionSpacePointWasMoved::class, - //DimensionShineThroughWasAdded::class, - //NodeAggregateWasMoved::class, - ]); - } - - public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void + public function apply(EventInterface $event, EventEnvelope $eventEnvelope): PromiseInterface { match ($event::class) { // ContentStreamForking @@ -233,8 +204,9 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void NodeSpecializationVariantWasCreated::class => $this->whenNodeSpecializationVariantWasCreated($event), NodeGeneralizationVariantWasCreated::class => $this->whenNodeGeneralizationVariantWasCreated($event), NodePeerVariantWasCreated::class => $this->whenNodePeerVariantWasCreated($event), - default => throw new \InvalidArgumentException(sprintf('Unsupported event %s', get_debug_type($event))), + default => null, }; + return resolve(null); } public function getCheckpointStorage(): DbalCheckpointStorage @@ -261,14 +233,6 @@ protected function getProjectionHypergraph(): ProjectionHypergraph return $this->projectionHypergraph; } - /** - * @throws \Throwable - */ - protected function transactional(\Closure $operations): void - { - $this->getDatabaseConnection()->transactional($operations); - } - protected function getDatabaseConnection(): Connection { return $this->databaseClient->getConnection(); diff --git a/Neos.ContentRepository.BehavioralTests/Classes/Command/PerformanceMeasurementCommandController.php b/Neos.ContentRepository.BehavioralTests/Classes/Command/PerformanceMeasurementCommandController.php index f96c3d6fd06..a34583a39e7 100644 --- a/Neos.ContentRepository.BehavioralTests/Classes/Command/PerformanceMeasurementCommandController.php +++ b/Neos.ContentRepository.BehavioralTests/Classes/Command/PerformanceMeasurementCommandController.php @@ -16,7 +16,6 @@ use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId; use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry; -use Neos\ContentRepositoryRegistry\Factory\ProjectionCatchUpTrigger\CatchUpTriggerWithSynchronousOption; use Neos\Flow\Cli\CommandController; use Neos\Neos\Fusion\Cache\GraphProjectorCatchUpHookForCacheFlushing; @@ -47,10 +46,8 @@ public function preparePerformanceTestCommand(int $nodesPerLevel, int $levels): { $this->performanceMeasurementService->removeEverything(); $this->outputLine("All removed. Starting to fill."); - CatchUpTriggerWithSynchronousOption::synchronously( - fn() => GraphProjectorCatchUpHookForCacheFlushing::disabled( - fn() => $this->performanceMeasurementService->createNodesForPerformanceTest($nodesPerLevel, $levels) - ) + GraphProjectorCatchUpHookForCacheFlushing::disabled( + fn() => $this->performanceMeasurementService->createNodesForPerformanceTest($nodesPerLevel, $levels) ); } @@ -62,9 +59,7 @@ public function preparePerformanceTestCommand(int $nodesPerLevel, int $levels): public function testPerformanceCommand(): void { $time = microtime(true); - CatchUpTriggerWithSynchronousOption::synchronously( - fn() => $this->performanceMeasurementService->forkContentStream() - ); + $this->performanceMeasurementService->forkContentStream(); $timeElapsed = microtime(true) - $time; $this->outputLine('Time: ' . $timeElapsed); diff --git a/Neos.ContentRepository.BehavioralTests/Classes/ProjectionRaceConditionTester/RaceTrackerCatchUpHook.php b/Neos.ContentRepository.BehavioralTests/Classes/ProjectionRaceConditionTester/RaceTrackerCatchUpHook.php index 3309f99d17d..97ce6721535 100644 --- a/Neos.ContentRepository.BehavioralTests/Classes/ProjectionRaceConditionTester/RaceTrackerCatchUpHook.php +++ b/Neos.ContentRepository.BehavioralTests/Classes/ProjectionRaceConditionTester/RaceTrackerCatchUpHook.php @@ -18,14 +18,13 @@ use Neos\ContentRepository\BehavioralTests\ProjectionRaceConditionTester\Dto\TraceEntryType; use Neos\ContentRepository\Core\EventStore\EventInterface; use Neos\ContentRepository\Core\Projection\CatchUpHookInterface; -use Neos\ContentRepositoryRegistry\Factory\ProjectionCatchUpTrigger\SubprocessProjectionCatchUpTrigger; use Neos\EventStore\Model\EventEnvelope; use Neos\Flow\Annotations as Flow; /** * We had some race conditions in projections, where {@see \Neos\ContentRepository\Core\Infrastructure\DbalCheckpointStorage} was not working properly. * We saw some non-deterministic, random errors when running the tests - unluckily only on Linux, not on OSX: - * On OSX, forking a new subprocess in {@see SubprocessProjectionCatchUpTrigger} is *WAY* slower than in Linux; + * On OSX, forking a new subprocess is *WAY* slower than in Linux; * and thus the race conditions which appears if two projector instances of the same class run concurrently * won't happen (or are way less likely). * diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Bootstrap/FeatureContext.php b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Bootstrap/FeatureContext.php index 44b677827b3..0aed9d47cc7 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Bootstrap/FeatureContext.php +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Bootstrap/FeatureContext.php @@ -60,7 +60,6 @@ public function __construct() self::bootstrapFlow(); $this->dbalClient = $this->getObject(DbalClientInterface::class); - $this->setupCRTestSuiteTrait(); $this->setUpInterleavingLogger(); $this->contentRepositoryRegistry = $this->getObject(ContentRepositoryRegistry::class); } diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/01-RootNodeCreation/01-CreateRootNodeAggregateWithNode_ConstraintChecks.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/01-RootNodeCreation/01-CreateRootNodeAggregateWithNode_ConstraintChecks.feature index b1ff005357c..893ea06044a 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/01-RootNodeCreation/01-CreateRootNodeAggregateWithNode_ConstraintChecks.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/01-RootNodeCreation/01-CreateRootNodeAggregateWithNode_ConstraintChecks.feature @@ -26,13 +26,11 @@ Feature: Create a root node aggregate | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date Scenario: Try to create a root node aggregate in a workspace that currently does not exist: When the command CreateRootNodeAggregateWithNode is executed with payload and exceptions are caught: diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/01-RootNodeCreation/02-CreateRootNodeAggregateWithNode_WithoutDimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/01-RootNodeCreation/02-CreateRootNodeAggregateWithNode_WithoutDimensions.feature index 9f86bc72a56..7beddd9271c 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/01-RootNodeCreation/02-CreateRootNodeAggregateWithNode_WithoutDimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/01-RootNodeCreation/02-CreateRootNodeAggregateWithNode_WithoutDimensions.feature @@ -24,7 +24,6 @@ Feature: Create a root node aggregate | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" Scenario: Create the initial root node aggregate using valid payload without dimensions @@ -41,8 +40,6 @@ Feature: Create a root node aggregate | nodeTypeName | "Neos.ContentRepository:Root" | | coveredDimensionSpacePoints | [[]] | | nodeAggregateClassification | "root" | - - When the graph projection is fully up to date Then I expect the node aggregate "lady-eleonode-rootford" to exist And I expect this node aggregate to be classified as "root" And I expect this node aggregate to be of type "Neos.ContentRepository:Root" @@ -75,7 +72,6 @@ Feature: Create a root node aggregate | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date When the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | @@ -90,8 +86,6 @@ Feature: Create a root node aggregate | nodeTypeName | "Neos.ContentRepository:AnotherRoot" | | coveredDimensionSpacePoints | [[]] | | nodeAggregateClassification | "root" | - - When the graph projection is fully up to date Then I expect the node aggregate "lady-eleonode-rootford" to exist And I expect this node aggregate to have no parent node aggregates And I expect this node aggregate to have no child node aggregates diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/01-RootNodeCreation/03-CreateRootNodeAggregateWithNodeAndTetheredChildren_WithoutDimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/01-RootNodeCreation/03-CreateRootNodeAggregateWithNodeAndTetheredChildren_WithoutDimensions.feature index 163142ec3dd..21513bd8f4e 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/01-RootNodeCreation/03-CreateRootNodeAggregateWithNodeAndTetheredChildren_WithoutDimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/01-RootNodeCreation/03-CreateRootNodeAggregateWithNodeAndTetheredChildren_WithoutDimensions.feature @@ -37,7 +37,6 @@ Feature: Create a root node aggregate with tethered children | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {} And I am user identified by "initiating-user-identifier" @@ -47,7 +46,6 @@ Feature: Create a root node aggregate with tethered children | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository.Testing:RootWithTetheredChildNodes" | | tetheredDescendantNodeAggregateIds | {"child-node": "nody-mc-nodeface", "child-node/grandchild-node": "nodimus-prime"} | - And the graph projection is fully up to date Then I expect exactly 4 events to be published on stream "ContentStream:cs-identifier" And event at index 1 is of type "RootNodeAggregateWithNodeWasCreated" with payload: diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/01-RootNodeCreation/04-CreateRootNodeAggregateWithNodeAndTetheredChildren_WithDimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/01-RootNodeCreation/04-CreateRootNodeAggregateWithNodeAndTetheredChildren_WithDimensions.feature index 2f4455862d8..1d8dd432a33 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/01-RootNodeCreation/04-CreateRootNodeAggregateWithNodeAndTetheredChildren_WithDimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/01-RootNodeCreation/04-CreateRootNodeAggregateWithNodeAndTetheredChildren_WithDimensions.feature @@ -39,7 +39,6 @@ Feature: Create a root node aggregate with tethered children | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" And I am user identified by "initiating-user-identifier" @@ -49,7 +48,6 @@ Feature: Create a root node aggregate with tethered children | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository.Testing:RootWithTetheredChildNodes" | | tetheredDescendantNodeAggregateIds | {"child-node": "nody-mc-nodeface", "child-node/grandchild-node": "nodimus-prime"} | - And the graph projection is fully up to date Then I expect exactly 6 events to be published on stream "ContentStream:cs-identifier" And event at index 1 is of type "RootNodeAggregateWithNodeWasCreated" with payload: diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/01-RootNodeCreation/05-CreateRootNodeAggregateWithNode_WithDimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/01-RootNodeCreation/05-CreateRootNodeAggregateWithNode_WithDimensions.feature index af98e698f3f..b0b91fba47a 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/01-RootNodeCreation/05-CreateRootNodeAggregateWithNode_WithDimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/01-RootNodeCreation/05-CreateRootNodeAggregateWithNode_WithDimensions.feature @@ -25,7 +25,6 @@ Feature: Create a root node aggregate | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" Scenario: Create the initial root node aggregate using valid payload with dimensions @@ -44,8 +43,6 @@ Feature: Create a root node aggregate | nodeAggregateClassification | "root" | And event metadata at index 1 is: | Key | Expected | - - When the graph projection is fully up to date Then I expect the node aggregate "lady-eleonode-rootford" to exist And I expect this node aggregate to be classified as "root" And I expect this node aggregate to be of type "Neos.ContentRepository:Root" @@ -89,7 +86,6 @@ Feature: Create a root node aggregate | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date When the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | @@ -104,8 +100,6 @@ Feature: Create a root node aggregate | nodeTypeName | "Neos.ContentRepository:AnotherRoot" | | coveredDimensionSpacePoints | [{"language":"mul"},{"language":"de"},{"language":"en"},{"language":"gsw"}] | | nodeAggregateClassification | "root" | - - When the graph projection is fully up to date Then I expect the node aggregate "lady-eleonode-rootford" to exist And I expect this node aggregate to have no parent node aggregates And I expect this node aggregate to have no child node aggregates diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/02-NodeCreation/01-CreateNodeAggregateWithNode_ConstraintChecks.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/02-NodeCreation/01-CreateNodeAggregateWithNode_ConstraintChecks.feature index a14305214da..51b9f80890e 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/02-NodeCreation/01-CreateNodeAggregateWithNode_ConstraintChecks.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/02-NodeCreation/01-CreateNodeAggregateWithNode_ConstraintChecks.feature @@ -37,13 +37,11 @@ Feature: Create node aggregate with node | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date Scenario: Try to create a node aggregate in a workspace that currently does not exist: When the command CreateNodeAggregateWithNode is executed with payload and exceptions are caught: @@ -144,7 +142,6 @@ Feature: Create node aggregate with node | nodeTypeName | "Neos.ContentRepository.Testing:Node" | | parentNodeAggregateId | "lady-eleonode-rootford" | | nodeName | "document" | - And the graph projection is fully up to date When the command CreateNodeAggregateWithNode is executed with payload and exceptions are caught: | Key | Value | | nodeAggregateId | "nody-mc-nodeface" | diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/02-NodeCreation/02-CreateNodeAggregateWithNode_ConstraintChecks_WithDimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/02-NodeCreation/02-CreateNodeAggregateWithNode_ConstraintChecks_WithDimensions.feature index 66512883875..ab860f3b309 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/02-NodeCreation/02-CreateNodeAggregateWithNode_ConstraintChecks_WithDimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/02-NodeCreation/02-CreateNodeAggregateWithNode_ConstraintChecks_WithDimensions.feature @@ -39,14 +39,12 @@ Feature: Create node aggregate with node | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" And I am in dimension space point {} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date Scenario: Try to create a node aggregate in an origin dimension space point the parent node does not cover: When the command CreateNodeAggregateWithNode is executed with payload: @@ -55,7 +53,6 @@ Feature: Create node aggregate with node | nodeTypeName | "Neos.ContentRepository.Testing:Node" | | parentNodeAggregateId | "lady-eleonode-rootford" | | originDimensionSpacePoint | {"language":"gsw"} | - And the graph projection is fully up to date And the command CreateNodeAggregateWithNode is executed with payload and exceptions are caught: | Key | Value | | nodeAggregateId | "nody-mc-nodeface" | diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/02-NodeCreation/03-CreateNodeAggregateWithNode_WithoutDimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/02-NodeCreation/03-CreateNodeAggregateWithNode_WithoutDimensions.feature index 4bbca7c61d7..22bcf71759c 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/02-NodeCreation/03-CreateNodeAggregateWithNode_WithoutDimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/02-NodeCreation/03-CreateNodeAggregateWithNode_WithoutDimensions.feature @@ -29,7 +29,6 @@ Feature: Create node aggregate with node | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" And I am in dimension space point {} And I am user identified by "initiating-user-identifier" @@ -37,7 +36,6 @@ Feature: Create node aggregate with node | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date When the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | nodeName | parentNodeAggregateId | nodeTypeName | initialPropertyValues | @@ -200,7 +198,6 @@ Feature: Create node aggregate with node | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" And I am in dimension space point {} And I am user identified by "initiating-user-identifier" @@ -208,7 +205,6 @@ Feature: Create node aggregate with node | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date Given the command CreateNodeAggregateWithNodeAndSerializedProperties is executed with payload: | Key | Value | @@ -217,7 +213,6 @@ Feature: Create node aggregate with node | originDimensionSpacePoint | {} | | parentNodeAggregateId | "lady-eleonode-rootford" | | nodeName | "node" | - And the graph projection is fully up to date And the command CreateNodeAggregateWithNodeAndSerializedProperties is executed with payload: | Key | Value | | nodeAggregateId | "sir-nodeward-nodington-iii" | @@ -239,8 +234,6 @@ Feature: Create node aggregate with node | nodeName | "esquire" | | initialPropertyValues | [] | | nodeAggregateClassification | "regular" | - - When the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {} And I expect node aggregate identifier "sir-nodeward-nodington-iii" and node path "esquire" to lead to node cs-identifier;sir-nodeward-nodington-iii;{} And I expect this node to be a child of node cs-identifier;lady-eleonode-rootford;{} @@ -284,7 +277,6 @@ Feature: Create node aggregate with node | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" And I am in dimension space point {} And I am user identified by "initiating-user-identifier" @@ -292,7 +284,6 @@ Feature: Create node aggregate with node | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date When the command CreateNodeAggregateWithNodeAndSerializedProperties is executed with payload: | Key | Value | @@ -302,7 +293,6 @@ Feature: Create node aggregate with node | parentNodeAggregateId | "lady-eleonode-rootford" | | nodeName | "node" | | tetheredDescendantNodeAggregateIds | {"child-node": "nody-mc-nodeface", "child-node/grandchild-node": "nodimus-prime"} | - And the graph projection is fully up to date Then I expect exactly 5 events to be published on stream "ContentStream:cs-identifier" And event at index 2 is of type "NodeAggregateWithNodeWasCreated" with payload: @@ -468,7 +458,6 @@ Feature: Create node aggregate with node | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" And I am in dimension space point {} And I am user identified by "initiating-user-identifier" @@ -476,7 +465,6 @@ Feature: Create node aggregate with node | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date When the command CreateNodeAggregateWithNodeAndSerializedProperties is executed with payload: | Key | Value | @@ -486,7 +474,6 @@ Feature: Create node aggregate with node | parentNodeAggregateId | "lady-eleonode-rootford" | | nodeName | "node" | | tetheredDescendantNodeAggregateIds | {"invalidcasedname": "nody-mc-nodeface", "invalidcharactors": "lord-from-nodding-hill"} | - And the graph projection is fully up to date And I expect the node aggregate "lady-eleonode-rootford" to exist And I expect this node aggregate to be classified as "root" diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/02-NodeCreation/04-CreateNodeAggregateWithNode_WithDimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/02-NodeCreation/04-CreateNodeAggregateWithNode_WithDimensions.feature index 96d4734ebce..0566fbdd813 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/02-NodeCreation/04-CreateNodeAggregateWithNode_WithDimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/02-NodeCreation/04-CreateNodeAggregateWithNode_WithDimensions.feature @@ -29,13 +29,11 @@ Feature: Create node aggregate with node | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date Scenario: Create node aggregate with initial node with content dimensions When the following CreateNodeAggregateWithNode commands are executed: diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/02-NodeCreation/05-CreateNodeAggregateWithNode_ComplexDefaultAndInitialProperties.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/02-NodeCreation/05-CreateNodeAggregateWithNode_ComplexDefaultAndInitialProperties.feature index 22f043d0590..1dda7083fde 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/02-NodeCreation/05-CreateNodeAggregateWithNode_ComplexDefaultAndInitialProperties.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/02-NodeCreation/05-CreateNodeAggregateWithNode_ComplexDefaultAndInitialProperties.feature @@ -54,14 +54,12 @@ Feature: Create a node aggregate with complex default values | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" And I am in dimension space point {} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date Scenario: Create a node aggregate with complex default values When the command CreateNodeAggregateWithNode is executed with payload: @@ -69,7 +67,6 @@ Feature: Create a node aggregate with complex default values | nodeAggregateId | "nody-mc-nodeface" | | nodeTypeName | "Neos.ContentRepository.Testing:Node" | | parentNodeAggregateId | "lady-eleonode-rootford" | - And the graph projection is fully up to date Then I expect a node identified by cs-identifier;nody-mc-nodeface;{} to exist in the content graph And I expect this node to have the following serialized properties: @@ -102,7 +99,6 @@ Feature: Create a node aggregate with complex default values | nodeTypeName | "Neos.ContentRepository.Testing:Node" | | parentNodeAggregateId | "lady-eleonode-rootford" | | initialPropertyValues | {"dayOfWeek":"DayOfWeek:https://schema.org/Friday","postalAddress":"PostalAddress:anotherDummy", "date":"Date:2021-03-13T17:33:17+00:00", "uri":"URI:https://www.neos.io", "price":"PriceSpecification:anotherDummy"} | - And the graph projection is fully up to date Then I expect a node identified by cs-identifier;nody-mc-nodeface;{} to exist in the content graph And I expect this node to have the following properties: | Key | Value | diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/02-NodeCreation/06-CreateNodeAggregateWithNode_NodeTypeConstraintChecks.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/02-NodeCreation/06-CreateNodeAggregateWithNode_NodeTypeConstraintChecks.feature index 49a1f36fe45..96f9bb8497e 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/02-NodeCreation/06-CreateNodeAggregateWithNode_NodeTypeConstraintChecks.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/02-NodeCreation/06-CreateNodeAggregateWithNode_NodeTypeConstraintChecks.feature @@ -40,14 +40,12 @@ Feature: Create node aggregate with node | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in content stream "cs-identifier" And I am in dimension space point {} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date # Direct allowance via grandchild NodeType constraints overrule deny all on NodeType # issue https://github.com/neos/neos-development-collection/issues/4351 @@ -58,7 +56,6 @@ Feature: Create node aggregate with node | nodeTypeName | "Neos.ContentRepository.Testing.TetheredCollection" | | parentNodeAggregateId | "lady-eleonode-rootford" | | tetheredDescendantNodeAggregateIds | { "collection": "collection-node-id"} | - And the graph projection is fully up to date Then I expect the node aggregate "sir-david-nodenborough" to exist Then I expect the node aggregate "collection-node-id" to exist # TetheredCollection @@ -70,7 +67,6 @@ Feature: Create node aggregate with node | nodeAggregateId | "nody-mc-nodeface" | | nodeTypeName | "Neos.ContentRepository.Testing:Node" | | parentNodeAggregateId | "collection-node-id" | - And the graph projection is fully up to date Then I expect the node aggregate "nody-mc-nodeface" to exist # allowed via grant parent node constraints: PrettyNode @@ -79,7 +75,6 @@ Feature: Create node aggregate with node | nodeAggregateId | "pretty-node" | | nodeTypeName | "Neos.ContentRepository.Testing:PrettyNode" | | parentNodeAggregateId | "collection-node-id" | - And the graph projection is fully up to date Then I expect the node aggregate "pretty-node" to exist # disallowed via grant parent node constraints: UglyNode @@ -96,13 +91,11 @@ Feature: Create node aggregate with node | nodeAggregateId | "sir-david-nodenborough" | | nodeTypeName | "Neos.ContentRepository.Testing:Node" | | parentNodeAggregateId | "lady-eleonode-rootford" | - And the graph projection is fully up to date When the command CreateNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "collection-node-id" | | nodeTypeName | "Neos.ContentRepository.Testing:RestrictedCollection" | | parentNodeAggregateId | "sir-david-nodenborough" | - And the graph projection is fully up to date Then I expect the node aggregate "sir-david-nodenborough" to exist Then I expect the node aggregate "collection-node-id" to exist # Node @@ -114,7 +107,6 @@ Feature: Create node aggregate with node | nodeAggregateId | "pretty-node" | | nodeTypeName | "Neos.ContentRepository.Testing:PrettyNode" | | parentNodeAggregateId | "collection-node-id" | - And the graph projection is fully up to date Then I expect the node aggregate "pretty-node" to exist # disallowed via grant parent node constraints: UglyNode diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/03-NodeVariation/01-CreateNodeVariant_ConstraintChecks.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/03-NodeVariation/01-CreateNodeVariant_ConstraintChecks.feature index d4d2be10e79..8199a74c749 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/03-NodeVariation/01-CreateNodeVariant_ConstraintChecks.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/03-NodeVariation/01-CreateNodeVariant_ConstraintChecks.feature @@ -25,13 +25,11 @@ Feature: Create node variant | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"market":"DE", "language":"gsw"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date # We have to add another node since root nodes have no dimension space points and thus cannot be varied # Node /document And the following CreateNodeAggregateWithNode commands are executed: diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/03-NodeVariation/02-CreateNodeSpecializationVariant.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/03-NodeVariation/02-CreateNodeSpecializationVariant.feature index 38734f8514a..19a57f6a217 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/03-NodeVariation/02-CreateNodeSpecializationVariant.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/03-NodeVariation/02-CreateNodeSpecializationVariant.feature @@ -29,13 +29,11 @@ Feature: Create node specialization | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"example":"source"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | nodeName | parentNodeAggregateId | succeedingSiblingNodeAggregateId | nodeTypeName | tetheredDescendantNodeAggregateIds | @@ -90,8 +88,6 @@ Feature: Create node specialization | sourceOrigin | {"example":"source"} | | specializationOrigin | {"example":"spec"} | | specializationSiblings | [{"dimensionSpacePoint":{"example":"spec"},"nodeAggregateId":null},{"dimensionSpacePoint":{"example":"leafSpec"},"nodeAggregateId":null}] | - - When the graph projection is fully up to date Then I expect the graph projection to consist of exactly 12 nodes And I expect a node identified by cs-identifier;lady-eleonode-rootford;{} to exist in the content graph And I expect a node identified by cs-identifier;nody-mc-nodeface;{"example":"source"} to exist in the content graph @@ -288,7 +284,6 @@ Feature: Create node specialization | nodeAggregateId | "nody-mc-nodeface" | | sourceOrigin | {"example":"source"} | | targetOrigin | {"example":"leafSpec"} | - And the graph projection is fully up to date When the command CreateNodeVariant is executed with payload: | Key | Value | | nodeAggregateId | "nody-mc-nodeface" | @@ -316,8 +311,6 @@ Feature: Create node specialization | sourceOrigin | {"example":"source"} | | specializationOrigin | {"example":"spec"} | | specializationSiblings | [{"dimensionSpacePoint":{"example":"spec"},"nodeAggregateId":null}] | - - When the graph projection is fully up to date Then I expect the graph projection to consist of exactly 15 nodes And I expect a node identified by cs-identifier;lady-eleonode-rootford;{} to exist in the content graph And I expect a node identified by cs-identifier;nody-mc-nodeface;{"example":"source"} to exist in the content graph diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/03-NodeVariation/03-CreateNodeGeneralizationVariant.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/03-NodeVariation/03-CreateNodeGeneralizationVariant.feature index 55bddb932f0..2c42bc955d1 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/03-NodeVariation/03-CreateNodeGeneralizationVariant.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/03-NodeVariation/03-CreateNodeGeneralizationVariant.feature @@ -29,13 +29,11 @@ Feature: Create node generalization | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"example":"source"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | originDimensionSpacePoint | nodeName | parentNodeAggregateId | succeedingSiblingNodeAggregateId | nodeTypeName | tetheredDescendantNodeAggregateIds | # We have to add another node since root nodes have no origin dimension space points and thus cannot be varied. @@ -56,13 +54,11 @@ Feature: Create node generalization | nodeAggregateId | "nody-mc-nodeface" | | sourceOrigin | {"example":"source"} | | targetOrigin | {"example":"general"} | - And the graph projection is fully up to date And the command CreateNodeVariant is executed with payload: | Key | Value | | nodeAggregateId | "elder-mc-nodeface" | | sourceOrigin | {"example":"source"} | | targetOrigin | {"example":"general"} | - And the graph projection is fully up to date And the command CreateNodeVariant is executed with payload: | Key | Value | | nodeAggregateId | "youngest-mc-nodeface" | @@ -105,8 +101,6 @@ Feature: Create node generalization | sourceOrigin | {"example":"source"} | | generalizationOrigin | {"example":"general"} | | variantSucceedingSiblings | [{"dimensionSpacePoint":{"example":"general"},"nodeAggregateId":null},{"dimensionSpacePoint":{"example":"specB"},"nodeAggregateId":null}] | - - When the graph projection is fully up to date Then I expect the graph projection to consist of exactly 14 nodes And I expect a node identified by cs-identifier;lady-eleonode-rootford;{} to exist in the content graph And I expect a node identified by cs-identifier;eldest-mc-nodeface;{"example":"general"} to exist in the content graph @@ -370,7 +364,6 @@ Feature: Create node generalization | nodeAggregateId | "nody-mc-nodeface" | | sourceOrigin | {"example":"source"} | | targetOrigin | {"example":"specB"} | - And the graph projection is fully up to date When the command CreateNodeVariant is executed with payload: | Key | Value | @@ -420,8 +413,6 @@ Feature: Create node generalization | sourceOrigin | {"example":"source"} | | generalizationOrigin | {"example":"general"} | | variantSucceedingSiblings | [{"dimensionSpacePoint":{"example":"general"},"nodeAggregateId":null}] | - - When the graph projection is fully up to date Then I expect the graph projection to consist of exactly 15 nodes And I expect a node identified by cs-identifier;lady-eleonode-rootford;{} to exist in the content graph And I expect a node identified by cs-identifier;eldest-mc-nodeface;{"example":"general"} to exist in the content graph @@ -556,7 +547,6 @@ Feature: Create node generalization | nodeAggregateId | "nody-mc-nodeface" | | sourceOrigin | {"example":"source"} | | targetOrigin | {"example":"general"} | - And the graph projection is fully up to date When the command CreateNodeVariant is executed with payload: | Key | Value | @@ -606,8 +596,6 @@ Feature: Create node generalization | sourceOrigin | {"example":"source"} | | peerOrigin | {"example":"specB"} | | peerSucceedingSiblings | [{"dimensionSpacePoint":{"example":"specB"},"nodeAggregateId":null}] | - - When the graph projection is fully up to date Then I expect the graph projection to consist of exactly 15 nodes And I expect a node identified by cs-identifier;lady-eleonode-rootford;{} to exist in the content graph And I expect a node identified by cs-identifier;eldest-mc-nodeface;{"example":"general"} to exist in the content graph @@ -742,7 +730,6 @@ Feature: Create node generalization | nodeAggregateId | "nody-mc-nodeface" | | sourceOrigin | {"example":"source"} | | targetOrigin | {"example":"rootGeneral"} | - And the graph projection is fully up to date When the command CreateNodeVariant is executed with payload: | Key | Value | @@ -792,8 +779,6 @@ Feature: Create node generalization | sourceOrigin | {"example":"source"} | | generalizationOrigin | {"example":"general"} | | variantSucceedingSiblings | [{"dimensionSpacePoint":{"example":"general"},"nodeAggregateId":null},{"dimensionSpacePoint":{"example":"specB"},"nodeAggregateId":null}] | - - When the graph projection is fully up to date Then I expect the graph projection to consist of exactly 15 nodes And I expect a node identified by cs-identifier;lady-eleonode-rootford;{} to exist in the content graph And I expect a node identified by cs-identifier;eldest-mc-nodeface;{"example":"general"} to exist in the content graph diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/03-NodeVariation/04-CreateNodePeerVariant.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/03-NodeVariation/04-CreateNodePeerVariant.feature index 2a3ef7c7f8f..a9fe1f831fd 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/03-NodeVariation/04-CreateNodePeerVariant.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/03-NodeVariation/04-CreateNodePeerVariant.feature @@ -29,13 +29,11 @@ Feature: Create node peer variant | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"example":"source"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | originDimensionSpacePoint | nodeName | parentNodeAggregateId | succeedingSiblingNodeAggregateId | nodeTypeName | tetheredDescendantNodeAggregateIds | # We have to add another node since root nodes have no origin dimension space points and thus cannot be varied. @@ -55,13 +53,11 @@ Feature: Create node peer variant | nodeAggregateId | "nody-mc-nodeface" | | sourceOrigin | {"example":"source"} | | targetOrigin | {"example":"peer"} | - And the graph projection is fully up to date And the command CreateNodeVariant is executed with payload: | Key | Value | | nodeAggregateId | "elder-mc-nodeface" | | sourceOrigin | {"example":"source"} | | targetOrigin | {"example":"peer"} | - And the graph projection is fully up to date # Complete the sibling set with a node in the target DSP between the middle and last node And the command CreateNodeAggregateWithNode is executed with payload: | Key | Value | @@ -70,7 +66,6 @@ Feature: Create node peer variant | parentNodeAggregateId | "lady-eleonode-rootford" | | originDimensionSpacePoint | {"example":"peer"} | | nodeName | "younger-document" | - And the graph projection is fully up to date And the command CreateNodeVariant is executed with payload: | Key | Value | | nodeAggregateId | "youngest-mc-nodeface" | @@ -114,8 +109,6 @@ Feature: Create node peer variant | sourceOrigin | {"example":"source"} | | peerOrigin | {"example":"peer"} | | peerSucceedingSiblings | [{"dimensionSpacePoint":{"example":"peer"},"nodeAggregateId":null},{"dimensionSpacePoint":{"example":"peerSpec"},"nodeAggregateId":null}] | - - When the graph projection is fully up to date Then I expect the graph projection to consist of exactly 14 nodes And I expect a node identified by cs-identifier;lady-eleonode-rootford;{} to exist in the content graph And I expect a node identified by cs-identifier;nody-mc-nodeface;{"example":"source"} to exist in the content graph @@ -342,7 +335,6 @@ Feature: Create node peer variant | nodeAggregateId | "nody-mc-nodeface" | | sourceOrigin | {"example":"source"} | | targetOrigin | {"example":"peerSpec"} | - And the graph projection is fully up to date When the command CreateNodeVariant is executed with payload: | Key | Value | @@ -392,8 +384,6 @@ Feature: Create node peer variant | sourceOrigin | {"example":"source"} | | peerOrigin | {"example":"peer"} | | peerSucceedingSiblings | [{"dimensionSpacePoint":{"example":"peer"},"nodeAggregateId":null}] | - - When the graph projection is fully up to date Then I expect the graph projection to consist of exactly 14 nodes And I expect a node identified by cs-identifier;lady-eleonode-rootford;{} to exist in the content graph And I expect a node identified by cs-identifier;eldest-mc-nodeface;{"example":"peer"} to exist in the content graph @@ -509,7 +499,6 @@ Feature: Create node peer variant | nodeAggregateId | "nody-mc-nodeface" | | sourceOrigin | {"example":"source"} | | targetOrigin | {"example":"peer"} | - And the graph projection is fully up to date When the command CreateNodeVariant is executed with payload: | Key | Value | @@ -559,8 +548,6 @@ Feature: Create node peer variant | sourceOrigin | {"example":"source"} | | peerOrigin | {"example":"peerSpec"} | | peerSucceedingSiblings | [{"dimensionSpacePoint":{"example":"peerSpec"},"nodeAggregateId":null}] | - - When the graph projection is fully up to date Then I expect the graph projection to consist of exactly 14 nodes And I expect a node identified by cs-identifier;lady-eleonode-rootford;{} to exist in the content graph And I expect a node identified by cs-identifier;eldest-mc-nodeface;{"example":"peer"} to exist in the content graph @@ -684,7 +671,6 @@ Feature: Create node peer variant | nodeAggregateId | "elder-mc-nodeface" | | sourceOrigin | {"example":"source"} | | targetOrigin | {"example":"peer"} | - And the graph projection is fully up to date And the command CreateNodeVariant is executed with payload: | Key | Value | | nodeAggregateId | "elder-child-mc-nodeface" | @@ -706,8 +692,6 @@ Feature: Create node peer variant | sourceOrigin | {"example":"source"} | | peerOrigin | {"example":"peer"} | | peerSucceedingSiblings | [{"dimensionSpacePoint":{"example":"peer"},"nodeAggregateId":null},{"dimensionSpacePoint":{"example":"peerSpec"},"nodeAggregateId":null}] | - - When the graph projection is fully up to date Then I expect the graph projection to consist of exactly 11 nodes And I expect a node identified by cs-identifier;lady-eleonode-rootford;{} to exist in the content graph And I expect a node identified by cs-identifier;eldest-mc-nodeface;{"example":"peer"} to exist in the content graph diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/04-NodeModification/01-SetNodeProperties_ConstraintChecks.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/04-NodeModification/01-SetNodeProperties_ConstraintChecks.feature index 2ac617f4d44..18ecdfede6c 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/04-NodeModification/01-SetNodeProperties_ConstraintChecks.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/04-NodeModification/01-SetNodeProperties_ConstraintChecks.feature @@ -25,13 +25,11 @@ Feature: Set node properties: Constraint checks | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"de"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date # We have to add another node since root nodes have no dimension space points and thus cannot be varied # Node /document And the following CreateNodeAggregateWithNode commands are executed: diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/04-NodeModification/02-SetNodeProperties.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/04-NodeModification/02-SetNodeProperties.feature index a48915306a0..7b9752e0d21 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/04-NodeModification/02-SetNodeProperties.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/04-NodeModification/02-SetNodeProperties.feature @@ -63,13 +63,11 @@ Feature: Set properties | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"mul"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date # We have to add another node since root nodes have no dimension space points and thus cannot be varied # Node /document And the following CreateNodeAggregateWithNode commands are executed: @@ -80,13 +78,11 @@ Feature: Set properties | nodeAggregateId | "nody-mc-nodeface" | | sourceOrigin | {"language":"mul"} | | targetOrigin | {"language":"de"} | - And the graph projection is fully up to date And the command CreateNodeVariant is executed with payload: | Key | Value | | nodeAggregateId | "nody-mc-nodeface" | | sourceOrigin | {"language":"mul"} | | targetOrigin | {"language":"gsw"} | - And the graph projection is fully up to date Scenario: Set node properties And the command SetNodeProperties is executed with payload: @@ -94,7 +90,6 @@ Feature: Set properties | nodeAggregateId | "nody-mc-nodeface" | | originDimensionSpacePoint | {"language": "de"} | | propertyValues | {"string":"My new string", "int":8472, "float":72.84, "bool":true, "array":{"givenName":"David", "familyName":"Nodenborough","age":84}, "dayOfWeek":"DayOfWeek:https://schema.org/Friday", "date":"Date:2021-03-13T17:33:17+00:00", "uri":"URI:https://www.neos.io", "postalAddress":"PostalAddress:anotherDummy", "price":"PriceSpecification:anotherDummy"} | - And the graph projection is fully up to date Then I expect a node identified by cs-identifier;nody-mc-nodeface;{"language":"de"} to exist in the content graph And I expect this node to have the following properties: | Key | Value | @@ -115,7 +110,6 @@ Feature: Set properties | nodeAggregateId | "nody-mc-nodeface" | | originDimensionSpacePoint | {"language": "de"} | | propertyValues | {"string":"My new string"} | - And the graph projection is fully up to date Then I expect a node identified by cs-identifier;nody-mc-nodeface;{"language":"de"} to exist in the content graph And I expect this node to have the following properties: | Key | Value | diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/04-NodeModification/03-SetNodeProperties_PropertyScopes.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/04-NodeModification/03-SetNodeProperties_PropertyScopes.feature index 40fe2c65f85..45f1753f0a0 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/04-NodeModification/03-SetNodeProperties_PropertyScopes.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/04-NodeModification/03-SetNodeProperties_PropertyScopes.feature @@ -36,13 +36,11 @@ Feature: Set node properties with different scopes | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"mul"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date # We have to add another node since root nodes have no dimension space points and thus cannot be varied # Node /document And the following CreateNodeAggregateWithNode commands are executed: @@ -53,13 +51,11 @@ Feature: Set node properties with different scopes | nodeAggregateId | "nody-mc-nodeface" | | sourceOrigin | {"language":"mul"} | | targetOrigin | {"language":"de"} | - And the graph projection is fully up to date And the command CreateNodeVariant is executed with payload: | Key | Value | | nodeAggregateId | "nody-mc-nodeface" | | sourceOrigin | {"language":"mul"} | | targetOrigin | {"language":"gsw"} | - And the graph projection is fully up to date Scenario: Set node properties And the command SetNodeProperties is executed with payload: @@ -67,7 +63,6 @@ Feature: Set node properties with different scopes | nodeAggregateId | "nody-mc-nodeface" | | originDimensionSpacePoint | {"language": "de"} | | propertyValues | {"unscopedProperty":"My new string", "nodeScopedProperty":"My new string", "specializationsScopedProperty":"My new string", "nodeAggregateScopedProperty":"My new string"} | - And the graph projection is fully up to date Then I expect a node identified by cs-identifier;nody-mc-nodeface;{"language":"mul"} to exist in the content graph And I expect this node to have the following properties: | Key | Value | diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/05-NodeReferencing/01-SetNodeReferences_ConstraintChecks.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/05-NodeReferencing/01-SetNodeReferences_ConstraintChecks.feature index c374e45a337..5222b17ad1b 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/05-NodeReferencing/01-SetNodeReferences_ConstraintChecks.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/05-NodeReferencing/01-SetNodeReferences_ConstraintChecks.feature @@ -45,13 +45,11 @@ Feature: Constraint checks on SetNodeReferences | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"de"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | nodeTypeName | parentNodeAggregateId | | source-nodandaise | Neos.ContentRepository.Testing:NodeWithReferences | lady-eleonode-rootford | @@ -163,7 +161,6 @@ Feature: Constraint checks on SetNodeReferences | nodeTypeName | "Neos.ContentRepository.Testing:NodeWithReferences" | | originDimensionSpacePoint | {"language":"en"} | | parentNodeAggregateId | "lady-eleonode-rootford" | - And the graph projection is fully up to date When the command SetNodeReferences is executed with payload and exceptions are caught: | Key | Value | diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/05-NodeReferencing/02-SetNodeReferences_WithoutDimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/05-NodeReferencing/02-SetNodeReferences_WithoutDimensions.feature index 287ab61f562..7057ee16b42 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/05-NodeReferencing/02-SetNodeReferences_WithoutDimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/05-NodeReferencing/02-SetNodeReferences_WithoutDimensions.feature @@ -50,13 +50,11 @@ Feature: Node References without Dimensions | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | parentNodeAggregateId | nodeTypeName | | source-nodandaise | lady-eleonode-rootford | Neos.ContentRepository.Testing:NodeWithReferences | @@ -71,7 +69,6 @@ Feature: Node References without Dimensions | sourceNodeAggregateId | "source-nodandaise" | | referenceName | "referenceProperty" | | references | [{"target": "anthony-destinode"}] | - And the graph projection is fully up to date Then I expect node aggregate identifier "source-nodandaise" to lead to node cs-identifier;source-nodandaise;{} And I expect this node to have the following references: @@ -89,7 +86,6 @@ Feature: Node References without Dimensions | sourceNodeAggregateId | "source-nodandaise" | | referenceName | "referencePropertyWithProperty" | | references | [{"target": "anthony-destinode", "properties":{"text":"my text", "dayOfWeek":"DayOfWeek:https://schema.org/Friday", "postalAddress":"PostalAddress:dummy"}}] | - And the graph projection is fully up to date Then I expect node aggregate identifier "source-nodandaise" to lead to node cs-identifier;source-nodandaise;{} And I expect this node to have the following references: @@ -107,7 +103,6 @@ Feature: Node References without Dimensions | sourceNodeAggregateId | "source-nodandaise" | | referenceName | "referencesProperty" | | references | [{"target": "berta-destinode"}, {"target": "carl-destinode"}] | - And the graph projection is fully up to date Then I expect node aggregate identifier "source-nodandaise" to lead to node cs-identifier;source-nodandaise;{} And I expect this node to have the following references: @@ -131,7 +126,6 @@ Feature: Node References without Dimensions | sourceNodeAggregateId | "source-nodandaise" | | referenceName | "referencesPropertyWithProperty" | | references | [{"target":"berta-destinode", "properties":{"text":"my text", "dayOfWeek":"DayOfWeek:https://schema.org/Wednesday", "postalAddress":"PostalAddress:dummy"}}, {"target":"carl-destinode", "properties":{"text":"my other text", "dayOfWeek":"DayOfWeek:https://schema.org/Friday", "postalAddress":"PostalAddress:anotherDummy"}}] | - And the graph projection is fully up to date Then I expect node aggregate identifier "source-nodandaise" to lead to node cs-identifier;source-nodandaise;{} And I expect this node to have the following references: @@ -155,14 +149,12 @@ Feature: Node References without Dimensions | sourceNodeAggregateId | "source-nodandaise" | | references | [{"target": "berta-destinode"}, {"target": "carl-destinode"}] | | referenceName | "referencesProperty" | - And the graph projection is fully up to date And the command SetNodeReferences is executed with payload: | Key | Value | | sourceNodeAggregateId | "source-nodandaise" | | references | [{"target": "anthony-destinode"}] | | referenceName | "referencesProperty" | - And the graph projection is fully up to date Then I expect node aggregate identifier "source-nodandaise" to lead to node cs-identifier;source-nodandaise;{} And I expect this node to have the following references: @@ -187,14 +179,12 @@ Feature: Node References without Dimensions | sourceNodeAggregateId | "source-nodandaise" | | references | [{"target": "berta-destinode"}, {"target": "carl-destinode"}] | | referenceName | "referencesProperty" | - And the graph projection is fully up to date And the command SetNodeReferences is executed with payload: | Key | Value | | sourceNodeAggregateId | "source-nodandaise" | | references | [{"target": "carl-destinode"}, {"target": "berta-destinode"}] | | referenceName | "referencesProperty" | - And the graph projection is fully up to date Then I expect node aggregate identifier "source-nodandaise" to lead to node cs-identifier;source-nodandaise;{} And I expect this node to have the following references: @@ -209,7 +199,6 @@ Feature: Node References without Dimensions | sourceNodeAggregateId | "source-nodandaise" | | references | [{"target": "berta-destinode"}, {"target": "carl-destinode"}] | | referenceName | "referencesProperty" | - And the graph projection is fully up to date And the command SetNodeReferences is executed with payload: | Key | Value | @@ -217,8 +206,6 @@ Feature: Node References without Dimensions | references | [] | | referenceName | "referencesProperty" | - And the graph projection is fully up to date - Then I expect node aggregate identifier "source-nodandaise" to lead to node cs-identifier;source-nodandaise;{} And I expect this node to have no references @@ -235,14 +222,12 @@ Feature: Node References without Dimensions | sourceNodeAggregateId | "source-nodandaise" | | references | [{"target": "anthony-destinode"}] | | referenceName | "referenceProperty" | - And the graph projection is fully up to date And the command SetNodeReferences is executed with payload: | Key | Value | | sourceNodeAggregateId | "node-wan-kenodi" | | references | [{"target": "anthony-destinode"}] | | referenceName | "referenceProperty" | - And the graph projection is fully up to date Then I expect node aggregate identifier "anthony-destinode" to lead to node cs-identifier;anthony-destinode;{} And I expect this node to be referenced by: @@ -256,7 +241,6 @@ Feature: Node References without Dimensions | sourceNodeAggregateId | "source-nodandaise" | | references | [{"target": "anthony-destinode"}] | | referenceName | "restrictedReferenceProperty" | - And the graph projection is fully up to date Then I expect node aggregate identifier "source-nodandaise" to lead to node cs-identifier;source-nodandaise;{} And I expect this node to have the following references: diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/05-NodeReferencing/03-SetNodeReferences_WithDimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/05-NodeReferencing/03-SetNodeReferences_WithDimensions.feature index 466f0e67602..f46604359a4 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/05-NodeReferencing/03-SetNodeReferences_WithDimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/05-NodeReferencing/03-SetNodeReferences_WithDimensions.feature @@ -29,13 +29,11 @@ Feature: Node References with Dimensions | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"de"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | nodeTypeName | parentNodeAggregateId | | source-nodandaise | Neos.ContentRepository.Testing:NodeWithReferences | lady-eleonode-rootford | @@ -47,7 +45,6 @@ Feature: Node References with Dimensions | sourceNodeAggregateId | "source-nodandaise" | | referenceName | "referenceProperty" | | references | [{"target": "anthony-destinode"}] | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {"language": "de"} Then I expect node aggregate identifier "source-nodandaise" to lead to node cs-identifier;source-nodandaise;{"language": "de"} diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/05-NodeReferencing/04-SetNodeReferences_PropertyScopes.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/05-NodeReferencing/04-SetNodeReferences_PropertyScopes.feature index 0bc4edb6565..99be7a37f06 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/05-NodeReferencing/04-SetNodeReferences_PropertyScopes.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/05-NodeReferencing/04-SetNodeReferences_PropertyScopes.feature @@ -43,13 +43,11 @@ Feature: Set node properties with different scopes | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"mul"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date # We have to add another node since root nodes have no dimension space points and thus cannot be varied # Node /document And the following CreateNodeAggregateWithNode commands are executed: @@ -61,13 +59,11 @@ Feature: Set node properties with different scopes | nodeAggregateId | "source-nodandaise" | | sourceOrigin | {"language":"mul"} | | targetOrigin | {"language":"de"} | - And the graph projection is fully up to date And the command CreateNodeVariant is executed with payload: | Key | Value | | nodeAggregateId | "source-nodandaise" | | sourceOrigin | {"language":"mul"} | | targetOrigin | {"language":"gsw"} | - And the graph projection is fully up to date Scenario: Set node properties And the command SetNodeReferences is executed with payload: @@ -118,7 +114,6 @@ Feature: Set node properties with different scopes | referenceName | "specializationsScopedReferences" | | sourceOriginDimensionSpacePoint | {"language": "de"} | | references | [{"target": "anthony-destinode"}] | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {"language": "mul"} Then I expect node aggregate identifier "source-nodandaise" to lead to node cs-identifier;source-nodandaise;{"language": "mul"} diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/05-NodeReferencing/05-NodeVariation_After_NodeReferencing.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/05-NodeReferencing/05-NodeVariation_After_NodeReferencing.feature index 35bfb620617..29d9cf5d2e8 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/05-NodeReferencing/05-NodeVariation_After_NodeReferencing.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/05-NodeReferencing/05-NodeVariation_After_NodeReferencing.feature @@ -29,13 +29,11 @@ Feature: Node References with Dimensions | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"de"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | nodeTypeName | parentNodeAggregateId | | source-nodandaise | Neos.ContentRepository.Testing:NodeWithReferences | lady-eleonode-rootford | @@ -47,14 +45,12 @@ Feature: Node References with Dimensions | sourceNodeAggregateId | "source-nodandaise" | | referenceName | "referenceProperty" | | references | [{"target": "anthony-destinode"}] | - And the graph projection is fully up to date When the command CreateNodeVariant is executed with payload: | Key | Value | | nodeAggregateId | "source-nodandaise" | | sourceOrigin | {"language":"de"} | | targetOrigin | {"language":"ch"} | - And the graph projection is fully up to date # after specialization, the reference must still exist on the specialized node When I am in the active content stream of workspace "live" and dimension space point {"language": "ch"} @@ -86,7 +82,6 @@ Feature: Node References with Dimensions | sourceOriginDimensionSpacePoint | {"language": "ch"} | | referenceName | "referenceProperty" | | references | [{"target": "source-nodandaise"}] | - And the graph projection is fully up to date # reference to self (modified 2 lines above) When I am in the active content stream of workspace "live" and dimension space point {"language": "ch"} @@ -115,7 +110,6 @@ Feature: Node References with Dimensions | nodeAggregateId | "source-nodandaise" | | sourceOrigin | {"language":"de"} | | targetOrigin | {"language":"ch"} | - And the graph projection is fully up to date When the command SetNodeReferences is executed with payload: | Key | Value | @@ -123,7 +117,6 @@ Feature: Node References with Dimensions | sourceOriginDimensionSpacePoint | {"language": "ch"} | | referenceName | "referenceProperty" | | references | [{"target": "anthony-destinode"}] | - And the graph projection is fully up to date # on the specialization, the reference exists. @@ -153,21 +146,18 @@ Feature: Node References with Dimensions | nodeAggregateId | "anthony-destinode" | | sourceOrigin | {"language":"de"} | | targetOrigin | {"language":"en"} | - And the graph projection is fully up to date When the command SetNodeReferences is executed with payload: | Key | Value | | sourceNodeAggregateId | "source-nodandaise" | | referenceName | "referenceProperty" | | references | [{"target": "anthony-destinode"}] | - And the graph projection is fully up to date When the command CreateNodeVariant is executed with payload: | Key | Value | | nodeAggregateId | "source-nodandaise" | | sourceOrigin | {"language":"de"} | | targetOrigin | {"language":"en"} | - And the graph projection is fully up to date # after creating a peer, the reference must still exist on the peer node When I am in the active content stream of workspace "live" and dimension space point {"language": "en"} @@ -209,7 +199,6 @@ Feature: Node References with Dimensions | sourceOriginDimensionSpacePoint | {"language": "en"} | | referenceName | "referenceProperty" | | references | [{"target": "source-nodandaise"}] | - And the graph projection is fully up to date # reference to self (modified 2 lines above) When I am in the active content stream of workspace "live" and dimension space point {"language": "en"} @@ -250,7 +239,6 @@ Feature: Node References with Dimensions | originDimensionSpacePoint | {"language": "ch"} | | nodeTypeName | "Neos.ContentRepository.Testing:NodeWithReferences" | | parentNodeAggregateId | "lady-eleonode-rootford" | - And the graph projection is fully up to date When the command SetNodeReferences is executed with payload: | Key | Value | @@ -258,7 +246,6 @@ Feature: Node References with Dimensions | sourceOriginDimensionSpacePoint | {"language": "ch"} | | referenceName | "referenceProperty" | | references | [{"target": "anthony-destinode"}] | - And the graph projection is fully up to date # here we generalize When the command CreateNodeVariant is executed with payload: @@ -266,7 +253,6 @@ Feature: Node References with Dimensions | nodeAggregateId | "ch-only" | | sourceOrigin | {"language":"ch"} | | targetOrigin | {"language":"de"} | - And the graph projection is fully up to date # after generalizing, the reference must still exist on the generalized node When I am in the active content stream of workspace "live" and dimension space point {"language": "de"} diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/06-NodeDisabling/01-DisableNodeAggregate_ConstraintChecks.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/06-NodeDisabling/01-DisableNodeAggregate_ConstraintChecks.feature index 82db6e57770..25621470085 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/06-NodeDisabling/01-DisableNodeAggregate_ConstraintChecks.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/06-NodeDisabling/01-DisableNodeAggregate_ConstraintChecks.feature @@ -22,13 +22,11 @@ Feature: Constraint checks on node aggregate disabling | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"de"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | nodeTypeName | parentNodeAggregateId | nodeName | | sir-david-nodenborough | Neos.ContentRepository.Testing:Document | lady-eleonode-rootford | document | @@ -64,7 +62,6 @@ Feature: Constraint checks on node aggregate disabling | nodeAggregateId | "sir-david-nodenborough" | | coveredDimensionSpacePoint | {"language": "de"} | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date # Note: The behavior has been changed with https://github.com/neos/neos-development-collection/pull/4284 and the test was adjusted accordingly When the command DisableNodeAggregate is executed with payload: diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/06-NodeDisabling/02-DisableNodeAggregate_WithoutDimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/06-NodeDisabling/02-DisableNodeAggregate_WithoutDimensions.feature index ed23f5e23db..8a2d7f77423 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/06-NodeDisabling/02-DisableNodeAggregate_WithoutDimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/06-NodeDisabling/02-DisableNodeAggregate_WithoutDimensions.feature @@ -23,13 +23,11 @@ Feature: Disable a node aggregate | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | nodeTypeName | parentNodeAggregateId | nodeName | | preceding-nodenborough | Neos.ContentRepository.Testing:Document | lady-eleonode-rootford | preceding-document | @@ -41,7 +39,6 @@ Feature: Disable a node aggregate | sourceNodeAggregateId | "preceding-nodenborough" | | referenceName | "references" | | references | [{"target": "sir-david-nodenborough"}] | - And the graph projection is fully up to date Scenario: Disable node with arbitrary strategy since dimensions are not involved When the command DisableNodeAggregate is executed with payload: @@ -56,8 +53,6 @@ Feature: Disable a node aggregate | nodeAggregateId | "sir-david-nodenborough" | | affectedDimensionSpacePoints | [[]] | | tag | "disabled" | - - When the graph projection is fully up to date And I am in the active content stream of workspace "live" Then I expect the graph projection to consist of exactly 5 nodes And I expect a node identified by cs-identifier;lady-eleonode-rootford;{} to exist in the content graph diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/06-NodeDisabling/03-DisableNodeAggregate_WithDimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/06-NodeDisabling/03-DisableNodeAggregate_WithDimensions.feature index b4df608c120..cd2f0142224 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/06-NodeDisabling/03-DisableNodeAggregate_WithDimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/06-NodeDisabling/03-DisableNodeAggregate_WithDimensions.feature @@ -25,13 +25,11 @@ Feature: Disable a node aggregate | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"mul"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | nodeTypeName | parentNodeAggregateId | nodeName | | preceding-nodenborough | Neos.ContentRepository.Testing:Document | lady-eleonode-rootford | preceding-document | @@ -49,7 +47,6 @@ Feature: Disable a node aggregate | nodeAggregateId | "sir-david-nodenborough" | | sourceOrigin | {"language":"mul"} | | targetOrigin | {"language":"ltz"} | - And the graph projection is fully up to date # Set the DSP to the "central" variant having variants of all kind And I am in dimension space point {"language":"de"} @@ -66,8 +63,6 @@ Feature: Disable a node aggregate | nodeAggregateId | "sir-david-nodenborough" | | affectedDimensionSpacePoints | [{"language":"de"}, {"language":"ltz"}, {"language":"gsw"}] | | tag | "disabled" | - - When the graph projection is fully up to date And I am in the active content stream of workspace "live" Then I expect the graph projection to consist of exactly 6 nodes And I expect a node identified by cs-identifier;lady-eleonode-rootford;{} to exist in the content graph @@ -318,8 +313,6 @@ Feature: Disable a node aggregate | nodeAggregateId | "sir-david-nodenborough" | | affectedDimensionSpacePoints | [{"language":"ltz"}, {"language":"mul"}, {"language":"de"}, {"language":"en"}, {"language":"gsw"}] | | tag | "disabled" | - - When the graph projection is fully up to date And I am in the active content stream of workspace "live" Then I expect the graph projection to consist of exactly 6 nodes And I expect a node identified by cs-identifier;lady-eleonode-rootford;{} to exist in the content graph diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/06-NodeDisabling/04-EnableNodeAggregate_ConstraintChecks.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/06-NodeDisabling/04-EnableNodeAggregate_ConstraintChecks.feature index 44b5734afd4..3e4fe63be4c 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/06-NodeDisabling/04-EnableNodeAggregate_ConstraintChecks.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/06-NodeDisabling/04-EnableNodeAggregate_ConstraintChecks.feature @@ -22,13 +22,11 @@ Feature: Enable a node aggregate | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"de"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | nodeTypeName | parentNodeAggregateId | nodeName | | sir-david-nodenborough | Neos.ContentRepository.Testing:Document | lady-eleonode-rootford | document | diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/06-NodeDisabling/05-EnableNodeAggregate_WithoutDimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/06-NodeDisabling/05-EnableNodeAggregate_WithoutDimensions.feature index b44170f3870..9d4f9cb574e 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/06-NodeDisabling/05-EnableNodeAggregate_WithoutDimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/06-NodeDisabling/05-EnableNodeAggregate_WithoutDimensions.feature @@ -23,13 +23,11 @@ Feature: Enable a node aggregate | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | nodeTypeName | parentNodeAggregateId | nodeName | | preceding-nodenborough | Neos.ContentRepository.Testing:Document | lady-eleonode-rootford | preceding-document | @@ -41,14 +39,12 @@ Feature: Enable a node aggregate | sourceNodeAggregateId | "preceding-nodenborough" | | referenceName | "references" | | references | [{"target": "sir-david-nodenborough"}] | - And the graph projection is fully up to date Scenario: Enable a previously disabled node with arbitrary strategy since dimensions are not involved Given the command DisableNodeAggregate is executed with payload: | Key | Value | | nodeAggregateId | "sir-david-nodenborough" | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date When the command EnableNodeAggregate is executed with payload: | Key | Value | @@ -62,8 +58,6 @@ Feature: Enable a node aggregate | nodeAggregateId | "sir-david-nodenborough" | | affectedDimensionSpacePoints | [[]] | | tag | "disabled" | - - When the graph projection is fully up to date And I am in the active content stream of workspace "live" Then I expect the graph projection to consist of exactly 5 nodes And I expect a node identified by cs-identifier;lady-eleonode-rootford;{} to exist in the content graph @@ -126,12 +120,10 @@ Feature: Enable a node aggregate | Key | Value | | nodeAggregateId | "sir-david-nodenborough" | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date And the command DisableNodeAggregate is executed with payload: | Key | Value | | nodeAggregateId | "nody-mc-nodeface" | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date When the command EnableNodeAggregate is executed with payload: | Key | Value | @@ -144,8 +136,6 @@ Feature: Enable a node aggregate | nodeAggregateId | "sir-david-nodenborough" | | affectedDimensionSpacePoints | [[]] | | tag | "disabled" | - - When the graph projection is fully up to date And I am in the active content stream of workspace "live" Then I expect the node aggregate "sir-david-nodenborough" to exist @@ -204,12 +194,10 @@ Feature: Enable a node aggregate | Key | Value | | nodeAggregateId | "sir-david-nodenborough" | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date And the command DisableNodeAggregate is executed with payload: | Key | Value | | nodeAggregateId | "nody-mc-nodeface" | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date When the command EnableNodeAggregate is executed with payload: | Key | Value | @@ -222,8 +210,6 @@ Feature: Enable a node aggregate | nodeAggregateId | "nody-mc-nodeface" | | affectedDimensionSpacePoints | [[]] | | tag | "disabled" | - - When the graph projection is fully up to date And I am in the active content stream of workspace "live" Then I expect the node aggregate "sir-david-nodenborough" to exist diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/06-NodeDisabling/06-EnableNodeAggregate_WithDimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/06-NodeDisabling/06-EnableNodeAggregate_WithDimensions.feature index 97f56b109d3..2b26d15e2b6 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/06-NodeDisabling/06-EnableNodeAggregate_WithDimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/06-NodeDisabling/06-EnableNodeAggregate_WithDimensions.feature @@ -25,13 +25,11 @@ Feature: Enable a node aggregate | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"mul"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | nodeTypeName | parentNodeAggregateId | nodeName | | preceding-nodenborough | Neos.ContentRepository.Testing:Document | lady-eleonode-rootford | preceding-document | @@ -50,19 +48,16 @@ Feature: Enable a node aggregate | nodeAggregateId | "sir-david-nodenborough" | | sourceOrigin | {"language":"mul"} | | targetOrigin | {"language":"ltz"} | - And the graph projection is fully up to date # Disable our reference node aggregate in all variants And the command DisableNodeAggregate is executed with payload: | Key | Value | | nodeAggregateId | "sir-david-nodenborough" | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date # Explicitly disable a child node aggregate in all variants And the command DisableNodeAggregate is executed with payload: | Key | Value | | nodeAggregateId | "the-great-nodini" | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date # Set the DSP to the "central" variant having variants of all kind And I am in dimension space point {"language":"de"} @@ -80,8 +75,6 @@ Feature: Enable a node aggregate | nodeAggregateId | "sir-david-nodenborough" | | affectedDimensionSpacePoints | [{"language":"de"},{"language":"ltz"},{"language":"gsw"}] | | tag | "disabled" | - - When the graph projection is fully up to date And I am in the active content stream of workspace "live" Then I expect the graph projection to consist of exactly 7 nodes And I expect a node identified by cs-identifier;lady-eleonode-rootford;{} to exist in the content graph @@ -376,8 +369,6 @@ Feature: Enable a node aggregate | nodeAggregateId | "sir-david-nodenborough" | | affectedDimensionSpacePoints | [{"language":"mul"},{"language":"de"},{"language":"en"},{"language":"gsw"},{"language":"ltz"}] | | tag | "disabled" | - - When the graph projection is fully up to date And I am in the active content stream of workspace "live" Then I expect the graph projection to consist of exactly 7 nodes And I expect a node identified by cs-identifier;lady-eleonode-rootford;{} to exist in the content graph @@ -704,8 +695,6 @@ Feature: Enable a node aggregate | Key | Value | | nodeAggregateId | "the-great-nodini" | | nodeVariantSelectionStrategy | "allVariants" | - - When the graph projection is fully up to date And I am in the active content stream of workspace "live" Then I expect the node aggregate "the-great-nodini" to exist diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/06-NodeDisabling/07-CreateNodeAggregateWithNodeWithDisabledAncestor_WithoutDimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/06-NodeDisabling/07-CreateNodeAggregateWithNodeWithDisabledAncestor_WithoutDimensions.feature index 1d236a45a38..9018cb61797 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/06-NodeDisabling/07-CreateNodeAggregateWithNodeWithDisabledAncestor_WithoutDimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/06-NodeDisabling/07-CreateNodeAggregateWithNodeWithDisabledAncestor_WithoutDimensions.feature @@ -21,13 +21,11 @@ Feature: Creation of nodes underneath disabled nodes | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | nodeTypeName | parentNodeAggregateId | nodeName | | the-great-nodini | Neos.ContentRepository.Testing:Document | lady-eleonode-rootford | document | @@ -35,7 +33,6 @@ Feature: Creation of nodes underneath disabled nodes | Key | Value | | nodeAggregateId | "the-great-nodini" | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date Scenario: When a new node is created underneath a hidden node, this one should be hidden as well When the following CreateNodeAggregateWithNode commands are executed: @@ -49,6 +46,5 @@ Feature: Creation of nodes underneath disabled nodes | Key | Value | | nodeAggregateId | "the-great-nodini" | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date Then I expect node aggregate identifier "nodingers-cat" and node path "document/pet-document" to lead to node cs-identifier;nodingers-cat;{} And I expect this node to be a child of node cs-identifier;the-great-nodini;{} diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/06-NodeDisabling/08-CreateNodeAggregateWithNodeWithDisabledAncestor_WithDimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/06-NodeDisabling/08-CreateNodeAggregateWithNodeWithDisabledAncestor_WithDimensions.feature index 48ca1fa841d..128989f0a46 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/06-NodeDisabling/08-CreateNodeAggregateWithNodeWithDisabledAncestor_WithDimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/06-NodeDisabling/08-CreateNodeAggregateWithNodeWithDisabledAncestor_WithDimensions.feature @@ -23,13 +23,11 @@ Feature: Creation of nodes underneath disabled nodes | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"mul"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | nodeTypeName | parentNodeAggregateId | nodeName | | the-great-nodini | Neos.ContentRepository.Testing:Document | lady-eleonode-rootford | document | @@ -39,7 +37,6 @@ Feature: Creation of nodes underneath disabled nodes | nodeAggregateId | "the-great-nodini" | | sourceOrigin | {"language":"mul"} | | targetOrigin | {"language":"ltz"} | - And the graph projection is fully up to date And VisibilityConstraints are set to "frontend" Scenario: Create a new node with parent disabled with strategy allSpecializations @@ -77,7 +74,6 @@ Feature: Creation of nodes underneath disabled nodes | nodeAggregateId | "the-great-nodini" | | coveredDimensionSpacePoint | {"language":"de"} | | nodeVariantSelectionStrategy | "allSpecializations" | - And the graph projection is fully up to date When I am in dimension space point {"language":"de"} And I expect node aggregate identifier "nodingers-cat" and node path "document/pet-document" to lead to node cs-identifier;nodingers-cat;{"language":"mul"} @@ -124,7 +120,6 @@ Feature: Creation of nodes underneath disabled nodes | nodeAggregateId | "the-great-nodini" | | coveredDimensionSpacePoint | {"language":"de"} | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date When I am in dimension space point {"language":"mul"} And I expect node aggregate identifier "nodingers-cat" and node path "document/pet-document" to lead to node cs-identifier;nodingers-cat;{"language":"mul"} diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/06-NodeDisabling/09-CreateNodeVariantOfDisabledNode.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/06-NodeDisabling/09-CreateNodeVariantOfDisabledNode.feature index d7acb6a6c92..b283f1e6352 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/06-NodeDisabling/09-CreateNodeVariantOfDisabledNode.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/06-NodeDisabling/09-CreateNodeVariantOfDisabledNode.feature @@ -21,13 +21,11 @@ Feature: Variation of hidden nodes | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"mul"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And VisibilityConstraints are set to "frontend" Scenario: Specialize a node where the specialization target is enabled @@ -40,20 +38,17 @@ Feature: Variation of hidden nodes | nodeAggregateId | "the-great-nodini" | | coveredDimensionSpacePoint | {"language":"de"} | | nodeVariantSelectionStrategy | "allSpecializations" | - And the graph projection is fully up to date And the command EnableNodeAggregate is executed with payload: | Key | Value | | nodeAggregateId | "the-great-nodini" | | coveredDimensionSpacePoint | {"language":"gsw"} | | nodeVariantSelectionStrategy | "allSpecializations" | - And the graph projection is fully up to date When the command CreateNodeVariant is executed with payload: | Key | Value | | nodeAggregateId | "the-great-nodini" | | sourceOrigin | {"language":"de"} | | targetOrigin | {"language":"gsw"} | - And the graph projection is fully up to date And I am in dimension space point {"language":"de"} And I expect node aggregate identifier "the-great-nodini" and node path "court-magician" to lead to no node @@ -70,14 +65,12 @@ Feature: Variation of hidden nodes | nodeAggregateId | "the-great-nodini" | | coveredDimensionSpacePoint | {"language":"de"} | | nodeVariantSelectionStrategy | "allSpecializations" | - And the graph projection is fully up to date When the command CreateNodeVariant is executed with payload: | Key | Value | | nodeAggregateId | "the-great-nodini" | | sourceOrigin | {"language":"de"} | | targetOrigin | {"language":"gsw"} | - And the graph projection is fully up to date When I am in dimension space point {"language":"de"} Then I expect node aggregate identifier "the-great-nodini" and node path "court-magician" to lead to no node @@ -90,7 +83,6 @@ Feature: Variation of hidden nodes | nodeAggregateId | "the-great-nodini" | | coveredDimensionSpacePoint | {"language":"gsw"} | | nodeVariantSelectionStrategy | "allSpecializations" | - And the graph projection is fully up to date When I am in dimension space point {"language":"gsw"} Then I expect node aggregate identifier "the-great-nodini" and node path "court-magician" to lead to node cs-identifier;the-great-nodini;{"language":"gsw"} @@ -105,14 +97,12 @@ Feature: Variation of hidden nodes | nodeAggregateId | "the-great-nodini" | | coveredDimensionSpacePoint | {"language":"de"} | | nodeVariantSelectionStrategy | "allSpecializations" | - And the graph projection is fully up to date When the command CreateNodeVariant is executed with payload: | Key | Value | | nodeAggregateId | "the-great-nodini" | | sourceOrigin | {"language":"de"} | | targetOrigin | {"language":"mul"} | - And the graph projection is fully up to date When I am in dimension space point {"language":"de"} Then I expect node aggregate identifier "the-great-nodini" and node path "court-magician" to lead to no node @@ -132,20 +122,17 @@ Feature: Variation of hidden nodes | nodeAggregateId | "the-great-nodini" | | sourceOrigin | {"language":"ltz"} | | targetOrigin | {"language":"mul"} | - And the graph projection is fully up to date And the command DisableNodeAggregate is executed with payload: | Key | Value | | nodeAggregateId | "the-great-nodini" | | coveredDimensionSpacePoint | {"language":"mul"} | | nodeVariantSelectionStrategy | "allSpecializations" | - And the graph projection is fully up to date When the command CreateNodeVariant is executed with payload: | Key | Value | | nodeAggregateId | "the-great-nodini" | | sourceOrigin | {"language":"ltz"} | | targetOrigin | {"language":"de"} | - And the graph projection is fully up to date When I am in dimension space point {"language":"ltz"} Then I expect node aggregate identifier "the-great-nodini" and node path "court-magician" to lead to no node @@ -158,7 +145,6 @@ Feature: Variation of hidden nodes | nodeAggregateId | "the-great-nodini" | | coveredDimensionSpacePoint | {"language":"de"} | | nodeVariantSelectionStrategy | "allSpecializations" | - And the graph projection is fully up to date When I am in dimension space point {"language":"de"} Then I expect node aggregate identifier "the-great-nodini" and node path "court-magician" to lead to node cs-identifier;the-great-nodini;{"language":"de"} @@ -173,14 +159,12 @@ Feature: Variation of hidden nodes | nodeAggregateId | "the-great-nodini" | | coveredDimensionSpacePoint | {"language":"de"} | | nodeVariantSelectionStrategy | "allSpecializations" | - And the graph projection is fully up to date When the command CreateNodeVariant is executed with payload: | Key | Value | | nodeAggregateId | "the-great-nodini" | | sourceOrigin | {"language":"de"} | | targetOrigin | {"language":"en"} | - And the graph projection is fully up to date When I am in dimension space point {"language":"de"} Then I expect node aggregate identifier "the-great-nodini" and node path "court-magician" to lead to no node @@ -198,20 +182,17 @@ Feature: Variation of hidden nodes | nodeAggregateId | "the-great-nodini" | | sourceOrigin | {"language":"de"} | | targetOrigin | {"language":"mul"} | - And the graph projection is fully up to date And the command DisableNodeAggregate is executed with payload: | Key | Value | | nodeAggregateId | "the-great-nodini" | | coveredDimensionSpacePoint | {"language":"mul"} | | nodeVariantSelectionStrategy | "allSpecializations" | - And the graph projection is fully up to date When the command CreateNodeVariant is executed with payload: | Key | Value | | nodeAggregateId | "the-great-nodini" | | sourceOrigin | {"language":"de"} | | targetOrigin | {"language":"en"} | - And the graph projection is fully up to date When I am in dimension space point {"language":"de"} Then I expect node aggregate identifier "the-great-nodini" and node path "court-magician" to lead to no node @@ -224,7 +205,6 @@ Feature: Variation of hidden nodes | nodeAggregateId | "the-great-nodini" | | coveredDimensionSpacePoint | {"language":"en"} | | nodeVariantSelectionStrategy | "allSpecializations" | - And the graph projection is fully up to date When I am in dimension space point {"language":"en"} Then I expect node aggregate identifier "the-great-nodini" and node path "court-magician" to lead to node cs-identifier;the-great-nodini;{"language":"en"} diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/07-NodeRemoval/01-RemoveNodeAggregate_ConstraintChecks.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/07-NodeRemoval/01-RemoveNodeAggregate_ConstraintChecks.feature index bc0798286f2..dbf9d93d83d 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/07-NodeRemoval/01-RemoveNodeAggregate_ConstraintChecks.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/07-NodeRemoval/01-RemoveNodeAggregate_ConstraintChecks.feature @@ -26,13 +26,11 @@ Feature: Remove NodeAggregate | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"de"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | nodeTypeName | parentNodeAggregateId | nodeName | tetheredDescendantNodeAggregateIds | | sir-david-nodenborough | Neos.ContentRepository.Testing:Document | lady-eleonode-rootford | document | {"tethered":"nodewyn-tetherton"} | diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/07-NodeRemoval/02-RemoveNodeAggregate_WithoutDimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/07-NodeRemoval/02-RemoveNodeAggregate_WithoutDimensions.feature index 96d5fdbf148..c25bf6ade27 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/07-NodeRemoval/02-RemoveNodeAggregate_WithoutDimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/07-NodeRemoval/02-RemoveNodeAggregate_WithoutDimensions.feature @@ -23,13 +23,11 @@ Feature: Remove NodeAggregate | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | nodeTypeName | parentNodeAggregateId | nodeName | | sir-david-nodenborough | Neos.ContentRepository.Testing:Document | lady-eleonode-rootford | document | @@ -54,7 +52,6 @@ Feature: Remove NodeAggregate | affectedOccupiedDimensionSpacePoints | [[]] | | affectedCoveredDimensionSpacePoints | [[]] | | removalAttachmentPoint | null | - When the graph projection is fully up to date Then I expect the graph projection to consist of exactly 2 nodes And I expect a node identified by cs-identifier;lady-eleonode-rootford;{} to exist in the content graph And I expect a node identified by cs-identifier;sir-david-nodenborough;{} to exist in the content graph @@ -77,19 +74,16 @@ Feature: Remove NodeAggregate | Key | Value | | nodeAggregateId | "nodingers-cat" | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date And the command RemoveNodeAggregate is executed with payload: | Key | Value | | nodeAggregateId | "nodingers-cat" | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date And the command CreateNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "nodingers-cat" | | nodeTypeName | "Neos.ContentRepository.Testing:Document" | | parentNodeAggregateId | "lady-eleonode-rootford" | | nodeName | "pet" | - And the graph projection is fully up to date Then I expect the node aggregate "nodingers-cat" to exist And I expect this node aggregate to disable dimension space points [] @@ -117,14 +111,12 @@ Feature: Remove NodeAggregate | Key | Value | | nodeAggregateId | "nodingers-cat" | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date And the command CreateNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "nodingers-cat" | | nodeTypeName | "Neos.ContentRepository.Testing:Document" | | parentNodeAggregateId | "lady-eleonode-rootford" | | nodeName | "pet" | - And the graph projection is fully up to date Then I expect node aggregate identifier "sir-david-nodenborough" and node path "document" to lead to node cs-identifier;sir-david-nodenborough;{} And I expect this node to be a child of node cs-identifier;lady-eleonode-rootford;{} diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/07-NodeRemoval/03-RemoveNodeAggregate_WithDimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/07-NodeRemoval/03-RemoveNodeAggregate_WithDimensions.feature index 7039cbfc02b..914e41599bc 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/07-NodeRemoval/03-RemoveNodeAggregate_WithDimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/07-NodeRemoval/03-RemoveNodeAggregate_WithDimensions.feature @@ -25,13 +25,11 @@ Feature: Remove NodeAggregate | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"en"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | nodeTypeName | parentNodeAggregateId | nodeName | | sir-david-nodenborough | Neos.ContentRepository.Testing:Document | lady-eleonode-rootford | document | @@ -57,7 +55,6 @@ Feature: Remove NodeAggregate | affectedOccupiedDimensionSpacePoints | [{"language":"en"}] | | affectedCoveredDimensionSpacePoints | [{"language":"de"},{"language":"gsw"}] | | removalAttachmentPoint | null | - When the graph projection is fully up to date Then I expect the graph projection to consist of exactly 4 nodes And I expect a node identified by cs-identifier;lady-eleonode-rootford;{} to exist in the content graph And I expect a node identified by cs-identifier;sir-david-nodenborough;{"language":"en"} to exist in the content graph @@ -191,7 +188,6 @@ Feature: Remove NodeAggregate | nodeAggregateId | "nodingers-cat" | | sourceOrigin | {"language":"en"} | | targetOrigin | {"language":"de"} | - And the graph projection is fully up to date When the command RemoveNodeAggregate is executed with payload: | Key | Value | @@ -206,7 +202,6 @@ Feature: Remove NodeAggregate | affectedOccupiedDimensionSpacePoints | [{"language":"de"},{"language":"en"}] | | affectedCoveredDimensionSpacePoints | [{"language":"de"},{"language":"en"},{"language":"gsw"},{"language":"fr"}] | | removalAttachmentPoint | null | - When the graph projection is fully up to date Then I expect the graph projection to consist of exactly 2 nodes And I expect a node identified by cs-identifier;lady-eleonode-rootford;{} to exist in the content graph And I expect a node identified by cs-identifier;sir-david-nodenborough;{"language":"en"} to exist in the content graph @@ -296,12 +291,10 @@ Feature: Remove NodeAggregate | Key | Value | | nodeAggregateId | "nodingers-cat" | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date And the command RemoveNodeAggregate is executed with payload: | Key | Value | | nodeAggregateId | "nodingers-cat" | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | nodeTypeName | parentNodeAggregateId | nodeName | | nodingers-cat | Neos.ContentRepository.Testing:Document | lady-eleonode-rootford | pet | @@ -351,19 +344,16 @@ Feature: Remove NodeAggregate | Key | Value | | nodeAggregateId | "nodingers-cat" | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date And the command RemoveNodeAggregate is executed with payload: | Key | Value | | nodeAggregateId | "nodingers-cat" | | coveredDimensionSpacePoint | {"language":"de"} | | nodeVariantSelectionStrategy | "allSpecializations" | - And the graph projection is fully up to date And the command CreateNodeVariant is executed with payload: | Key | Value | | nodeAggregateId | "nodingers-cat" | | sourceOrigin | {"language":"en"} | | targetOrigin | {"language":"de"} | - And the graph projection is fully up to date Then I expect the node aggregate "nodingers-cat" to exist And I expect this node aggregate to disable dimension space points [{"language":"en"},{"language":"fr"}] diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/07-NodeRemoval/04-VariantRecreation.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/07-NodeRemoval/04-VariantRecreation.feature index 81027a506e7..2f6720f682c 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/07-NodeRemoval/04-VariantRecreation.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/07-NodeRemoval/04-VariantRecreation.feature @@ -30,14 +30,12 @@ Feature: Recreate a node variant | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"en"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | originDimensionSpacePoint | nodeName | parentNodeAggregateId | nodeTypeName | tetheredDescendantNodeAggregateIds | | sir-david-nodenborough | {"language":"en"} | document | lady-eleonode-rootford | Neos.ContentRepository.Testing:Document | {"tethered-document": "nodimus-prime", "tethered-document/tethered": "nodimus-mediocre"} | @@ -48,7 +46,6 @@ Feature: Recreate a node variant | workspaceName | "user-ws" | | baseWorkspaceName | "live" | | newContentStreamId | "user-cs-id" | - And the graph projection is fully up to date Scenario: Create specialization variant of node, publish, delete it and recreate it When the command CreateNodeVariant is executed with payload: @@ -57,19 +54,16 @@ Feature: Recreate a node variant | nodeAggregateId | "sir-david-nodenborough" | | sourceOrigin | {"language":"en"} | | targetOrigin | {"language":"de"} | - And the graph projection is fully up to date When the command CreateNodeVariant is executed with payload: | Key | Value | | workspaceName | "user-ws" | | nodeAggregateId | "nody-mc-nodeface" | | sourceOrigin | {"language":"en"} | | targetOrigin | {"language":"de"} | - And the graph projection is fully up to date And the command PublishWorkspace is executed with payload: | Key | Value | | workspaceName | "user-ws" | | newContentStreamId | "new-user-cs-id" | - And the graph projection is fully up to date And the command RemoveNodeAggregate is executed with payload: | Key | Value | @@ -77,7 +71,6 @@ Feature: Recreate a node variant | nodeAggregateId | "sir-david-nodenborough" | | coveredDimensionSpacePoint | {"language":"de"} | | nodeVariantSelectionStrategy | "allSpecializations" | - And the graph projection is fully up to date And the command CreateNodeVariant is executed with payload: | Key | Value | @@ -85,14 +78,12 @@ Feature: Recreate a node variant | nodeAggregateId | "sir-david-nodenborough" | | sourceOrigin | {"language":"en"} | | targetOrigin | {"language":"de"} | - And the graph projection is fully up to date When the command CreateNodeVariant is executed with payload: | Key | Value | | workspaceName | "user-ws" | | nodeAggregateId | "nody-mc-nodeface" | | sourceOrigin | {"language":"en"} | | targetOrigin | {"language":"de"} | - And the graph projection is fully up to date When I am in the active content stream of workspace "user-ws" and dimension space point {"language": "de"} Then I expect node aggregate identifier "sir-david-nodenborough" and node path "document" to lead to node new-user-cs-id;sir-david-nodenborough;{"language": "de"} diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/07-NodeRemoval/05-CreateNodeAfterDeletion.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/07-NodeRemoval/05-CreateNodeAfterDeletion.feature index e8402d7025e..dcd512286bf 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/07-NodeRemoval/05-CreateNodeAfterDeletion.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/07-NodeRemoval/05-CreateNodeAfterDeletion.feature @@ -30,13 +30,11 @@ Feature: Create node specialization | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"example":"source"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | nodeName | parentNodeAggregateId | succeedingSiblingNodeAggregateId | nodeTypeName | tetheredDescendantNodeAggregateIds | @@ -52,7 +50,6 @@ Feature: Create node specialization | nodeAggregateId | "younger-mc-nodeface" | | coveredDimensionSpacePoint | {"example":"spec"} | | nodeVariantSelectionStrategy | "allSpecializations" | - And the graph projection is fully up to date When the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | nodeName | parentNodeAggregateId | succeedingSiblingNodeAggregateId | nodeTypeName | tetheredDescendantNodeAggregateIds | | nody-mc-nodeface | document | lady-eleonode-rootford | younger-mc-nodeface | Neos.ContentRepository.Testing:Document | {"tethered-node": "nodewyn-tetherton", "tethered-node/tethered-leaf": "nodimer-tetherton"} | diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/07-NodeRemoval/06-CreateNodeSpecializationVariantAfterDeletion.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/07-NodeRemoval/06-CreateNodeSpecializationVariantAfterDeletion.feature index a0c1ae951a9..a73cb14209c 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/07-NodeRemoval/06-CreateNodeSpecializationVariantAfterDeletion.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/07-NodeRemoval/06-CreateNodeSpecializationVariantAfterDeletion.feature @@ -31,13 +31,11 @@ Feature: Create node specialization | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"example":"source"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | nodeName | parentNodeAggregateId | succeedingSiblingNodeAggregateId | nodeTypeName | tetheredDescendantNodeAggregateIds | @@ -56,14 +54,12 @@ Feature: Create node specialization | nodeAggregateId | "nody-mc-nodeface" | | coveredDimensionSpacePoint | {"example":"spec"} | | nodeVariantSelectionStrategy | "allSpecializations" | - And the graph projection is fully up to date When the command CreateNodeVariant is executed with payload: | Key | Value | | contentStreamId | "cs-identifier" | | nodeAggregateId | "nody-mc-nodeface" | | sourceOrigin | {"example":"source"} | | targetOrigin | {"example":"spec"} | - And the graph projection is fully up to date Then I expect the graph projection to consist of exactly 12 nodes And I expect a node identified by cs-identifier;lady-eleonode-rootford;{} to exist in the content graph diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/08-NodeMove/MoveNodeAggregate.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/08-NodeMove/MoveNodeAggregate.feature index 5dd2d441fa8..8c81cd7a4d7 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/08-NodeMove/MoveNodeAggregate.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/08-NodeMove/MoveNodeAggregate.feature @@ -43,7 +43,6 @@ Feature: Move node to a new parent / within the current parent before a sibling | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | And I am in the active content stream of workspace "live" - And the graph projection is fully up to date And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | @@ -78,7 +77,6 @@ Feature: Move node to a new parent / within the current parent before a sibling | parentNodeAggregateId | "sir-david-nodenborough" | | nodeName | "esquire" | | nodeAggregateClassification | "regular" | - And the graph projection is fully up to date Scenario: Try to move a node in a non-existing workspace: When the command MoveNodeAggregate is executed with payload and exceptions are caught: @@ -160,7 +158,6 @@ Feature: Move node to a new parent / within the current parent before a sibling | parentNodeAggregateId | "sir-david-nodenborough" | | nodeName | "document" | | nodeAggregateClassification | "regular" | - And the graph projection is fully up to date When the command MoveNodeAggregate is executed with payload and exceptions are caught: | Key | Value | @@ -180,7 +177,6 @@ Feature: Move node to a new parent / within the current parent before a sibling | coveredDimensionSpacePoints | [{"market": "DE", "language": "de"}, {"market": "DE", "language": "gsw"}, {"market": "CH", "language": "de"}, {"market": "CH", "language": "gsw"}] | | parentNodeAggregateId | "sir-david-nodenborough" | | nodeAggregateClassification | "regular" | - And the graph projection is fully up to date When the command MoveNodeAggregate is executed with payload: | Key | Value | @@ -188,7 +184,6 @@ Feature: Move node to a new parent / within the current parent before a sibling | nodeAggregateId | "nody-mc-nodeface" | | newParentNodeAggregateId | "lady-eleonode-rootford" | | relationDistributionStrategy | "scatter" | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {"market": "DE", "language": "de"} And I expect node aggregate identifier "nody-mc-nodeface" to lead to node cs-identifier;nody-mc-nodeface;{"market":"DE","language":"de"} @@ -204,7 +199,6 @@ Feature: Move node to a new parent / within the current parent before a sibling | parentNodeAggregateId | "lady-eleonode-rootford" | | nodeName | "other-document" | | nodeAggregateClassification | "regular" | - And the graph projection is fully up to date When the command MoveNodeAggregate is executed with payload and exceptions are caught: | Key | Value | @@ -225,7 +219,6 @@ Feature: Move node to a new parent / within the current parent before a sibling | parentNodeAggregateId | "lady-eleonode-rootford" | | nodeName | "content" | | nodeAggregateClassification | "regular" | - And the graph projection is fully up to date When the command MoveNodeAggregate is executed with payload and exceptions are caught: | Key | Value | | dimensionSpacePoint | {"market": "DE", "language": "de"} | diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/08-NodeMove/MoveNodeAggregateConsideringDisableStateWithoutDimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/08-NodeMove/MoveNodeAggregateConsideringDisableStateWithoutDimensions.feature index e8f664d3ec1..d82b280aaeb 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/08-NodeMove/MoveNodeAggregateConsideringDisableStateWithoutDimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/08-NodeMove/MoveNodeAggregateConsideringDisableStateWithoutDimensions.feature @@ -28,7 +28,6 @@ Feature: Move a node aggregate considering disable state but without content dim | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | @@ -74,7 +73,6 @@ Feature: Move a node aggregate considering disable state but without content dim | parentNodeAggregateId | "sir-nodeward-nodington-iii" | | nodeName | "esquire-child" | | nodeAggregateClassification | "regular" | - And the graph projection is fully up to date Scenario: Move a node disabled by one of its ancestors to a new parent that is enabled Given the event SubtreeWasTagged was published with payload: @@ -83,7 +81,6 @@ Feature: Move a node aggregate considering disable state but without content dim | nodeAggregateId | "sir-david-nodenborough" | | affectedDimensionSpacePoints | [{}] | | tag | "disabled" | - And the graph projection is fully up to date When the command MoveNodeAggregate is executed with payload: | Key | Value | @@ -91,7 +88,6 @@ Feature: Move a node aggregate considering disable state but without content dim | dimensionSpacePoint | {} | | newParentNodeAggregateId | "sir-nodeward-nodington-iii" | | newSucceedingSiblingNodeAggregateId | null | - And the graph projection is fully up to date # node aggregate occupation and coverage is not relevant without dimensions and thus not tested @@ -107,7 +103,6 @@ Feature: Move a node aggregate considering disable state but without content dim | nodeAggregateId | "nody-mc-nodeface" | | affectedDimensionSpacePoints | [{}] | | tag | "disabled" | - And the graph projection is fully up to date When the command MoveNodeAggregate is executed with payload: | Key | Value | @@ -115,7 +110,6 @@ Feature: Move a node aggregate considering disable state but without content dim | dimensionSpacePoint | {} | | newParentNodeAggregateId | "sir-nodeward-nodington-iii" | | newSucceedingSiblingNodeAggregateId | null | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {} And VisibilityConstraints are set to "frontend" @@ -128,7 +122,6 @@ Feature: Move a node aggregate considering disable state but without content dim | nodeAggregateId | "sir-david-nodenborough" | | affectedDimensionSpacePoints | [{}] | | tag | "disabled" | - And the graph projection is fully up to date When the command MoveNodeAggregate is executed with payload: | Key | Value | @@ -136,7 +129,6 @@ Feature: Move a node aggregate considering disable state but without content dim | dimensionSpacePoint | {} | | newParentNodeAggregateId | "sir-nodeward-nodington-iii" | | newSucceedingSiblingNodeAggregateId | null | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {} And VisibilityConstraints are set to "frontend" @@ -156,7 +148,6 @@ Feature: Move a node aggregate considering disable state but without content dim | nodeAggregateId | "sir-nodeward-nodington-iii" | | affectedDimensionSpacePoints | [{}] | | tag | "disabled" | - And the graph projection is fully up to date When the command MoveNodeAggregate is executed with payload: | Key | Value | @@ -164,7 +155,6 @@ Feature: Move a node aggregate considering disable state but without content dim | dimensionSpacePoint | {} | | newParentNodeAggregateId | "sir-nodeward-nodington-iii" | | newSucceedingSiblingNodeAggregateId | null | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {} And VisibilityConstraints are set to "frontend" @@ -190,7 +180,6 @@ Feature: Move a node aggregate considering disable state but without content dim | dimensionSpacePoint | {} | | newParentNodeAggregateId | "sir-nodeward-nodington-iii" | | newSucceedingSiblingNodeAggregateId | null | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {} And VisibilityConstraints are set to "frontend" @@ -210,7 +199,6 @@ Feature: Move a node aggregate considering disable state but without content dim | dimensionSpacePoint | {} | | newParentNodeAggregateId | "sir-nodeward-nodington-iii" | | newSucceedingSiblingNodeAggregateId | null | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {} And VisibilityConstraints are set to "frontend" @@ -236,7 +224,6 @@ Feature: Move a node aggregate considering disable state but without content dim | dimensionSpacePoint | {} | | newParentNodeAggregateId | "sir-nodeward-nodington-iii" | | newSucceedingSiblingNodeAggregateId | null | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {} And VisibilityConstraints are set to "frontend" @@ -263,7 +250,6 @@ Feature: Move a node aggregate considering disable state but without content dim | dimensionSpacePoint | {} | | newParentNodeAggregateId | "nodimus-prime" | | newSucceedingSiblingNodeAggregateId | null | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {} And VisibilityConstraints are set to "frontend" @@ -289,7 +275,6 @@ Feature: Move a node aggregate considering disable state but without content dim | dimensionSpacePoint | {} | | newParentNodeAggregateId | "nodimus-prime" | | newSucceedingSiblingNodeAggregateId | null | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {} And VisibilityConstraints are set to "frontend" @@ -315,7 +300,6 @@ Feature: Move a node aggregate considering disable state but without content dim | dimensionSpacePoint | {} | | newParentNodeAggregateId | "nodimus-prime" | | newSucceedingSiblingNodeAggregateId | null | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {} And VisibilityConstraints are set to "frontend" @@ -336,7 +320,6 @@ Feature: Move a node aggregate considering disable state but without content dim | dimensionSpacePoint | {} | | newParentNodeAggregateId | "nodimus-prime" | | newSucceedingSiblingNodeAggregateId | null | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {} And VisibilityConstraints are set to "frontend" diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/08-NodeMove/MoveNodeAggregateWithoutDimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/08-NodeMove/MoveNodeAggregateWithoutDimensions.feature index 048a6738ceb..f6d913a28bb 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/08-NodeMove/MoveNodeAggregateWithoutDimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/08-NodeMove/MoveNodeAggregateWithoutDimensions.feature @@ -23,7 +23,6 @@ Feature: Move a node without content dimensions | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | @@ -59,7 +58,6 @@ Feature: Move a node without content dimensions | parentNodeAggregateId | "lady-eleonode-rootford" | | nodeName | "esquire" | | nodeAggregateClassification | "regular" | - And the graph projection is fully up to date Scenario: Move a node to the end of its siblings When the command MoveNodeAggregate is executed with payload: @@ -68,8 +66,6 @@ Feature: Move a node without content dimensions | dimensionSpacePoint | {} | | newParentNodeAggregateId | null | | newSucceedingSiblingNodeAggregateId | null | - - When the graph projection is fully up to date Then I expect the graph projection to consist of exactly 4 nodes And I expect a node identified by cs-identifier;lady-eleonode-rootford;{} to exist in the content graph And I expect a node identified by cs-identifier;sir-david-nodenborough;{} to exist in the content graph @@ -103,8 +99,6 @@ Feature: Move a node without content dimensions | dimensionSpacePoint | {} | | newParentNodeAggregateId | null | | newSucceedingSiblingNodeAggregateId | "sir-david-nodenborough" | - - When the graph projection is fully up to date Then I expect the graph projection to consist of exactly 4 nodes And I expect a node identified by cs-identifier;lady-eleonode-rootford;{} to exist in the content graph And I expect a node identified by cs-identifier;sir-david-nodenborough;{} to exist in the content graph @@ -142,7 +136,6 @@ Feature: Move a node without content dimensions | parentNodeAggregateId | "sir-nodeward-nodington-iii" | | nodeName | "other-document" | | nodeAggregateClassification | "regular" | - And the graph projection is fully up to date When the command MoveNodeAggregate is executed with payload: | Key | Value | | nodeAggregateId | "sir-david-nodenborough" | @@ -155,8 +148,6 @@ Feature: Move a node without content dimensions | contentStreamId | "cs-identifier" | | nodeAggregateId | "sir-david-nodenborough" | | nodeMoveMappings | [{"movedNodeOrigin":[],"newLocations":[{"coveredDimensionSpacePoint": [], "newParent": {"nodeAggregateId":"sir-nodeward-nodington-iii","originDimensionSpacePoint":[]}}]}] | - - When the graph projection is fully up to date Then I expect the graph projection to consist of exactly 5 nodes And I expect a node identified by cs-identifier;lady-eleonode-rootford;{} to exist in the content graph And I expect a node identified by cs-identifier;sir-david-nodenborough;{} to exist in the content graph @@ -201,8 +192,6 @@ Feature: Move a node without content dimensions | contentStreamId | "cs-identifier" | | nodeAggregateId | "nody-mc-nodeface" | | nodeMoveMappings | [{"movedNodeOrigin":[],"newLocations":[{"coveredDimensionSpacePoint": [],"newSucceedingSibling":{"nodeAggregateId":"sir-nodeward-nodington-iii","originDimensionSpacePoint":[], "parentNodeAggregateId": "lady-eleonode-rootford", "parentOriginDimensionSpacePoint": []}}]}] | - - When the graph projection is fully up to date Then I expect the graph projection to consist of exactly 4 nodes And I expect a node identified by cs-identifier;lady-eleonode-rootford;{} to exist in the content graph And I expect a node identified by cs-identifier;sir-david-nodenborough;{} to exist in the content graph diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/08-NodeMove/MoveNodeAggregate_NewParent_Dimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/08-NodeMove/MoveNodeAggregate_NewParent_Dimensions.feature index e2791f32b28..d8e7de04de8 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/08-NodeMove/MoveNodeAggregate_NewParent_Dimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/08-NodeMove/MoveNodeAggregate_NewParent_Dimensions.feature @@ -24,7 +24,6 @@ Feature: Move a node with content dimensions | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | @@ -100,7 +99,6 @@ Feature: Move a node with content dimensions | parentNodeAggregateId | "lady-eleonode-rootford" | | nodeName | "document2" | | nodeAggregateClassification | "regular" | - And the graph projection is fully up to date Scenario: Move a complete node aggregate to a new parent before the first of its new siblings When the command MoveNodeAggregate is executed with payload: @@ -109,7 +107,6 @@ Feature: Move a node with content dimensions | dimensionSpacePoint | {"language": "mul"} | | newParentNodeAggregateId | "sir-david-nodenborough" | | newSucceedingSiblingNodeAggregateId | "anthony-destinode" | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {"language": "mul"} And I expect node aggregate identifier "nody-mc-nodeface" and node path "document/child-document-n" to lead to node cs-identifier;nody-mc-nodeface;{"language": "mul"} @@ -128,7 +125,6 @@ Feature: Move a node with content dimensions | nodeAggregateId | "anthony-destinode" | | affectedOccupiedDimensionSpacePoints | [] | | affectedCoveredDimensionSpacePoints | [{"language": "gsw"}] | - And the graph projection is fully up to date When the command MoveNodeAggregate is executed with payload: | Key | Value | @@ -137,7 +133,6 @@ Feature: Move a node with content dimensions | newParentNodeAggregateId | "sir-david-nodenborough" | | newSucceedingSiblingNodeAggregateId | "anthony-destinode" | | relationDistributionStrategy | "gatherAll" | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {"language": "mul"} And I expect node aggregate identifier "nody-mc-nodeface" and node path "document/child-document-n" to lead to node cs-identifier;nody-mc-nodeface;{"language": "mul"} @@ -165,7 +160,6 @@ Feature: Move a node with content dimensions | dimensionSpacePoint | {"language": "mul"} | | newParentNodeAggregateId | "sir-david-nodenborough" | | newSucceedingSiblingNodeAggregateId | "berta-destinode" | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {"language": "mul"} And I expect node aggregate identifier "nody-mc-nodeface" and node path "document/child-document-n" to lead to node cs-identifier;nody-mc-nodeface;{"language": "mul"} @@ -185,7 +179,6 @@ Feature: Move a node with content dimensions | nodeAggregateId | "berta-destinode" | | affectedOccupiedDimensionSpacePoints | [] | | affectedCoveredDimensionSpacePoints | [{"language": "gsw"}] | - And the graph projection is fully up to date When the command MoveNodeAggregate is executed with payload: | Key | Value | @@ -193,7 +186,6 @@ Feature: Move a node with content dimensions | dimensionSpacePoint | {"language": "mul"} | | newParentNodeAggregateId | "sir-david-nodenborough" | | newSucceedingSiblingNodeAggregateId | "berta-destinode" | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {"language": "mul"} And I expect node aggregate identifier "nody-mc-nodeface" and node path "document/child-document-n" to lead to node cs-identifier;nody-mc-nodeface;{"language": "mul"} @@ -223,7 +215,6 @@ Feature: Move a node with content dimensions | nodeAggregateId | "carl-destinode" | | affectedOccupiedDimensionSpacePoints | [] | | affectedCoveredDimensionSpacePoints | [{"language": "gsw"}] | - And the graph projection is fully up to date When the command MoveNodeAggregate is executed with payload: | Key | Value | @@ -231,7 +222,6 @@ Feature: Move a node with content dimensions | dimensionSpacePoint | {"language": "mul"} | | newParentNodeAggregateId | "sir-david-nodenborough" | | newPrecedingSiblingNodeAggregateId | "berta-destinode" | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {"language": "mul"} And I expect node aggregate identifier "nody-mc-nodeface" and node path "document/child-document-n" to lead to node cs-identifier;nody-mc-nodeface;{"language": "mul"} @@ -260,7 +250,6 @@ Feature: Move a node with content dimensions | nodeAggregateId | "carl-destinode" | | affectedOccupiedDimensionSpacePoints | [] | | affectedCoveredDimensionSpacePoints | [{"language": "gsw"}] | - And the graph projection is fully up to date When the command MoveNodeAggregate is executed with payload: | Key | Value | @@ -268,7 +257,6 @@ Feature: Move a node with content dimensions | dimensionSpacePoint | {"language": "mul"} | | newParentNodeAggregateId | "sir-david-nodenborough" | | newSucceedingSiblingNodeAggregateId | null | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {"language": "mul"} And I expect node aggregate identifier "nody-mc-nodeface" and node path "document/child-document-n" to lead to node cs-identifier;nody-mc-nodeface;{"language": "mul"} @@ -297,7 +285,6 @@ Feature: Move a node with content dimensions | newParentNodeAggregateId | "sir-david-nodenborough" | | newSucceedingSiblingNodeAggregateId | null | | relationDistributionStrategy | "scatter" | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {"language": "mul"} And I expect node aggregate identifier "nody-mc-nodeface" and node path "esquire/child-document-n" to lead to node cs-identifier;nody-mc-nodeface;{"language": "mul"} @@ -323,7 +310,6 @@ Feature: Move a node with content dimensions | newParentNodeAggregateId | "sir-david-nodenborough" | | newSucceedingSiblingNodeAggregateId | null | | relationDistributionStrategy | "gatherSpecializations" | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {"language": "mul"} And I expect node aggregate identifier "nody-mc-nodeface" and node path "esquire/child-document-n" to lead to node cs-identifier;nody-mc-nodeface;{"language": "mul"} @@ -359,7 +345,6 @@ Feature: Move a node with content dimensions | newParentNodeAggregateId | "lady-abigail-nodenborough" | | newSucceedingSiblingNodeAggregateId | null | | relationDistributionStrategy | "scatter" | - And the graph projection is fully up to date When the command MoveNodeAggregate is executed with payload: | Key | Value | @@ -369,7 +354,6 @@ Feature: Move a node with content dimensions | newPrecedingSiblingNodeAggregateId | "anthony-destinode" | | newSucceedingSiblingNodeAggregateId | "berta-destinode" | | relationDistributionStrategy | "gatherAll" | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {"language": "mul"} Then I expect node aggregate identifier "nody-mc-nodeface" and node path "document/child-document-n" to lead to node cs-identifier;nody-mc-nodeface;{"language": "mul"} @@ -401,7 +385,6 @@ Feature: Move a node with content dimensions | newParentNodeAggregateId | "lady-abigail-nodenborough" | | newSucceedingSiblingNodeAggregateId | null | | relationDistributionStrategy | "scatter" | - And the graph projection is fully up to date When the command MoveNodeAggregate is executed with payload: | Key | Value | @@ -410,7 +393,6 @@ Feature: Move a node with content dimensions | newPrecedingSiblingNodeAggregateId | "anthony-destinode" | | newSucceedingSiblingNodeAggregateId | "berta-destinode" | | relationDistributionStrategy | "gatherAll" | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {"language": "mul"} Then I expect node aggregate identifier "nody-mc-nodeface" and node path "document/child-document-n" to lead to node cs-identifier;nody-mc-nodeface;{"language": "mul"} diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/08-NodeMove/MoveNodeAggregate_NoNewParent_Dimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/08-NodeMove/MoveNodeAggregate_NoNewParent_Dimensions.feature index fa4d0a3467f..6d9e95bb4e1 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/08-NodeMove/MoveNodeAggregate_NoNewParent_Dimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/08-NodeMove/MoveNodeAggregate_NoNewParent_Dimensions.feature @@ -24,7 +24,6 @@ Feature: Move a node with content dimensions | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | @@ -90,7 +89,6 @@ Feature: Move a node with content dimensions | parentNodeAggregateId | "lady-eleonode-rootford" | | nodeName | "esquire" | | nodeAggregateClassification | "regular" | - And the graph projection is fully up to date Scenario: Move a complete node aggregate before the first of its siblings When the command MoveNodeAggregate is executed with payload: @@ -99,7 +97,6 @@ Feature: Move a node with content dimensions | dimensionSpacePoint | {"language": "mul"} | | newParentNodeAggregateId | null | | newSucceedingSiblingNodeAggregateId | "anthony-destinode" | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {"language": "mul"} And I expect node aggregate identifier "nody-mc-nodeface" and node path "document/child-document-n" to lead to node cs-identifier;nody-mc-nodeface;{"language": "mul"} @@ -118,7 +115,6 @@ Feature: Move a node with content dimensions | nodeAggregateId | "anthony-destinode" | | affectedOccupiedDimensionSpacePoints | [] | | affectedCoveredDimensionSpacePoints | [{"language": "gsw"}] | - And the graph projection is fully up to date When the command MoveNodeAggregate is executed with payload: | Key | Value | @@ -127,7 +123,6 @@ Feature: Move a node with content dimensions | newParentNodeAggregateId | null | | newSucceedingSiblingNodeAggregateId | "anthony-destinode" | | relationDistributionStrategy | "gatherAll" | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {"language": "mul"} And I expect node aggregate identifier "nody-mc-nodeface" and node path "document/child-document-n" to lead to node cs-identifier;nody-mc-nodeface;{"language": "mul"} @@ -155,7 +150,6 @@ Feature: Move a node with content dimensions | dimensionSpacePoint | {"language": "mul"} | | newParentNodeAggregateId | null | | newSucceedingSiblingNodeAggregateId | "berta-destinode" | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {"language": "mul"} And I expect node aggregate identifier "nody-mc-nodeface" and node path "document/child-document-n" to lead to node cs-identifier;nody-mc-nodeface;{"language": "mul"} @@ -175,7 +169,6 @@ Feature: Move a node with content dimensions | nodeAggregateId | "berta-destinode" | | affectedOccupiedDimensionSpacePoints | [] | | affectedCoveredDimensionSpacePoints | [{"language": "gsw"}] | - And the graph projection is fully up to date When the command MoveNodeAggregate is executed with payload: | Key | Value | @@ -183,7 +176,6 @@ Feature: Move a node with content dimensions | dimensionSpacePoint | {"language": "mul"} | | newParentNodeAggregateId | null | | newSucceedingSiblingNodeAggregateId | "berta-destinode" | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {"language": "mul"} And I expect node aggregate identifier "nody-mc-nodeface" and node path "document/child-document-n" to lead to node cs-identifier;nody-mc-nodeface;{"language": "mul"} @@ -213,7 +205,6 @@ Feature: Move a node with content dimensions | nodeAggregateId | "carl-destinode" | | affectedOccupiedDimensionSpacePoints | [] | | affectedCoveredDimensionSpacePoints | [{"language": "gsw"}] | - And the graph projection is fully up to date When the command MoveNodeAggregate is executed with payload: | Key | Value | @@ -221,7 +212,6 @@ Feature: Move a node with content dimensions | dimensionSpacePoint | {"language": "mul"} | | newParentNodeAggregateId | null | | newPrecedingSiblingNodeAggregateId | "berta-destinode" | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {"language": "mul"} And I expect node aggregate identifier "nody-mc-nodeface" and node path "document/child-document-n" to lead to node cs-identifier;nody-mc-nodeface;{"language": "mul"} @@ -250,7 +240,6 @@ Feature: Move a node with content dimensions | nodeAggregateId | "carl-destinode" | | affectedOccupiedDimensionSpacePoints | [] | | affectedCoveredDimensionSpacePoints | [{"language": "gsw"}] | - And the graph projection is fully up to date When the command MoveNodeAggregate is executed with payload: | Key | Value | @@ -258,7 +247,6 @@ Feature: Move a node with content dimensions | dimensionSpacePoint | {"language": "mul"} | | newParentNodeAggregateId | null | | newSucceedingSiblingNodeAggregateId | null | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {"language": "mul"} And I expect node aggregate identifier "nody-mc-nodeface" and node path "document/child-document-n" to lead to node cs-identifier;nody-mc-nodeface;{"language": "mul"} @@ -286,7 +274,6 @@ Feature: Move a node with content dimensions | dimensionSpacePoint | {"language": "mul"} | | newSucceedingSiblingNodeAggregateId | "anthony-destinode" | | relationDistributionStrategy | "scatter" | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {"language": "mul"} And I expect node aggregate identifier "nody-mc-nodeface" and node path "document/child-document-n" to lead to node cs-identifier;nody-mc-nodeface;{"language": "mul"} @@ -316,7 +303,6 @@ Feature: Move a node with content dimensions | dimensionSpacePoint | {"language": "mul"} | | newSucceedingSiblingNodeAggregateId | "berta-destinode" | | relationDistributionStrategy | "scatter" | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {"language": "mul"} And I expect node aggregate identifier "nody-mc-nodeface" and node path "document/child-document-n" to lead to node cs-identifier;nody-mc-nodeface;{"language": "mul"} @@ -346,7 +332,6 @@ Feature: Move a node with content dimensions | nodeAggregateId | "nody-mc-nodeface" | | dimensionSpacePoint | {"language": "mul"} | | relationDistributionStrategy | "scatter" | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {"language": "mul"} And I expect node aggregate identifier "nody-mc-nodeface" and node path "document/child-document-n" to lead to node cs-identifier;nody-mc-nodeface;{"language": "mul"} @@ -376,7 +361,6 @@ Feature: Move a node with content dimensions | dimensionSpacePoint | {"language": "de"} | | newSucceedingSiblingNodeAggregateId | "anthony-destinode" | | relationDistributionStrategy | "gatherSpecializations" | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {"language": "mul"} And I expect node aggregate identifier "nody-mc-nodeface" and node path "document/child-document-n" to lead to node cs-identifier;nody-mc-nodeface;{"language": "mul"} @@ -416,7 +400,6 @@ Feature: Move a node with content dimensions | dimensionSpacePoint | {"language": "de"} | | newSucceedingSiblingNodeAggregateId | "berta-destinode" | | relationDistributionStrategy | "gatherSpecializations" | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {"language": "mul"} And I expect node aggregate identifier "nody-mc-nodeface" and node path "document/child-document-n" to lead to node cs-identifier;nody-mc-nodeface;{"language": "mul"} @@ -457,7 +440,6 @@ Feature: Move a node with content dimensions | nodeAggregateId | "nody-mc-nodeface" | | dimensionSpacePoint | {"language": "de"} | | relationDistributionStrategy | "gatherSpecializations" | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {"language": "mul"} And I expect node aggregate identifier "nody-mc-nodeface" and node path "document/child-document-n" to lead to node cs-identifier;nody-mc-nodeface;{"language": "mul"} @@ -510,49 +492,41 @@ Feature: Move a node with content dimensions | Key | Value | | nodeAggregateId | "lady-nodette-nodington-ii" | | newSucceedingSiblingNodeAggregateId | "lady-nodette-nodington-x" | - And the graph projection is fully up to date # distance iii to x: 32 And the command MoveNodeAggregate is executed with payload: | Key | Value | | nodeAggregateId | "lady-nodette-nodington-iii" | | newSucceedingSiblingNodeAggregateId | "lady-nodette-nodington-x" | - And the graph projection is fully up to date # distance iv to x: 16 And the command MoveNodeAggregate is executed with payload: | Key | Value | | nodeAggregateId | "lady-nodette-nodington-iv" | | newSucceedingSiblingNodeAggregateId | "lady-nodette-nodington-x" | - And the graph projection is fully up to date # distance v to x: 8 And the command MoveNodeAggregate is executed with payload: | Key | Value | | nodeAggregateId | "lady-nodette-nodington-v" | | newSucceedingSiblingNodeAggregateId | "lady-nodette-nodington-x" | - And the graph projection is fully up to date # distance vi to x: 4 And the command MoveNodeAggregate is executed with payload: | Key | Value | | nodeAggregateId | "lady-nodette-nodington-vi" | | newSucceedingSiblingNodeAggregateId | "lady-nodette-nodington-x" | - And the graph projection is fully up to date # distance vii to x: 2 And the command MoveNodeAggregate is executed with payload: | Key | Value | | nodeAggregateId | "lady-nodette-nodington-vii" | | newSucceedingSiblingNodeAggregateId | "lady-nodette-nodington-x" | - And the graph projection is fully up to date # distance viii to x: 1 -> reorder -> 128 And the command MoveNodeAggregate is executed with payload: | Key | Value | | nodeAggregateId | "lady-nodette-nodington-viii" | | newSucceedingSiblingNodeAggregateId | "lady-nodette-nodington-x" | - And the graph projection is fully up to date # distance ix to x: 64 after reorder And the command MoveNodeAggregate is executed with payload: | Key | Value | | nodeAggregateId | "lady-nodette-nodington-ix" | | newSucceedingSiblingNodeAggregateId | "lady-nodette-nodington-x" | - And the graph projection is fully up to date Then I expect node aggregate identifier "lady-eleonode-rootford" to lead to node cs-identifier;lady-eleonode-rootford;{} And I expect this node to have the following child nodes: diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ContentStreamClosing/01-CloseContentStream_ConstraintChecks.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ContentStreamClosing/01-CloseContentStream_ConstraintChecks.feature index d991eb4fd5b..595c2e53055 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ContentStreamClosing/01-CloseContentStream_ConstraintChecks.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ContentStreamClosing/01-CloseContentStream_ConstraintChecks.feature @@ -13,7 +13,6 @@ Feature: Constraint check test cases for closing content streams | Key | Value | | workspaceName | "live" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date Scenario: Try to close a non-existing content stream: And the command CloseContentStream is executed with payload and exceptions are caught: diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ContentStreamForking/01-ForkContentStream_ConstraintChecks.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ContentStreamForking/01-ForkContentStream_ConstraintChecks.feature index 8d25d71e03a..5549e48c277 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ContentStreamForking/01-ForkContentStream_ConstraintChecks.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ContentStreamForking/01-ForkContentStream_ConstraintChecks.feature @@ -23,7 +23,6 @@ Feature: ForkContentStream Without Dimensions | Key | Value | | workspaceName | "live" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ContentStreamForking/ForkContentStreamWithDisabledNodesWithoutDimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ContentStreamForking/ForkContentStreamWithDisabledNodesWithoutDimensions.feature index dcc5fad2036..14ca6926302 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ContentStreamForking/ForkContentStreamWithDisabledNodesWithoutDimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ContentStreamForking/ForkContentStreamWithDisabledNodesWithoutDimensions.feature @@ -22,7 +22,6 @@ Feature: On forking a content stream, hidden nodes should be correctly copied as | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | @@ -48,13 +47,11 @@ Feature: On forking a content stream, hidden nodes should be correctly copied as | parentNodeAggregateId | "the-great-nodini" | | nodeName | "pet" | | nodeAggregateClassification | "regular" | - And the graph projection is fully up to date And the command DisableNodeAggregate is executed with payload: | Key | Value | | nodeAggregateId | "the-great-nodini" | | coveredDimensionSpacePoint | {} | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date Scenario: on ForkContentStream, the disabled nodes in the target content stream should still be invisible. When the command ForkContentStream is executed with payload: @@ -62,8 +59,6 @@ Feature: On forking a content stream, hidden nodes should be correctly copied as | sourceContentStreamId | "cs-identifier" | | contentStreamId | "user-cs-identifier" | - When the graph projection is fully up to date - # node aggregate occupation and coverage is not relevant without dimensions and thus not tested When I am in content stream "user-cs-identifier" and dimension space point {} diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ContentStreamForking/ForkContentStreamWithoutDimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ContentStreamForking/ForkContentStreamWithoutDimensions.feature index e7b8197080c..fe5f1530f6b 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ContentStreamForking/ForkContentStreamWithoutDimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ContentStreamForking/ForkContentStreamWithoutDimensions.feature @@ -23,7 +23,6 @@ Feature: ForkContentStream Without Dimensions | Key | Value | | workspaceName | "live" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | @@ -53,7 +52,6 @@ Feature: ForkContentStream Without Dimensions | Key | Value | | contentStreamId | "user-cs-identifier" | | sourceContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in content stream "user-cs-identifier" and dimension space point {} Then I expect node aggregate identifier "nody-mc-nodeface" to lead to node user-cs-identifier;nody-mc-nodeface;{} @@ -71,7 +69,6 @@ Feature: ForkContentStream Without Dimensions | affectedDimensionSpacePoints | [{}] | | propertyValues | {"text": {"value": "modified value", "type": "string"}} | | propertiesToUnset | {} | - And the graph projection is fully up to date # live When I am in content stream "cs-identifier" and dimension space point {} @@ -101,7 +98,6 @@ Feature: ForkContentStream Without Dimensions | affectedDimensionSpacePoints | [{}] | | propertyValues | {"text": {"value": "modified value", "type": "string"}} | | propertiesToUnset | {} | - And the graph projection is fully up to date # live When I am in content stream "cs-identifier" and dimension space point {} diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ContentStreamForking/NodeReferencesOnForkContentStream.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ContentStreamForking/NodeReferencesOnForkContentStream.feature index e8b6e164bc4..247d1ee36c3 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ContentStreamForking/NodeReferencesOnForkContentStream.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ContentStreamForking/NodeReferencesOnForkContentStream.feature @@ -28,13 +28,11 @@ Feature: On forking a content stream, node references should be copied as well. | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"de"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | nodeTypeName | parentNodeAggregateId | | source-nodandaise | Neos.ContentRepository.Testing:NodeWithReferences | lady-eleonode-rootford | @@ -46,13 +44,11 @@ Feature: On forking a content stream, node references should be copied as well. | sourceNodeAggregateId | "source-nodandaise" | | referenceName | "referenceProperty" | | references | [{"target": "anthony-destinode"}] | - And the graph projection is fully up to date When the command ForkContentStream is executed with payload: | Key | Value | | contentStreamId | "user-cs-identifier" | | sourceContentStreamId | "cs-identifier" | - And the graph projection is fully up to date # after forking, the reference must still exist on the forked content stream (no surprises here). When I am in content stream "user-cs-identifier" and dimension space point {"language": "de"} @@ -82,7 +78,6 @@ Feature: On forking a content stream, node references should be copied as well. | Key | Value | | nodeAggregateId | "source-nodandaise" | | propertyValues | {"text": "Modified in live workspace"} | - And the graph projection is fully up to date Then I expect node aggregate identifier "source-nodandaise" to lead to node user-cs-identifier;source-nodandaise;{"language": "de"} And I expect this node to have the following references: | Name | Node | Properties | diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/AddDimensionShineThrough.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/AddDimensionShineThrough.feature index b8e3d750c59..6decc482fb0 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/AddDimensionShineThrough.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/AddDimensionShineThrough.feature @@ -37,13 +37,11 @@ Feature: Add Dimension Specialization | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in workspace "live" And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date # Node /document When the command CreateNodeAggregateWithNode is executed with payload: | Key | Value | @@ -52,7 +50,6 @@ Feature: Add Dimension Specialization | originDimensionSpacePoint | {"language": "de"} | | parentNodeAggregateId | "lady-eleonode-rootford" | | initialPropertyValues | {"text": "hello" } | - And the graph projection is fully up to date Scenario: Success Case - simple # we change the dimension configuration @@ -110,7 +107,6 @@ Feature: Add Dimension Specialization | nodeAggregateId | "sir-david-nodenborough" | | originDimensionSpacePoint | {"language": "de"} | | propertyValues | {"text": "changed"} | - And the graph projection is fully up to date When I am in content stream "migration-cs" and dimension space point {"language": "de"} Then I expect node aggregate identifier "sir-david-nodenborough" to lead to node migration-cs;sir-david-nodenborough;{"language": "de"} And I expect this node to have the following properties: @@ -142,7 +138,6 @@ Feature: Add Dimension Specialization | nodeAggregateId | "sir-david-nodenborough" | | coveredDimensionSpacePoint | {"language": "de"} | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date # ensure the node is disabled When I am in the active content stream of workspace "live" and dimension space point {"language": "de"} diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/AddNewProperty_NoDimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/AddNewProperty_NoDimensions.feature index e99b20f0e24..7be8ec1a867 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/AddNewProperty_NoDimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/AddNewProperty_NoDimensions.feature @@ -22,13 +22,11 @@ Feature: Add New Property | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date # Node /document When the command CreateNodeAggregateWithNode is executed with payload: | Key | Value | @@ -37,7 +35,6 @@ Feature: Add New Property | originDimensionSpacePoint | {} | | parentNodeAggregateId | "lady-eleonode-rootford" | | initialPropertyValues | {"text": "Original text"} | - And the graph projection is fully up to date # Node /doc2 When the command CreateNodeAggregateWithNode is executed with payload: @@ -47,7 +44,6 @@ Feature: Add New Property | originDimensionSpacePoint | {} | | parentNodeAggregateId | "lady-eleonode-rootford" | | initialPropertyValues | {} | - And the graph projection is fully up to date Scenario: Fixed newValue diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/ChangePropertyValue_Dimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/ChangePropertyValue_Dimensions.feature index bd52c8d1d2b..03dd8da6566 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/ChangePropertyValue_Dimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/ChangePropertyValue_Dimensions.feature @@ -28,13 +28,11 @@ Feature: Change Property Value across dimensions; and test DimensionSpacePoints | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date # Node /document (in "de") When the command CreateNodeAggregateWithNode is executed with payload: | Key | Value | @@ -43,7 +41,6 @@ Feature: Change Property Value across dimensions; and test DimensionSpacePoints | originDimensionSpacePoint | {"language": "de"} | | parentNodeAggregateId | "lady-eleonode-rootford" | | initialPropertyValues | {"text": "Original text"} | - And the graph projection is fully up to date # Node /document (in "en") When the command CreateNodeVariant is executed with payload: @@ -51,7 +48,6 @@ Feature: Change Property Value across dimensions; and test DimensionSpacePoints | nodeAggregateId | "sir-david-nodenborough" | | sourceOrigin | {"language":"de"} | | targetOrigin | {"language":"en"} | - And the graph projection is fully up to date Scenario: change materialized "de" node, should shine through in "ch", but not in "en" @@ -124,7 +120,6 @@ Feature: Change Property Value across dimensions; and test DimensionSpacePoints | nodeAggregateId | "sir-david-nodenborough" | | sourceOrigin | {"language":"de"} | | targetOrigin | {"language":"ch"} | - And the graph projection is fully up to date When I run the following node migration for workspace "live", creating content streams "migration-cs": """yaml @@ -170,7 +165,6 @@ Feature: Change Property Value across dimensions; and test DimensionSpacePoints | nodeAggregateId | "sir-david-nodenborough" | | sourceOrigin | {"language":"de"} | | targetOrigin | {"language":"ch"} | - And the graph projection is fully up to date When I run the following node migration for workspace "live", creating content streams "migration-cs": """yaml diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/ChangePropertyValue_NoDimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/ChangePropertyValue_NoDimensions.feature index 2c3ae2d9969..098cb26c3e6 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/ChangePropertyValue_NoDimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/ChangePropertyValue_NoDimensions.feature @@ -23,13 +23,11 @@ Feature: Change Property | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date # Node /document When the command CreateNodeAggregateWithNode is executed with payload: | Key | Value | @@ -38,7 +36,6 @@ Feature: Change Property | originDimensionSpacePoint | {} | | parentNodeAggregateId | "lady-eleonode-rootford" | | initialPropertyValues | {"text": "Original text"} | - And the graph projection is fully up to date Scenario: Fixed newValue diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/Filter_NodeName_NoDimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/Filter_NodeName_NoDimensions.feature index 0958d6cf1f4..d92749e4168 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/Filter_NodeName_NoDimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/Filter_NodeName_NoDimensions.feature @@ -24,12 +24,10 @@ Feature: Filter - Node Name | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | And I am in the active content stream of workspace "live" - And the graph projection is fully up to date And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date # Node /name1 When the command CreateNodeAggregateWithNode is executed with payload: | Key | Value | @@ -39,7 +37,6 @@ Feature: Filter - Node Name | originDimensionSpacePoint | {} | | parentNodeAggregateId | "lady-eleonode-rootford" | | initialPropertyValues | {"text": "Original name1"} | - And the graph projection is fully up to date # Node /name2 When the command CreateNodeAggregateWithNode is executed with payload: @@ -50,7 +47,6 @@ Feature: Filter - Node Name | originDimensionSpacePoint | {} | | parentNodeAggregateId | "lady-eleonode-rootford" | | initialPropertyValues | {"text": "Original name2"} | - And the graph projection is fully up to date # no node name When the command CreateNodeAggregateWithNode is executed with payload: @@ -60,7 +56,6 @@ Feature: Filter - Node Name | originDimensionSpacePoint | {} | | parentNodeAggregateId | "lady-eleonode-rootford" | | initialPropertyValues | {"text": "no node name"} | - And the graph projection is fully up to date Scenario: Fixed newValue diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/Filter_PropertyNotEmpty_NoDimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/Filter_PropertyNotEmpty_NoDimensions.feature index 103e8290d27..b7097579661 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/Filter_PropertyNotEmpty_NoDimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/Filter_PropertyNotEmpty_NoDimensions.feature @@ -23,13 +23,11 @@ Feature: Filter - Property not empty | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date # Node /name1 (has text value set) When the command CreateNodeAggregateWithNode is executed with payload: | Key | Value | @@ -39,7 +37,6 @@ Feature: Filter - Property not empty | originDimensionSpacePoint | {} | | parentNodeAggregateId | "lady-eleonode-rootford" | | initialPropertyValues | {"text": "Original name1"} | - And the graph projection is fully up to date # Node /name2 (has text value empty) When the command CreateNodeAggregateWithNode is executed with payload: @@ -50,7 +47,6 @@ Feature: Filter - Property not empty | originDimensionSpacePoint | {} | | parentNodeAggregateId | "lady-eleonode-rootford" | | initialPropertyValues | {"text": ""} | - And the graph projection is fully up to date # no node name (has text value not set) When the command CreateNodeAggregateWithNode is executed with payload: @@ -60,7 +56,6 @@ Feature: Filter - Property not empty | originDimensionSpacePoint | {} | | parentNodeAggregateId | "lady-eleonode-rootford" | | initialPropertyValues | {"text": null} | - And the graph projection is fully up to date # no node name (has text value not set, and null will be ignored as unset) When the command CreateNodeAggregateWithNode is executed with payload: @@ -70,7 +65,6 @@ Feature: Filter - Property not empty | originDimensionSpacePoint | {} | | parentNodeAggregateId | "lady-eleonode-rootford" | | initialPropertyValues | {} | - And the graph projection is fully up to date Scenario: PropertyNotEmpty diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/Filter_PropertyValue_NoDimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/Filter_PropertyValue_NoDimensions.feature index b3e314fab70..42b2d4e8e2b 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/Filter_PropertyValue_NoDimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/Filter_PropertyValue_NoDimensions.feature @@ -24,12 +24,10 @@ Feature: Filter - Property Value | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | And I am in the active content stream of workspace "live" - And the graph projection is fully up to date And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date # Node /name1 (has text value set) When the command CreateNodeAggregateWithNode is executed with payload: | Key | Value | @@ -39,7 +37,6 @@ Feature: Filter - Property Value | originDimensionSpacePoint | {} | | parentNodeAggregateId | "lady-eleonode-rootford" | | initialPropertyValues | {"text": "Original name1"} | - And the graph projection is fully up to date # Node /name2 (has text value2) When the command CreateNodeAggregateWithNode is executed with payload: @@ -50,7 +47,6 @@ Feature: Filter - Property Value | originDimensionSpacePoint | {} | | parentNodeAggregateId | "lady-eleonode-rootford" | | initialPropertyValues | {"text": "value2"} | - And the graph projection is fully up to date # no node name (has text value not set, and null will be ignored as unset) When the command CreateNodeAggregateWithNode is executed with payload: @@ -60,7 +56,6 @@ Feature: Filter - Property Value | originDimensionSpacePoint | {} | | parentNodeAggregateId | "lady-eleonode-rootford" | | initialPropertyValues | {"text": null} | - And the graph projection is fully up to date # no node name (has text value not set) When the command CreateNodeAggregateWithNode is executed with payload: @@ -70,7 +65,6 @@ Feature: Filter - Property Value | originDimensionSpacePoint | {} | | parentNodeAggregateId | "lady-eleonode-rootford" | | initialPropertyValues | {} | - And the graph projection is fully up to date Scenario: PropertyValue diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/MoveDimensionSpacePoint.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/MoveDimensionSpacePoint.feature index c3a56b5605b..47ef3a7246c 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/MoveDimensionSpacePoint.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/MoveDimensionSpacePoint.feature @@ -36,12 +36,10 @@ Feature: Move dimension space point | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | And I am in the active content stream of workspace "live" - And the graph projection is fully up to date And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date # Node /document When the command CreateNodeAggregateWithNode is executed with payload: | Key | Value | @@ -49,7 +47,6 @@ Feature: Move dimension space point | nodeTypeName | "Neos.ContentRepository.Testing:Document" | | originDimensionSpacePoint | {"language": "de"} | | parentNodeAggregateId | "lady-eleonode-rootford" | - And the graph projection is fully up to date Scenario: Success Case - simple @@ -93,7 +90,6 @@ Feature: Move dimension space point | nodeAggregateId | "sir-david-nodenborough" | | coveredDimensionSpacePoint | {"language": "de"} | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date # ensure the node is disabled When I am in the active content stream of workspace "live" and dimension space point {"language": "de"} diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/NodeTypeAdjustment_Dimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/NodeTypeAdjustment_Dimensions.feature index b4394b7679f..b082e9189e3 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/NodeTypeAdjustment_Dimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/NodeTypeAdjustment_Dimensions.feature @@ -29,13 +29,11 @@ Feature: Adjust node types with a node migration | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date # Node /document When the command CreateNodeAggregateWithNode is executed with payload: | Key | Value | @@ -43,7 +41,6 @@ Feature: Adjust node types with a node migration | nodeTypeName | "Neos.ContentRepository.Testing:Document" | | originDimensionSpacePoint | {"language": "de"} | | parentNodeAggregateId | "lady-eleonode-rootford" | - And the graph projection is fully up to date ######################## # Actual Test diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/NodeTypeAdjustment_NoDimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/NodeTypeAdjustment_NoDimensions.feature index afd94e15f65..ec99edccbdd 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/NodeTypeAdjustment_NoDimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/NodeTypeAdjustment_NoDimensions.feature @@ -27,13 +27,11 @@ Feature: Adjust node types with a node migration | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date # Node /document When the command CreateNodeAggregateWithNode is executed with payload: | Key | Value | @@ -41,7 +39,6 @@ Feature: Adjust node types with a node migration | nodeTypeName | "Neos.ContentRepository.Testing:Document" | | originDimensionSpacePoint | {} | | parentNodeAggregateId | "lady-eleonode-rootford" | - And the graph projection is fully up to date ######################## # Actual Test diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/RemoveNodes_Dimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/RemoveNodes_Dimensions.feature index 9498e574b49..7332a9ffc21 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/RemoveNodes_Dimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/RemoveNodes_Dimensions.feature @@ -26,13 +26,11 @@ Feature: Remove Nodes | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date # Node /document (in "de") When the command CreateNodeAggregateWithNode is executed with payload: | Key | Value | @@ -41,7 +39,6 @@ Feature: Remove Nodes | originDimensionSpacePoint | {"language": "de"} | | parentNodeAggregateId | "lady-eleonode-rootford" | | initialPropertyValues | {"text": "Original text"} | - And the graph projection is fully up to date # Node /document (in "en") When the command CreateNodeVariant is executed with payload: @@ -49,7 +46,6 @@ Feature: Remove Nodes | nodeAggregateId | "sir-david-nodenborough" | | sourceOrigin | {"language":"de"} | | targetOrigin | {"language":"en"} | - And the graph projection is fully up to date Scenario: Remove nodes in a given dimension space point removes the node with all virtual specializations diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/RemoveProperty_NoDimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/RemoveProperty_NoDimensions.feature index 399bcf84a1d..3d42e1a7619 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/RemoveProperty_NoDimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/RemoveProperty_NoDimensions.feature @@ -23,13 +23,11 @@ Feature: Remove Property | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date # Node /document When the command CreateNodeAggregateWithNode is executed with payload: | Key | Value | @@ -38,7 +36,6 @@ Feature: Remove Property | originDimensionSpacePoint | {} | | parentNodeAggregateId | "lady-eleonode-rootford" | | initialPropertyValues | {"text": "Original text"} | - And the graph projection is fully up to date Scenario: Fixed newValue diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/RenameNodeAggregate_Dimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/RenameNodeAggregate_Dimensions.feature index 2842fc39a2d..29186760c63 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/RenameNodeAggregate_Dimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/RenameNodeAggregate_Dimensions.feature @@ -26,13 +26,11 @@ Feature: Rename Node Aggregate | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date # Node /document (in "de") When the command CreateNodeAggregateWithNode is executed with payload: | Key | Value | @@ -42,7 +40,6 @@ Feature: Rename Node Aggregate | originDimensionSpacePoint | {"language": "de"} | | parentNodeAggregateId | "lady-eleonode-rootford" | | initialPropertyValues | {"text": "Original text"} | - And the graph projection is fully up to date # Node /document (in "en") When the command CreateNodeVariant is executed with payload: @@ -50,7 +47,6 @@ Feature: Rename Node Aggregate | nodeAggregateId | "sir-david-nodenborough" | | sourceOrigin | {"language":"de"} | | targetOrigin | {"language":"en"} | - And the graph projection is fully up to date Scenario: Rename Node Aggregate diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/RenameProperty_NoDimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/RenameProperty_NoDimensions.feature index b63569bd20f..ef81383da0b 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/RenameProperty_NoDimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/RenameProperty_NoDimensions.feature @@ -23,13 +23,11 @@ Feature: Rename Property | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date # Node /document When the command CreateNodeAggregateWithNode is executed with payload: | Key | Value | @@ -38,7 +36,6 @@ Feature: Rename Property | originDimensionSpacePoint | {} | | parentNodeAggregateId | "lady-eleonode-rootford" | | initialPropertyValues | {"text": "Original text"} | - And the graph projection is fully up to date Scenario: Fixed newValue diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/StripTagsOnProperty_NoDimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/StripTagsOnProperty_NoDimensions.feature index 987cbc19287..5e2f0fe8723 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/StripTagsOnProperty_NoDimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/StripTagsOnProperty_NoDimensions.feature @@ -23,13 +23,11 @@ Feature: Strip Tags on Property | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date # Node /document When the command CreateNodeAggregateWithNode is executed with payload: | Key | Value | @@ -38,7 +36,6 @@ Feature: Strip Tags on Property | originDimensionSpacePoint | {} | | parentNodeAggregateId | "lady-eleonode-rootford" | | initialPropertyValues | {"text": "Original

text

"} | - And the graph projection is fully up to date Scenario: Fixed newValue diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeCopying/CopyNode_NoDimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeCopying/CopyNode_NoDimensions.feature index 28634b325b5..84cb41299ba 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeCopying/CopyNode_NoDimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeCopying/CopyNode_NoDimensions.feature @@ -15,7 +15,6 @@ Feature: Copy nodes (without dimensions) | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | @@ -51,7 +50,6 @@ Feature: Copy nodes (without dimensions) | parentNodeAggregateId | "lady-eleonode-rootford" | | nodeName | "esquire" | | nodeAggregateClassification | "regular" | - And the graph projection is fully up to date Scenario: Copy When I am in the active content stream of workspace "live" and dimension space point {} @@ -64,6 +62,4 @@ Feature: Copy nodes (without dimensions) | targetNodeName | "target-nn" | | targetSucceedingSiblingnodeAggregateId | null | | nodeAggregateIdMapping | {"sir-nodeward-nodington-iii": "sir-nodeward-nodington-iii-copy"} | - - And the graph projection is fully up to date Then I expect node aggregate identifier "sir-nodeward-nodington-iii-copy" to lead to node cs-identifier;sir-nodeward-nodington-iii-copy;{} diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodePropertyConversion/NodePropertyConversion.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodePropertyConversion/NodePropertyConversion.feature index 77aa2b318ad..36662573aa4 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodePropertyConversion/NodePropertyConversion.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodePropertyConversion/NodePropertyConversion.feature @@ -16,13 +16,11 @@ Feature: Node Property Conversion | Key | Value | | workspaceName | "live" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date Scenario: DateTime objects at Node Creation When the command CreateNodeAggregateWithNode is executed with payload: @@ -33,8 +31,6 @@ Feature: Node Property Conversion | parentNodeAggregateId | "lady-eleonode-rootford" | | initialPropertyValues | {"dateProperty": "Date:1997-07-16T19:20:30+05:00"} | - And the graph projection is fully up to date - When I am in the active content stream of workspace "live" and dimension space point {} Then I expect node aggregate identifier "nody-mc-nodeface" to lead to node cs-identifier;nody-mc-nodeface;{} And I expect this node to have the following properties: @@ -49,14 +45,12 @@ Feature: Node Property Conversion | originDimensionSpacePoint | {} | | parentNodeAggregateId | "lady-eleonode-rootford" | | initialPropertyValues | {"dateProperty": "Date:1997-07-16T19:20:30+05:00"} | - And the graph projection is fully up to date When the command SetNodeProperties is executed with payload: | Key | Value | | nodeAggregateId | "nody-mc-nodeface" | | originDimensionSpacePoint | {} | | propertyValues | {"dateProperty": "Date:1997-07-19T19:20:30+05:00"} | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {} Then I expect node aggregate identifier "nody-mc-nodeface" to lead to node cs-identifier;nody-mc-nodeface;{} diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeRemoval/RemoveNodeAggregateAfterDisabling.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeRemoval/RemoveNodeAggregateAfterDisabling.feature index f6355585dc0..caae21a7333 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeRemoval/RemoveNodeAggregateAfterDisabling.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeRemoval/RemoveNodeAggregateAfterDisabling.feature @@ -23,13 +23,11 @@ Feature: Disable a node aggregate | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | nodeTypeName | parentNodeAggregateId | nodeName | | preceding-nodenborough | Neos.ContentRepository.Testing:Document | lady-eleonode-rootford | preceding-document | @@ -41,7 +39,6 @@ Feature: Disable a node aggregate | sourceNodeAggregateId | "preceding-nodenborough" | | referenceName | "references" | | references | [{"target": "sir-david-nodenborough"}] | - And the graph projection is fully up to date Scenario: Restore a hidden node by removing and recreating it Given the command DisableNodeAggregate is executed with payload: @@ -54,7 +51,6 @@ Feature: Disable a node aggregate | nodeAggregateId | "nody-mc-nodeface" | | affectedOccupiedDimensionSpacePoints | [{}] | | affectedCoveredDimensionSpacePoints | [{}] | - And the graph projection is fully up to date When the command CreateNodeAggregateWithNodeAndSerializedProperties is executed with payload: | Key | Value | @@ -63,8 +59,6 @@ Feature: Disable a node aggregate | originDimensionSpacePoint | {} | | parentNodeAggregateId | "sir-david-nodenborough" | | nodeName | "child-document" | - - When the graph projection is fully up to date And I am in the active content stream of workspace "live" Then I expect the graph projection to consist of exactly 5 nodes And I expect a node identified by cs-identifier;lady-eleonode-rootford;{} to exist in the content graph diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeRemoval/RemoveNodeAggregateWithDimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeRemoval/RemoveNodeAggregateWithDimensions.feature index 9f44a74c9c0..f70998f7b1f 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeRemoval/RemoveNodeAggregateWithDimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeRemoval/RemoveNodeAggregateWithDimensions.feature @@ -19,13 +19,11 @@ Feature: Remove NodeAggregate | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "live-cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"de"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-nodesworth" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date # We have to add another node since root nodes are in all dimension space points and thus cannot be varied # Node /document And the command CreateNodeAggregateWithNodeAndSerializedProperties is executed with payload: @@ -34,7 +32,6 @@ Feature: Remove NodeAggregate | nodeTypeName | "Neos.ContentRepository.Testing:Document" | | parentNodeAggregateId | "lady-eleonode-nodesworth" | | nodeName | "document" | - And the graph projection is fully up to date # We also want to add a child node to make sure it is correctly removed when the parent is removed # Node /document/child-document And the command CreateNodeAggregateWithNodeAndSerializedProperties is executed with payload: @@ -43,13 +40,11 @@ Feature: Remove NodeAggregate | nodeTypeName | "Neos.ContentRepository.Testing:Document" | | parentNodeAggregateId | "nody-mc-nodeface" | | nodeName | "child-document" | - And the graph projection is fully up to date And the command CreateNodeVariant is executed with payload: | Key | Value | | nodeAggregateId | "nody-mc-nodeface" | | sourceOrigin | {"language":"de"} | | targetOrigin | {"language":"gsw"} | - And the graph projection is fully up to date ######################## # Section: EXTRA testcases @@ -60,7 +55,6 @@ Feature: Remove NodeAggregate | nodeAggregateId | "nody-mc-nodeface" | | nodeVariantSelectionStrategy | "allVariants" | | coveredDimensionSpacePoint | {"language":"de"} | - And the graph projection is fully up to date Then I expect the graph projection to consist of exactly 1 node And I expect a node identified by live-cs-identifier;lady-eleonode-nodesworth;{} to exist in the content graph @@ -81,7 +75,6 @@ Feature: Remove NodeAggregate | workspaceName | "user-test" | | baseWorkspaceName | "live" | | newContentStreamId | "user-cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "user-test" When the command RemoveNodeAggregate is executed with payload: @@ -89,7 +82,6 @@ Feature: Remove NodeAggregate | nodeAggregateId | "nody-mc-nodeface" | | nodeVariantSelectionStrategy | "allVariants" | | coveredDimensionSpacePoint | {"language":"de"} | - And the graph projection is fully up to date Then I expect the graph projection to consist of exactly 4 nodes And I expect a node identified by live-cs-identifier;lady-eleonode-nodesworth;{} to exist in the content graph diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeRemoval/RemoveNodesFromAggregate.wip b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeRemoval/RemoveNodesFromAggregate.wip index 9d5338d22a4..3fe26bf8051 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeRemoval/RemoveNodesFromAggregate.wip +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeRemoval/RemoveNodesFromAggregate.wip @@ -29,7 +29,6 @@ Feature: Remove Nodes from Aggregate | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "live-cs-identifier" | - And the graph projection is fully up to date And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | contentStreamId | "live-cs-identifier" | @@ -65,7 +64,6 @@ Feature: Remove Nodes from Aggregate | originDimensionSpacePoint | {"language":"de"} | | parentNodeAggregateId | "nodimus-prime" | | nodeName | "grandchild-document" | - And the graph projection is fully up to date ######################## # Section: EXTRA testcases @@ -96,7 +94,6 @@ Feature: Remove Nodes from Aggregate | contentStreamId | "live-cs-identifier" | | nodeAggregateId | "nodasaurus-rex" | | dimensionSpacePointSet | [{"language":"de"},{"language":"gsw"}] | - And the graph projection is fully up to date Then I expect the graph projection to consist of exactly 3 nodes And I expect a node identified by live-cs-identifier;lady-eleonode-nodesworth;{} to exist in the content graph @@ -121,7 +118,6 @@ Feature: Remove Nodes from Aggregate | contentStreamId | "live-cs-identifier" | | nodeAggregateId | "nodasaurus-rex" | | dimensionSpacePointSet | [{"language":"gsw"}] | - And the graph projection is fully up to date Then I expect the graph projection to consist of exactly 4 nodes And I expect a node identified by live-cs-identifier;lady-eleonode-nodesworth;{} to exist in the content graph @@ -152,7 +148,6 @@ Feature: Remove Nodes from Aggregate | contentStreamId | "live-cs-identifier" | | nodeAggregateId | "nody-mc-nodeface" | | dimensionSpacePointSet | [{"language":"de"}] | - And the graph projection is fully up to date Then I expect the graph projection to consist of exactly 1 nodes And I expect a node identified by live-cs-identifier;lady-eleonode-nodesworth;{} to exist in the content graph @@ -172,7 +167,6 @@ Feature: Remove Nodes from Aggregate | contentStreamId | "live-cs-identifier" | | nodeAggregateId | "nody-mc-nodeface" | | dimensionSpacePointSet | [{"language":"gsw"}] | - And the graph projection is fully up to date Then I expect the graph projection to consist of exactly 4 nodes And I expect a node identified by live-cs-identifier;lady-eleonode-nodesworth;{} to exist in the content graph @@ -200,13 +194,11 @@ Feature: Remove Nodes from Aggregate | Key | Value | | contentStreamId | "user-cs-identifier" | | sourceContentStreamId | "live-cs-identifier" | - And the graph projection is fully up to date When the command RemoveNodesFromAggregate was published with payload: | Key | Value | | contentStreamId | "user-cs-identifier" | | nodeAggregateId | "nodasaurus-rex" | | dimensionSpacePointSet | [{"language":"de"}] | - And the graph projection is fully up to date Then I expect the graph projection to consist of exactly 4 nodes And I expect a node identified by live-cs-identifier;lady-eleonode-nodesworth;{} to exist in the content graph @@ -255,14 +247,12 @@ Feature: Remove Nodes from Aggregate | Key | Value | | contentStreamId | "user-cs-identifier" | | sourceContentStreamId | "live-cs-identifier" | - And the graph projection is fully up to date When the command RemoveNodesFromAggregate was published with payload: | Key | Value | | contentStreamId | "user-cs-identifier" | | nodeAggregateId | "nodimus-prime" | | dimensionSpacePointSet | [{"language":"gsw"}] | - And the graph projection is fully up to date When I am in content stream "user-cs-identifier" and dimension space point {"language":"de"} Then I expect a node "doc-identifier-de" to exist in the graph projection @@ -297,14 +287,12 @@ Feature: Remove Nodes from Aggregate | Key | Value | | contentStreamId | "user-cs-identifier" | | sourceContentStreamId | "live-cs-identifier" | - And the graph projection is fully up to date When the command RemoveNodesFromAggregate was published with payload: | Key | Value | | contentStreamId | "user-cs-identifier" | | nodeAggregateId | "nody-mc-nodeface" | | dimensionSpacePointSet | [{"language":"de"},{"language":"gsw"}] | - And the graph projection is fully up to date When I am in content stream "user-cs-identifier" and dimension space point {"language":"de"} Then I expect a node "doc-identifier-de" not to exist in the graph projection @@ -339,14 +327,12 @@ Feature: Remove Nodes from Aggregate | Key | Value | | contentStreamId | "user-cs-identifier" | | sourceContentStreamId | "live-cs-identifier" | - And the graph projection is fully up to date When the command RemoveNodesFromAggregate was published with payload: | Key | Value | | contentStreamId | "user-cs-identifier" | | nodeAggregateId | "nody-mc-nodeface" | | dimensionSpacePointSet | [{"language":"gsw"}] | - And the graph projection is fully up to date When I am in content stream "user-cs-identifier" and dimension space point {"language":"de"} Then I expect a node "doc-identifier-de" to exist in the graph projection diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeRenaming/01_ChangeNodeAggregateName_ConstraintChecks.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeRenaming/01_ChangeNodeAggregateName_ConstraintChecks.feature index 542dbc3fb26..f017ede72b9 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeRenaming/01_ChangeNodeAggregateName_ConstraintChecks.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeRenaming/01_ChangeNodeAggregateName_ConstraintChecks.feature @@ -23,14 +23,12 @@ Feature: Change node name | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | nodeName | nodeTypeName | parentNodeAggregateId | initialPropertyValues | tetheredDescendantNodeAggregateIds | | sir-david-nodenborough | null | Neos.ContentRepository.Testing:Document | lady-eleonode-rootford | {} | {"tethered": "nodewyn-tetherton"} | diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeRenaming/ChangeNodeAggregateName.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeRenaming/ChangeNodeAggregateName.feature index e1760070c4e..b04eef7ecc3 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeRenaming/ChangeNodeAggregateName.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeRenaming/ChangeNodeAggregateName.feature @@ -17,7 +17,6 @@ Feature: Change node name | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {} And the command CreateRootNodeAggregateWithNode is executed with payload: @@ -36,8 +35,6 @@ Feature: Change node name | parentNodeAggregateId | "lady-eleonode-rootford" | | nodeName | "dog" | | nodeAggregateClassification | "regular" | - - And the graph projection is fully up to date When the command "ChangeNodeAggregateName" is executed with payload: | Key | Value | | workspaceName | "live" | @@ -62,7 +59,6 @@ Feature: Change node name | parentNodeAggregateId | "lady-eleonode-rootford" | | nodeName | "dog" | | nodeAggregateClassification | "regular" | - And the graph projection is fully up to date # we read the node initially, to ensure it is filled in the cache (to check whether cache clearing actually works) When I am in the active content stream of workspace "live" and dimension space point {} Then I expect node aggregate identifier "lady-eleonode-rootford" to lead to node cs-identifier;lady-eleonode-rootford;{} @@ -75,7 +71,6 @@ Feature: Change node name | workspaceName | "live" | | nodeAggregateId | "nody-mc-nodeface" | | newNodeName | "cat" | - And the graph projection is fully up to date Then I expect node aggregate identifier "lady-eleonode-rootford" to lead to node cs-identifier;lady-eleonode-rootford;{} Then I expect this node to have the following child nodes: diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeRetyping/ChangeNodeAggregateType_BasicErrorCases.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeRetyping/ChangeNodeAggregateType_BasicErrorCases.feature index 597ab0036b9..56a7aa32316 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeRetyping/ChangeNodeAggregateType_BasicErrorCases.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeRetyping/ChangeNodeAggregateType_BasicErrorCases.feature @@ -49,13 +49,11 @@ Feature: Change node aggregate type - basic error cases | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"de"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date When the command CreateNodeAggregateWithNodeAndSerializedProperties is executed with payload: | Key | Value | @@ -65,8 +63,6 @@ Feature: Change node aggregate type - basic error cases | nodeName | "parent" | | initialPropertyValues | {} | - And the graph projection is fully up to date - Scenario: Try to change the node aggregate type on a non-existing content stream When the command ChangeNodeAggregateType was published with payload and exceptions are caught: | Key | Value | @@ -100,7 +96,6 @@ Feature: Change node aggregate type - basic error cases | parentNodeAggregateId | "sir-david-nodenborough" | | nodeName | "parent" | | initialPropertyValues | {} | - And the graph projection is fully up to date When the command ChangeNodeAggregateType was published with payload and exceptions are caught: | Key | Value | | nodeAggregateId | "nody-mc-nodeface" | @@ -117,7 +112,6 @@ Feature: Change node aggregate type - basic error cases | nodeName | "parent2" | | initialPropertyValues | {} | | tetheredDescendantNodeAggregateIds | {"autocreated": "autocreated-child"} | - And the graph projection is fully up to date When the command CreateNodeAggregateWithNodeAndSerializedProperties is executed with payload: | Key | Value | @@ -126,7 +120,6 @@ Feature: Change node aggregate type - basic error cases | originDimensionSpacePoint | {"language":"de"} | | parentNodeAggregateId | "autocreated-child" | | initialPropertyValues | {} | - And the graph projection is fully up to date When the command ChangeNodeAggregateType was published with payload and exceptions are caught: | Key | Value | @@ -145,7 +138,6 @@ Feature: Change node aggregate type - basic error cases | nodeName | "parent2" | | initialPropertyValues | {} | | tetheredDescendantNodeAggregateIds | {"autocreated": "nody-mc-nodeface"} | - And the graph projection is fully up to date When the command ChangeNodeAggregateType was published with payload and exceptions are caught: | Key | Value | diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeRetyping/ChangeNodeAggregateType_DeleteStrategy.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeRetyping/ChangeNodeAggregateType_DeleteStrategy.feature index c2bfccea819..ea894c7c37b 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeRetyping/ChangeNodeAggregateType_DeleteStrategy.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeRetyping/ChangeNodeAggregateType_DeleteStrategy.feature @@ -65,13 +65,11 @@ Feature: Change node aggregate type - behavior of DELETE strategy | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"de"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date When the command CreateNodeAggregateWithNodeAndSerializedProperties is executed with payload: | Key | Value | @@ -82,8 +80,6 @@ Feature: Change node aggregate type - behavior of DELETE strategy | nodeName | "parent" | | initialPropertyValues | {} | - And the graph projection is fully up to date - Scenario: Try to change to a node type that disallows already present children with the delete conflict resolution strategy When the command CreateNodeAggregateWithNodeAndSerializedProperties is executed with payload: | Key | Value | @@ -91,14 +87,12 @@ Feature: Change node aggregate type - behavior of DELETE strategy | nodeTypeName | "Neos.ContentRepository.Testing:NodeTypeA" | | originDimensionSpacePoint | {"language":"de"} | | parentNodeAggregateId | "sir-david-nodenborough" | - And the graph projection is fully up to date When the command ChangeNodeAggregateType was published with payload: | Key | Value | | nodeAggregateId | "sir-david-nodenborough" | | newNodeTypeName | "Neos.ContentRepository.Testing:ParentNodeTypeB" | | strategy | "delete" | - And the graph projection is fully up to date # the type has changed When I am in the active content stream of workspace "live" and dimension space point {"language":"de"} @@ -119,7 +113,6 @@ Feature: Change node aggregate type - behavior of DELETE strategy | parentNodeAggregateId | "lady-eleonode-rootford" | | nodeName | "parent2" | | tetheredDescendantNodeAggregateIds | {"autocreated": "autocreated-child"} | - And the graph projection is fully up to date When the command CreateNodeAggregateWithNodeAndSerializedProperties is executed with payload: | Key | Value | @@ -128,14 +121,12 @@ Feature: Change node aggregate type - behavior of DELETE strategy | originDimensionSpacePoint | {"language":"de"} | | parentNodeAggregateId | "autocreated-child" | | initialPropertyValues | {} | - And the graph projection is fully up to date When the command ChangeNodeAggregateType was published with payload: | Key | Value | | nodeAggregateId | "parent2-na" | | newNodeTypeName | "Neos.ContentRepository.Testing:ParentNodeTypeB" | | strategy | "delete" | - And the graph projection is fully up to date # the type has changed When I am in the active content stream of workspace "live" and dimension space point {"language":"de"} @@ -163,14 +154,12 @@ Feature: Change node aggregate type - behavior of DELETE strategy | parentNodeAggregateId | "lady-eleonode-rootford" | | initialPropertyValues | {} | | tetheredDescendantNodeAggregateIds | { "child-of-type-a": "child-of-type-a-id"} | - And the graph projection is fully up to date When the command CreateNodeVariant is executed with payload: | Key | Value | | nodeAggregateId | "nodea-identifier-de" | | sourceOrigin | {"language":"de"} | | targetOrigin | {"language":"gsw"} | - And the graph projection is fully up to date When the command ChangeNodeAggregateType was published with payload: | Key | Value | @@ -178,7 +167,6 @@ Feature: Change node aggregate type - behavior of DELETE strategy | newNodeTypeName | "Neos.ContentRepository.Testing:NodeTypeB" | | strategy | "delete" | | tetheredDescendantNodeAggregateIds | { "child-of-type-b": "child-of-type-b-id"} | - And the graph projection is fully up to date # the type has changed When I am in the active content stream of workspace "live" and dimension space point {"language":"de"} @@ -202,14 +190,12 @@ Feature: Change node aggregate type - behavior of DELETE strategy | parentNodeAggregateId | "lady-eleonode-rootford" | | initialPropertyValues | {} | | tetheredDescendantNodeAggregateIds | { "child-of-type-a": "child-of-type-a-id"} | - And the graph projection is fully up to date When the command CreateNodeVariant is executed with payload: | Key | Value | | nodeAggregateId | "nodea-identifier-de" | | sourceOrigin | {"language":"de"} | | targetOrigin | {"language":"gsw"} | - And the graph projection is fully up to date When the command ChangeNodeAggregateType was published with payload: | Key | Value | @@ -217,7 +203,6 @@ Feature: Change node aggregate type - behavior of DELETE strategy | newNodeTypeName | "Neos.ContentRepository.Testing:NodeTypeB" | | strategy | "delete" | | tetheredDescendantNodeAggregateIds | { "child-of-type-b": "child-of-type-b-id"} | - And the graph projection is fully up to date # the type has changed When I am in the active content stream of workspace "live" and dimension space point {"language":"de"} diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeRetyping/ChangeNodeAggregateType_HappyPathStrategy.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeRetyping/ChangeNodeAggregateType_HappyPathStrategy.feature index cf130d3c988..4db432784f8 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeRetyping/ChangeNodeAggregateType_HappyPathStrategy.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeRetyping/ChangeNodeAggregateType_HappyPathStrategy.feature @@ -58,13 +58,11 @@ Feature: Change node aggregate type - behavior of HAPPYPATH strategy | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"de"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date When the command CreateNodeAggregateWithNodeAndSerializedProperties is executed with payload: | Key | Value | @@ -75,8 +73,6 @@ Feature: Change node aggregate type - behavior of HAPPYPATH strategy | nodeName | "parent" | | initialPropertyValues | {} | - And the graph projection is fully up to date - Scenario: Try to change to a node type that disallows already present children with the HAPPYPATH conflict resolution strategy When the command CreateNodeAggregateWithNodeAndSerializedProperties is executed with payload: | Key | Value | @@ -84,7 +80,6 @@ Feature: Change node aggregate type - behavior of HAPPYPATH strategy | nodeTypeName | "Neos.ContentRepository.Testing:NodeTypeA" | | originDimensionSpacePoint | {"language":"de"} | | parentNodeAggregateId | "sir-david-nodenborough" | - And the graph projection is fully up to date When the command ChangeNodeAggregateType was published with payload and exceptions are caught: | Key | Value | @@ -102,7 +97,6 @@ Feature: Change node aggregate type - behavior of HAPPYPATH strategy | parentNodeAggregateId | "lady-eleonode-rootford" | | nodeName | "parent2" | | tetheredDescendantNodeAggregateIds | {"autocreated": "autocreated-child"} | - And the graph projection is fully up to date When the command CreateNodeAggregateWithNodeAndSerializedProperties is executed with payload: | Key | Value | @@ -111,7 +105,6 @@ Feature: Change node aggregate type - behavior of HAPPYPATH strategy | originDimensionSpacePoint | {"language":"de"} | | parentNodeAggregateId | "autocreated-child" | | initialPropertyValues | {} | - And the graph projection is fully up to date When the command ChangeNodeAggregateType was published with payload and exceptions are caught: | Key | Value | @@ -129,14 +122,12 @@ Feature: Change node aggregate type - behavior of HAPPYPATH strategy | parentNodeAggregateId | "lady-eleonode-rootford" | | initialPropertyValues | {} | | tetheredDescendantNodeAggregateIds | { "child-of-type-a": "child-of-type-a-id"} | - And the graph projection is fully up to date When the command CreateNodeVariant is executed with payload: | Key | Value | | nodeAggregateId | "nodea-identifier-de" | | sourceOrigin | {"language":"de"} | | targetOrigin | {"language":"gsw"} | - And the graph projection is fully up to date When the command ChangeNodeAggregateType was published with payload: | Key | Value | @@ -144,7 +135,6 @@ Feature: Change node aggregate type - behavior of HAPPYPATH strategy | newNodeTypeName | "Neos.ContentRepository.Testing:NodeTypeB" | | strategy | "happypath" | | tetheredDescendantNodeAggregateIds | { "child-of-type-b": "child-of-type-b-id"} | - And the graph projection is fully up to date # the type has changed When I am in the active content stream of workspace "live" and dimension space point {"language":"de"} diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/AncestorNodes.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/AncestorNodes.feature index db876fac357..3e9f33dde36 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/AncestorNodes.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/AncestorNodes.feature @@ -50,13 +50,11 @@ Feature: Find and count nodes using the findAncestorNodes and countAncestorNodes | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"de"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | nodeName | nodeTypeName | parentNodeAggregateId | initialPropertyValues | tetheredDescendantNodeAggregateIds | | home | home | Neos.ContentRepository.Testing:Homepage | lady-eleonode-rootford | {} | {"terms": "terms", "contact": "contact"} | @@ -75,12 +73,10 @@ Feature: Find and count nodes using the findAncestorNodes and countAncestorNodes | Key | Value | | nodeAggregateId | "a2a2a" | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date And the command DisableNodeAggregate is executed with payload: | Key | Value | | nodeAggregateId | "a2b" | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date Scenario: # findAncestorNodes queries without results diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/ChildNodes.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/ChildNodes.feature index 565e2556cc6..62f0f125fa9 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/ChildNodes.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/ChildNodes.feature @@ -64,13 +64,11 @@ Feature: Find and count nodes using the findChildNodes and countChildNodes queri | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"de"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | nodeTypeName | parentNodeAggregateId | initialPropertyValues | tetheredDescendantNodeAggregateIds | | home | Neos.ContentRepository.Testing:Homepage | lady-eleonode-rootford | {} | {"terms": "terms", "contact": "contact"} | @@ -94,7 +92,6 @@ Feature: Find and count nodes using the findChildNodes and countChildNodes queri | Key | Value | | nodeAggregateId | "a2a3" | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date Scenario: # Child nodes without filter diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/ClosestNode.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/ClosestNode.feature index c5816b0d300..ea07f96758f 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/ClosestNode.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/ClosestNode.feature @@ -50,13 +50,11 @@ Feature: Find nodes using the findClosestNode query | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"de"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | nodeName | nodeTypeName | parentNodeAggregateId | initialPropertyValues | tetheredDescendantNodeAggregateIds | | home | home | Neos.ContentRepository.Testing:Homepage | lady-eleonode-rootford | {} | {"terms": "terms", "contact": "contact"} | @@ -75,12 +73,10 @@ Feature: Find nodes using the findClosestNode query | Key | Value | | nodeAggregateId | "a2a2a" | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date And the command DisableNodeAggregate is executed with payload: | Key | Value | | nodeAggregateId | "a2b" | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date Scenario: # findClosestNode queries without results diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/CountNodes.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/CountNodes.feature index 33d104675a4..2edd24ca474 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/CountNodes.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/CountNodes.feature @@ -52,13 +52,11 @@ Feature: Find nodes using the countNodes query | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"de"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | nodeName | nodeTypeName | parentNodeAggregateId | initialPropertyValues | tetheredDescendantNodeAggregateIds | | home | home | Neos.ContentRepository.Testing:Homepage | lady-eleonode-rootford | {} | {"terms": "terms", "contact": "contact"} | @@ -80,6 +78,5 @@ Feature: Find nodes using the countNodes query | Key | Value | | nodeAggregateId | "a2a1" | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date # NOTE: countNodes() counts _all_ nodes, even disabled ones And I execute the countNodes query I expect the result to be 12 diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/DescendantNodes.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/DescendantNodes.feature index 34847488825..d415675be04 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/DescendantNodes.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/DescendantNodes.feature @@ -64,13 +64,11 @@ Feature: Find and count nodes using the findDescendantNodes and countDescendantN | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"de"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | nodeName | nodeTypeName | parentNodeAggregateId | initialPropertyValues | tetheredDescendantNodeAggregateIds | | home | home | Neos.ContentRepository.Testing:Homepage | lady-eleonode-rootford | {} | {"terms": "terms", "contact": "contact"} | @@ -94,7 +92,6 @@ Feature: Find and count nodes using the findDescendantNodes and countDescendantN | Key | Value | | nodeAggregateId | "a2a2a" | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date Scenario: diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/FindNodeById.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/FindNodeById.feature index b61dffbc52f..ba993e78a97 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/FindNodeById.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/FindNodeById.feature @@ -63,13 +63,11 @@ Feature: Find nodes using the findNodeById query | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"de"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | nodeName | nodeTypeName | parentNodeAggregateId | initialPropertyValues | tetheredDescendantNodeAggregateIds | | home | home | Neos.ContentRepository.Testing:Homepage | lady-eleonode-rootford | {} | {"terms": "terms", "contact": "contact"} | @@ -85,7 +83,6 @@ Feature: Find nodes using the findNodeById query | Key | Value | | nodeAggregateId | "a2a1" | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date Scenario: # findNodeById queries without result diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/FindNodeByPath.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/FindNodeByPath.feature index c895ac33025..e2aca84b06a 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/FindNodeByPath.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/FindNodeByPath.feature @@ -66,13 +66,11 @@ Feature: Find nodes using the findNodeByPath query | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"de"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | nodeName | nodeTypeName | parentNodeAggregateId | initialPropertyValues | tetheredDescendantNodeAggregateIds | | home | home | Neos.ContentRepository.Testing:Homepage | lady-eleonode-rootford | {} | {"terms": "terms", "contact": "contact"} | @@ -89,7 +87,6 @@ Feature: Find nodes using the findNodeByPath query | Key | Value | | nodeAggregateId | "a2a2" | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date Scenario: # absolute paths without result diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/FindNodeByPathAsNodeName.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/FindNodeByPathAsNodeName.feature index bb98926abc2..58418a76d48 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/FindNodeByPathAsNodeName.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/FindNodeByPathAsNodeName.feature @@ -63,13 +63,11 @@ Feature: Find nodes using the findNodeByPath query with node name as path argume | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"de"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | nodeName | nodeTypeName | parentNodeAggregateId | initialPropertyValues | tetheredDescendantNodeAggregateIds | | home | home | Neos.ContentRepository.Testing:Homepage | lady-eleonode-rootford | {} | {"terms": "terms", "contact": "contact"} | @@ -86,7 +84,6 @@ Feature: Find nodes using the findNodeByPath query with node name as path argume | Key | Value | | nodeAggregateId | "a2a2" | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date Scenario: # findNodeByPath queries without results diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/FindParentNode.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/FindParentNode.feature index 68bc44ef005..e72e1ec2af8 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/FindParentNode.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/FindParentNode.feature @@ -63,13 +63,11 @@ Feature: Find nodes using the findParentNodes query | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"de"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | nodeName | nodeTypeName | parentNodeAggregateId | initialPropertyValues | tetheredDescendantNodeAggregateIds | | home | home | Neos.ContentRepository.Testing:Homepage | lady-eleonode-rootford | {} | {"terms": "terms", "contact": "contact"} | @@ -85,7 +83,6 @@ Feature: Find nodes using the findParentNodes query | Key | Value | | nodeAggregateId | "a2a" | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date Scenario: # findParentNode queries without result diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/FindRootNodeByType.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/FindRootNodeByType.feature index c56e42a84a0..a277eb6cbaf 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/FindRootNodeByType.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/FindRootNodeByType.feature @@ -23,18 +23,15 @@ Feature: Find root nodes by type | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"de"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootfords-evil-sister" | | nodeTypeName | "Neos.ContentRepository:AnotherRoot" | - And the graph projection is fully up to date Scenario: When I execute the findRootNodeByType query for node type "Neos.ContentRepository:Root" I expect the node "lady-eleonode-rootford" to be returned diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/FindSubtree.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/FindSubtree.feature index f65d2abd4ce..5742c04f435 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/FindSubtree.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/FindSubtree.feature @@ -52,13 +52,11 @@ Feature: Find nodes using the findSubtree query | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"de"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | nodeName | nodeTypeName | parentNodeAggregateId | initialPropertyValues | tetheredDescendantNodeAggregateIds | | home | home | Neos.ContentRepository.Testing:Homepage | lady-eleonode-rootford | {} | {"terms": "terms", "contact": "contact"} | @@ -76,7 +74,6 @@ Feature: Find nodes using the findSubtree query | Key | Value | | nodeAggregateId | "a2a2a" | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date Scenario: # findSubtree queries without results diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/References.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/References.feature index 13a8e586444..2454d2840d2 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/References.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/References.feature @@ -73,13 +73,11 @@ Feature: Find and count references and their target nodes using the findReferenc | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"de"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | nodeTypeName | parentNodeAggregateId | initialPropertyValues | tetheredDescendantNodeAggregateIds | | home | Neos.ContentRepository.Testing:Homepage | lady-eleonode-rootford | {} | {"terms": "terms", "contact": "contact"} | @@ -143,7 +141,6 @@ Feature: Find and count references and their target nodes using the findReferenc | Key | Value | | nodeAggregateId | "a2a3" | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date Scenario: # findReferences queries without results diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/RetrieveNodePath.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/RetrieveNodePath.feature index d4bf8631090..907602c2dd2 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/RetrieveNodePath.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/RetrieveNodePath.feature @@ -53,13 +53,11 @@ Feature: Find nodes using the retrieveNodePath query | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"de"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | nodeName | nodeTypeName | parentNodeAggregateId | initialPropertyValues | tetheredDescendantNodeAggregateIds | | home | home | Neos.ContentRepository.Testing:Homepage | lady-eleonode-rootford | {} | {"terms": "terms", "contact": "contact"} | @@ -85,7 +83,6 @@ Feature: Find nodes using the retrieveNodePath query | Key | Value | | nodeAggregateId | "b1" | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date Scenario: # retrieveNodePath queries without result diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/SiblingNodes.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/SiblingNodes.feature index a94e992bd83..a23e0f2c0e1 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/SiblingNodes.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/SiblingNodes.feature @@ -63,13 +63,11 @@ Feature: Find sibling nodes using the findPrecedingSiblingNodes and findSucceedi | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"de"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | nodeName | nodeTypeName | parentNodeAggregateId | initialPropertyValues | tetheredDescendantNodeAggregateIds | | home | home | Neos.ContentRepository.Testing:Homepage | lady-eleonode-rootford | {} | {"terms": "terms", "contact": "contact"} | @@ -90,7 +88,6 @@ Feature: Find sibling nodes using the findPrecedingSiblingNodes and findSucceedi | Key | Value | | nodeAggregateId | "a2a2" | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date Scenario: # findPrecedingSiblingNodes queries without result diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/Timestamps.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/Timestamps.feature index ed4672f8e85..e385b5545ee 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/Timestamps.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/Timestamps.feature @@ -74,13 +74,11 @@ Feature: Behavior of Node timestamp properties "created", "originalCreated", "la | baseWorkspaceName | "review" | | newContentStreamId | "cs-user" | | workspaceOwner | "some-user" | - And the graph projection is fully up to date And I am in the active content stream of workspace "user-test" and dimension space point {"language":"de"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | nodeName | nodeTypeName | parentNodeAggregateId | initialPropertyValues | tetheredDescendantNodeAggregateIds | | home | home | Neos.ContentRepository.Testing:Homepage | lady-eleonode-rootford | {} | {"terms": "terms", "contact": "contact"} | @@ -92,7 +90,6 @@ Feature: Behavior of Node timestamp properties "created", "originalCreated", "la | nodeAggregateId | "a" | | sourceOrigin | {"language":"de"} | | targetOrigin | {"language":"ch"} | - And the graph projection is fully up to date Scenario: NodePropertiesWereSet events update last modified timestamps When the current date and time is "2023-03-16T13:00:00+01:00" @@ -102,7 +99,6 @@ Feature: Behavior of Node timestamp properties "created", "originalCreated", "la | originDimensionSpacePoint | {"language": "ch"} | | nodeAggregateId | "a" | | propertyValues | {"text": "Changed"} | - And the graph projection is fully up to date And I am in content stream "cs-user" and dimension space point {"language":"de"} Then I expect the node "a" to have the following timestamps: | created | originalCreated | lastModified | originalLastModified | @@ -120,7 +116,6 @@ Feature: Behavior of Node timestamp properties "created", "originalCreated", "la | workspaceName | "user-test" | | nodeAggregateId | "a" | | newNodeName | "a-renamed" | - And the graph projection is fully up to date And I am in content stream "cs-user" and dimension space point {"language":"de"} Then I expect the node "a" to have the following timestamps: | created | originalCreated | lastModified | originalLastModified | @@ -140,7 +135,6 @@ Feature: Behavior of Node timestamp properties "created", "originalCreated", "la | sourceNodeAggregateId | "a" | | referenceName | "ref" | | references | [{"target": "b"}] | - And the graph projection is fully up to date And I am in content stream "cs-user" and dimension space point {"language":"de"} Then I expect the node "a" to have the following timestamps: | created | originalCreated | lastModified | originalLastModified | @@ -165,7 +159,6 @@ Feature: Behavior of Node timestamp properties "created", "originalCreated", "la | nodeAggregateId | "a" | | newNodeTypeName | "Neos.ContentRepository.Testing:SpecialPage" | | strategy | "happypath" | - And the graph projection is fully up to date And I am in content stream "cs-user" and dimension space point {"language":"de"} Then I expect the node "a" to have the following timestamps: | created | originalCreated | lastModified | originalLastModified | @@ -183,7 +176,6 @@ Feature: Behavior of Node timestamp properties "created", "originalCreated", "la | nodeAggregateId | "home" | | sourceOrigin | {"language":"de"} | | targetOrigin | {"language":"en"} | - And the graph projection is fully up to date And I am in content stream "cs-user" and dimension space point {"language":"de"} Then I expect the node "home" to have the following timestamps: | created | originalCreated | lastModified | originalLastModified | @@ -201,7 +193,6 @@ Feature: Behavior of Node timestamp properties "created", "originalCreated", "la | nodeAggregateId | "home" | | sourceOrigin | {"language":"de"} | | targetOrigin | {"language":"mul"} | - And the graph projection is fully up to date And I am in content stream "cs-user" and dimension space point {"language":"de"} Then I expect the node "home" to have the following timestamps: | created | originalCreated | lastModified | originalLastModified | @@ -222,7 +213,6 @@ Feature: Behavior of Node timestamp properties "created", "originalCreated", "la | relationDistributionStrategy | "gatherSpecializations" | | nodeAggregateId | "a" | | newParentNodeAggregateId | "b" | - And the graph projection is fully up to date And I am in content stream "cs-user" and dimension space point {"language":"de"} Then I expect the node "a" to have the following timestamps: | created | originalCreated | lastModified | originalLastModified | @@ -238,7 +228,6 @@ Feature: Behavior of Node timestamp properties "created", "originalCreated", "la And the command UpdateRootNodeAggregateDimensions is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | - And the graph projection is fully up to date And I am in content stream "cs-user" and dimension space point {"language":"de"} Then I expect the node "a" to have the following timestamps: | created | originalCreated | lastModified | originalLastModified | @@ -257,7 +246,6 @@ Feature: Behavior of Node timestamp properties "created", "originalCreated", "la | coveredDimensionSpacePoint | {"language": "ch"} | | nodeAggregateId | "a" | | nodeVariantSelectionStrategy | "allSpecializations" | - And the graph projection is fully up to date And I am in content stream "cs-user" and dimension space point {"language":"de"} And VisibilityConstraints are set to "withoutRestrictions" Then I expect the node "a" to have the following timestamps: @@ -276,7 +264,6 @@ Feature: Behavior of Node timestamp properties "created", "originalCreated", "la | coveredDimensionSpacePoint | {"language": "ch"} | | nodeAggregateId | "a" | | nodeVariantSelectionStrategy | "allSpecializations" | - And the graph projection is fully up to date And I am in content stream "cs-user" and dimension space point {"language":"de"} Then I expect the node "a" to have the following timestamps: | created | originalCreated | lastModified | originalLastModified | @@ -296,12 +283,10 @@ Feature: Behavior of Node timestamp properties "created", "originalCreated", "la | nodeAggregateId | "a" | | propertyValues | {"text": "Changed"} | And I execute the findNodeById query for node aggregate id "non-existing" I expect no node to be returned - And the graph projection is fully up to date And the current date and time is "2023-03-16T14:00:00+01:00" And the command PublishWorkspace is executed with payload: | Key | Value | | workspaceName | "user-test" | - And the graph projection is fully up to date And I am in content stream "cs-user" Then I expect the node "a" to have the following timestamps: @@ -323,7 +308,6 @@ Feature: Behavior of Node timestamp properties "created", "originalCreated", "la And the command PublishWorkspace is executed with payload: | Key | Value | | workspaceName | "review" | - And the graph projection is fully up to date And I am in content stream "cs-live" Then I expect the node "a" to have the following timestamps: | created | originalCreated | lastModified | originalLastModified | diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ProjectionIntegrityViolationDetection/AllNodesAreConnectedToARootNodePerSubgraph.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ProjectionIntegrityViolationDetection/AllNodesAreConnectedToARootNodePerSubgraph.feature index 9dd34c4676b..d6872b0bf2a 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ProjectionIntegrityViolationDetection/AllNodesAreConnectedToARootNodePerSubgraph.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ProjectionIntegrityViolationDetection/AllNodesAreConnectedToARootNodePerSubgraph.feature @@ -20,7 +20,6 @@ Feature: Run projection integrity violation detection regarding root connection | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date Scenario: Create a cycle When the event RootNodeAggregateWithNodeWasCreated was published with payload: @@ -50,13 +49,11 @@ Feature: Run projection integrity violation detection regarding root connection | parentNodeAggregateId | "sir-david-nodenborough" | | nodeName | "child-document" | | nodeAggregateClassification | "regular" | - And the graph projection is fully up to date And the event NodeAggregateWasMoved was published with payload: | Key | Value | | contentStreamId | "cs-identifier" | | nodeAggregateId | "sir-david-nodenborough" | | nodeMoveMappings | [{"movedNodeOrigin":{"language":"de"},"newLocations":[{"coveredDimensionSpacePoint": {"language":"de"},"newParent":{"nodeAggregateId":"nody-mc-nodeface","originDimensionSpacePoint":{"language":"de"}}}, {"coveredDimensionSpacePoint": {"language":"gsw"},"newParent":{"nodeAggregateId":"nody-mc-nodeface","originDimensionSpacePoint":{"language":"de"}}}]}] | - And the graph projection is fully up to date And I run integrity violation detection # one error per subgraph Then I expect the integrity violation detection result to contain exactly 2 errors diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ProjectionIntegrityViolationDetection/AllNodesCoverTheirOrigin.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ProjectionIntegrityViolationDetection/AllNodesCoverTheirOrigin.feature index f7c96024ca4..68f9435ae90 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ProjectionIntegrityViolationDetection/AllNodesCoverTheirOrigin.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ProjectionIntegrityViolationDetection/AllNodesCoverTheirOrigin.feature @@ -19,13 +19,11 @@ Feature: Run projection integrity violation detection to find nodes that do not | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"de"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date Scenario: Create a node not covering its origin When the event NodeAggregateWithNodeWasCreated was published with payload: @@ -48,7 +46,6 @@ Feature: Run projection integrity violation detection to find nodes that do not | parentNodeAggregateId | "sir-david-nodenborough" | | nodeName | "document" | | nodeAggregateClassification | "regular" | - And the graph projection is fully up to date And I run integrity violation detection Then I expect the integrity violation detection result to contain exactly 1 errors And I expect integrity violation detection result error number 1 to have code 1597828607 diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ProjectionIntegrityViolationDetection/IntactContentGraph.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ProjectionIntegrityViolationDetection/IntactContentGraph.feature index 01276ad9f20..88f0b1e18b9 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ProjectionIntegrityViolationDetection/IntactContentGraph.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ProjectionIntegrityViolationDetection/IntactContentGraph.feature @@ -28,7 +28,6 @@ Feature: Create an intact content graph and run integrity violation detection | nodeTypeName | "Neos.ContentRepository:Root" | | coveredDimensionSpacePoints | [{"language":"de"},{"language":"gsw"}] | | nodeAggregateClassification | "root" | - And the graph projection is fully up to date And the event NodeAggregateWithNodeWasCreated was published with payload: | Key | Value | | contentStreamId | "cs-identifier" | @@ -66,6 +65,5 @@ Feature: Create an intact content graph and run integrity violation detection | affectedSourceOriginDimensionSpacePoints | [{"language":"de"}] | | referenceName | "referenceProperty" | | references | [{"targetNodeAggregateId":"sir-david-nodenborough", "properties":null}] | - And the graph projection is fully up to date And I run integrity violation detection Then I expect the integrity violation detection result to contain exactly 0 errors diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ProjectionIntegrityViolationDetection/NodeAggregateIdentifiersAreUniquePerSubgraph.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ProjectionIntegrityViolationDetection/NodeAggregateIdentifiersAreUniquePerSubgraph.feature index cb0fa7092c4..45a8e9ed1cf 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ProjectionIntegrityViolationDetection/NodeAggregateIdentifiersAreUniquePerSubgraph.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ProjectionIntegrityViolationDetection/NodeAggregateIdentifiersAreUniquePerSubgraph.feature @@ -19,13 +19,11 @@ Feature: Create two nodes with the same node aggregate identifier in the same su | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"de"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date Scenario: Create two node variants in the same subgraph When the event NodeAggregateWithNodeWasCreated was published with payload: @@ -48,7 +46,6 @@ Feature: Create two nodes with the same node aggregate identifier in the same su | parentNodeAggregateId | "lady-eleonode-rootford" | | nodeName | "document" | | nodeAggregateClassification | "regular" | - And the graph projection is fully up to date And I run integrity violation detection # one error per covered dimension space point Then I expect the integrity violation detection result to contain exactly 2 errors diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ProjectionIntegrityViolationDetection/NodeAggregatesAreConsistentlyClassifiedPerContentStream.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ProjectionIntegrityViolationDetection/NodeAggregatesAreConsistentlyClassifiedPerContentStream.feature index 79752e4371e..216a52cfaec 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ProjectionIntegrityViolationDetection/NodeAggregatesAreConsistentlyClassifiedPerContentStream.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ProjectionIntegrityViolationDetection/NodeAggregatesAreConsistentlyClassifiedPerContentStream.feature @@ -19,13 +19,11 @@ Feature: Run projection integrity violation detection regarding node aggregate c | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"de"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date Scenario: Create node variants of different type When the event NodeAggregateWithNodeWasCreated was published with payload: @@ -48,7 +46,6 @@ Feature: Run projection integrity violation detection regarding node aggregate c | parentNodeAggregateId | "lady-eleonode-rootford" | | nodeName | "document" | | nodeAggregateClassification | "tethered" | - And the graph projection is fully up to date And I run integrity violation detection Then I expect the integrity violation detection result to contain exactly 1 errors And I expect integrity violation detection result error number 1 to have code 1597825384 diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ProjectionIntegrityViolationDetection/NodeAggregatesAreConsistentlyTypedPerContentStream.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ProjectionIntegrityViolationDetection/NodeAggregatesAreConsistentlyTypedPerContentStream.feature index 5ddfd4d3e0a..a97680f48d7 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ProjectionIntegrityViolationDetection/NodeAggregatesAreConsistentlyTypedPerContentStream.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ProjectionIntegrityViolationDetection/NodeAggregatesAreConsistentlyTypedPerContentStream.feature @@ -21,13 +21,11 @@ Feature: Run projection integrity violation detection regarding node aggregate t | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"de"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date Scenario: Create node variants of different type When the event NodeAggregateWithNodeWasCreated was published with payload: @@ -50,7 +48,6 @@ Feature: Run projection integrity violation detection regarding node aggregate t | parentNodeAggregateId | "lady-eleonode-rootford" | | nodeName | "document" | | nodeAggregateClassification | "regular" | - And the graph projection is fully up to date And I run integrity violation detection Then I expect the integrity violation detection result to contain exactly 1 errors And I expect integrity violation detection result error number 1 to have code 1597747062 diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ProjectionIntegrityViolationDetection/ReferenceIntegrityIsProvided.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ProjectionIntegrityViolationDetection/ReferenceIntegrityIsProvided.feature index f8101ef42c1..200be1d315b 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ProjectionIntegrityViolationDetection/ReferenceIntegrityIsProvided.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/ProjectionIntegrityViolationDetection/ReferenceIntegrityIsProvided.feature @@ -19,7 +19,6 @@ Feature: Run integrity violation detection regarding reference relations | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language":"de"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | @@ -34,7 +33,6 @@ Feature: Run integrity violation detection regarding reference relations | coveredDimensionSpacePoints | [{"language":"de"}] | | parentNodeAggregateId | "lady-eleonode-rootford" | | nodeAggregateClassification | "regular" | - And the graph projection is fully up to date Scenario: Reference a non-existing node aggregate When the event NodeReferencesWereSet was published with payload: @@ -44,7 +42,6 @@ Feature: Run integrity violation detection regarding reference relations | affectedSourceOriginDimensionSpacePoints | [{"language":"de"}] | | referenceName | "referenceProperty" | | references | [{"targetNodeAggregateId":"anthony-destinode", "properties":null}] | - And the graph projection is fully up to date And I run integrity violation detection Then I expect the integrity violation detection result to contain exactly 1 error And I expect integrity violation detection result error number 1 to have code 1597919585 @@ -66,7 +63,6 @@ Feature: Run integrity violation detection regarding reference relations | affectedSourceOriginDimensionSpacePoints | [{"language":"de"}] | | referenceName | "referenceProperty" | | references | [{"targetNodeAggregateId":"anthony-destinode", "properties":null}] | - And the graph projection is fully up to date And I run integrity violation detection Then I expect the integrity violation detection result to contain exactly 1 error And I expect integrity violation detection result error number 1 to have code 1597919585 diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/RootNodeAggregateDimensionUpdates/UpdateRootNodeAggregateDimensions_WithDimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/RootNodeAggregateDimensionUpdates/UpdateRootNodeAggregateDimensions_WithDimensions.feature index 3382f6122a5..9ccab275ffc 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/RootNodeAggregateDimensionUpdates/UpdateRootNodeAggregateDimensions_WithDimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/RootNodeAggregateDimensionUpdates/UpdateRootNodeAggregateDimensions_WithDimensions.feature @@ -19,7 +19,6 @@ Feature: Update Root Node aggregate dimensions | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | @@ -38,8 +37,6 @@ Feature: Update Root Node aggregate dimensions | nodeAggregateClassification | "root" | And event metadata at index 1 is: | Key | Expected | - - When the graph projection is fully up to date Then I expect the node aggregate "lady-eleonode-rootford" to exist And I expect this node aggregate to be classified as "root" And I expect this node aggregate to be of type "Neos.ContentRepository:Root" @@ -74,7 +71,6 @@ Feature: Update Root Node aggregate dimensions Scenario: Adding a dimension and updating the root node works - When the graph projection is fully up to date Given I change the content dimensions in content repository "default" to: | Identifier | Values | Generalizations | | language | mul, de, en | | @@ -97,8 +93,6 @@ Feature: Update Root Node aggregate dimensions | coveredDimensionSpacePoints | [{"language":"mul"},{"language":"de"},{"language":"en"}] | And event metadata at index 1 is: | Key | Expected | - - When the graph projection is fully up to date Then I expect the node aggregate "lady-eleonode-rootford" to exist And I expect this node aggregate to be classified as "root" And I expect this node aggregate to be of type "Neos.ContentRepository:Root" @@ -138,14 +132,12 @@ Feature: Update Root Node aggregate dimensions Scenario: Adding a dimension updating the root node, removing dimension, updating the root node, works (dimension gone again) - When the graph projection is fully up to date Given I change the content dimensions in content repository "default" to: | Identifier | Values | Generalizations | | language | mul, de, en | | And the command UpdateRootNodeAggregateDimensions is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | - And the graph projection is fully up to date # now, the root node exists in "en" When I am in dimension space point {"language":"en"} @@ -159,7 +151,6 @@ Feature: Update Root Node aggregate dimensions And the command UpdateRootNodeAggregateDimensions is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | - And the graph projection is fully up to date # now, the root node should not exist anymore in "en" When I am in dimension space point {"language":"en"} diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/StructureAdjustment/DimensionMismatch.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/StructureAdjustment/DimensionMismatch.feature index b059a1cf922..ca786d1ee06 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/StructureAdjustment/DimensionMismatch.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/StructureAdjustment/DimensionMismatch.feature @@ -24,13 +24,11 @@ Feature: Dimension mismatch | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language": "en"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date Scenario: Generalization detection # Node /document @@ -40,7 +38,6 @@ Feature: Dimension mismatch | nodeTypeName | "Neos.ContentRepository.Testing:Document" | | originDimensionSpacePoint | {"language": "en"} | | parentNodeAggregateId | "lady-eleonode-rootford" | - And the graph projection is fully up to date When I change the content dimensions in content repository "default" to: | Identifier | Values | Generalizations | diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/StructureAdjustment/DisallowedChildNode.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/StructureAdjustment/DisallowedChildNode.feature index d662515984e..315d0d5f1dd 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/StructureAdjustment/DisallowedChildNode.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/StructureAdjustment/DisallowedChildNode.feature @@ -30,7 +30,6 @@ Feature: Remove disallowed Child Nodes and grandchild nodes | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | @@ -58,8 +57,6 @@ Feature: Remove disallowed Child Nodes and grandchild nodes | parentNodeAggregateId | "sir-david-nodenborough" | | nodeName | "sub" | | nodeAggregateClassification | "regular" | - - And the graph projection is fully up to date Then I expect no needed structure adjustments for type "Neos.ContentRepository:Root" Then I expect no needed structure adjustments for type "Neos.ContentRepository.Testing:Document" Then I expect no needed structure adjustments for type "Neos.ContentRepository.Testing:SubDocument" @@ -120,7 +117,6 @@ Feature: Remove disallowed Child Nodes and grandchild nodes | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | @@ -148,8 +144,6 @@ Feature: Remove disallowed Child Nodes and grandchild nodes | parentNodeAggregateId | "sir-david-nodenborough" | | nodeName | "sub" | | nodeAggregateClassification | "regular" | - - And the graph projection is fully up to date Then I expect no needed structure adjustments for type "Neos.ContentRepository:Root" Then I expect no needed structure adjustments for type "Neos.ContentRepository.Testing:Document" Then I expect no needed structure adjustments for type "Neos.ContentRepository.Testing:SubDocument" diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/StructureAdjustment/DisallowedChildNodesAndTetheredNodes.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/StructureAdjustment/DisallowedChildNodesAndTetheredNodes.feature index 9b819a633ee..54c4fa577d0 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/StructureAdjustment/DisallowedChildNodesAndTetheredNodes.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/StructureAdjustment/DisallowedChildNodesAndTetheredNodes.feature @@ -30,13 +30,11 @@ Feature: Remove disallowed Child Nodes and grandchild nodes | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | parentNodeAggregateId | nodeTypeName | | nody-mc-nodeface | lady-eleonode-rootford | Neos.ContentRepository.Testing:Document | diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/StructureAdjustment/Properties.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/StructureAdjustment/Properties.feature index ce752a421b1..7f3f22713fe 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/StructureAdjustment/Properties.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/StructureAdjustment/Properties.feature @@ -24,13 +24,11 @@ Feature: Properties | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date # Node /document When the command CreateNodeAggregateWithNodeAndSerializedProperties is executed with payload: | Key | Value | @@ -38,7 +36,6 @@ Feature: Properties | nodeTypeName | "Neos.ContentRepository.Testing:Document" | | originDimensionSpacePoint | {} | | parentNodeAggregateId | "lady-eleonode-rootford" | - And the graph projection is fully up to date Then I expect no needed structure adjustments for type "Neos.ContentRepository.Testing:Document" Then I expect node aggregate identifier "sir-david-nodenborough" to lead to node cs-identifier;sir-david-nodenborough;{} @@ -103,7 +100,6 @@ Feature: Properties | nodeAggregateId | "sir-david-nodenborough" | | originDimensionSpacePoint | {} | | propertyValues | {"otherProp": ""} | - And the graph projection is fully up to date Then I expect no needed structure adjustments for type "Neos.ContentRepository.Testing:Document" Scenario: a broken property (which cannot be deserialized) is detected and removed @@ -124,7 +120,6 @@ Feature: Properties | affectedDimensionSpacePoints | [{}] | | propertyValues | {"myProp": {"value": "original value", "type": "My\\Non\\Existing\\Class"}} | | propertiesToUnset | {} | - And the graph projection is fully up to date Then I expect the following structure adjustments for type "Neos.ContentRepository.Testing:Document": | Type | nodeAggregateId | | NON_DESERIALIZABLE_PROPERTY | sir-david-nodenborough | diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/StructureAdjustment/TetheredNodes.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/StructureAdjustment/TetheredNodes.feature index e5ef4bb624b..381fbdde5a2 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/StructureAdjustment/TetheredNodes.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/StructureAdjustment/TetheredNodes.feature @@ -36,7 +36,6 @@ Feature: Tethered Nodes integrity violations | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | @@ -79,7 +78,6 @@ Feature: Tethered Nodes integrity violations | parentNodeAggregateId | "nodewyn-tetherton" | | nodeName | "tethered-leaf" | | nodeAggregateClassification | "tethered" | - And the graph projection is fully up to date Then I expect no needed structure adjustments for type "Neos.ContentRepository.Testing:Document" Scenario: Adjusting the schema adding a new tethered node leads to a MissingTetheredNode integrity violation diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/StructureAdjustment/TetheredNodesReordering.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/StructureAdjustment/TetheredNodesReordering.feature index 72bc102776d..195eb8b7b84 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/StructureAdjustment/TetheredNodesReordering.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/StructureAdjustment/TetheredNodesReordering.feature @@ -25,13 +25,11 @@ Feature: Tethered Nodes Reordering Structure changes | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the command CreateNodeAggregateWithNodeAndSerializedProperties is executed with payload: | Key | Value | | nodeAggregateId | "sir-david-nodenborough" | @@ -40,7 +38,6 @@ Feature: Tethered Nodes Reordering Structure changes | parentNodeAggregateId | "lady-eleonode-rootford" | | nodeName | "document" | | tetheredDescendantNodeAggregateIds | {"tethered-node": "tethered-node-agg", "other-tethered-node": "other-tethered-node-agg", "third-tethered-node": "third-tethered-node-agg"} | - And the graph projection is fully up to date Then I expect no needed structure adjustments for type "Neos.ContentRepository.Testing:Document" diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/StructureAdjustment/UnknownNodeType.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/StructureAdjustment/UnknownNodeType.feature index 6bcb3ca90ff..be1ab7ee73c 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/StructureAdjustment/UnknownNodeType.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/StructureAdjustment/UnknownNodeType.feature @@ -17,7 +17,6 @@ Feature: Unknown node types | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | @@ -34,7 +33,6 @@ Feature: Unknown node types | parentNodeAggregateId | "lady-eleonode-rootford" | | nodeName | "document" | | nodeAggregateClassification | "regular" | - And the graph projection is fully up to date Then I expect no needed structure adjustments for type "Neos.ContentRepository.Testing:Document" Scenario: When removing "Neos.ContentRepository.Testing:Document", we find a missing node type. diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/SubtreeTagging/TagSubtree_WithDimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/SubtreeTagging/TagSubtree_WithDimensions.feature index 6da6d7e9020..361e6d6c024 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/SubtreeTagging/TagSubtree_WithDimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/SubtreeTagging/TagSubtree_WithDimensions.feature @@ -22,13 +22,11 @@ Feature: Tag subtree with dimensions | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "root" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | nodeTypeName | parentNodeAggregateId | nodeName | originDimensionSpacePoint | | a | Neos.ContentRepository.Testing:Document | root | a | {"language":"mul"} | @@ -43,7 +41,6 @@ Feature: Tag subtree with dimensions | nodeAggregateId | "a1" | | sourceOrigin | {"language":"de"} | | targetOrigin | {"language":"mul"} | - And the graph projection is fully up to date And the command TagSubtree is executed with payload: | Key | Value | @@ -63,8 +60,6 @@ Feature: Tag subtree with dimensions | sourceOrigin | {"language":"de"} | | targetOrigin | {"language":"mul"} | - And the graph projection is fully up to date - When I execute the findSubtree query for entry node aggregate id "a" I expect the following tree with tags: """ a @@ -129,26 +124,22 @@ Feature: Tag subtree with dimensions | workspaceName | "user-ws" | | baseWorkspaceName | "live" | | newContentStreamId | "user-cs-id" | - And the graph projection is fully up to date When the command CreateNodeVariant is executed with payload: | Key | Value | | workspaceName | "user-ws" | | nodeAggregateId | "a1" | | sourceOrigin | {"language":"de"} | | targetOrigin | {"language":"gsw"} | - And the graph projection is fully up to date When the command CreateNodeVariant is executed with payload: | Key | Value | | workspaceName | "user-ws" | | nodeAggregateId | "a1a" | | sourceOrigin | {"language":"de"} | | targetOrigin | {"language":"gsw"} | - And the graph projection is fully up to date And the command PublishWorkspace is executed with payload: | Key | Value | | workspaceName | "user-ws" | | newContentStreamId | "new-user-cs-id" | - And the graph projection is fully up to date And the command RemoveNodeAggregate is executed with payload: | Key | Value | @@ -156,7 +147,6 @@ Feature: Tag subtree with dimensions | nodeAggregateId | "a1" | | coveredDimensionSpacePoint | {"language":"gsw"} | | nodeVariantSelectionStrategy | "allSpecializations" | - And the graph projection is fully up to date And the command TagSubtree is executed with payload: | Key | Value | @@ -172,14 +162,12 @@ Feature: Tag subtree with dimensions | nodeAggregateId | "a1" | | sourceOrigin | {"language":"de"} | | targetOrigin | {"language":"gsw"} | - And the graph projection is fully up to date When the command CreateNodeVariant is executed with payload: | Key | Value | | workspaceName | "user-ws" | | nodeAggregateId | "a1a" | | sourceOrigin | {"language":"de"} | | targetOrigin | {"language":"gsw"} | - And the graph projection is fully up to date And I am in the active content stream of workspace "user-ws" and dimension space point {"language":"gsw"} And I execute the findSubtree query for entry node aggregate id "a" I expect the following tree with tags: """ diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/SubtreeTagging/TagSubtree_WithoutDimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/SubtreeTagging/TagSubtree_WithoutDimensions.feature index c88e62f53b3..92664759680 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/SubtreeTagging/TagSubtree_WithoutDimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/SubtreeTagging/TagSubtree_WithoutDimensions.feature @@ -20,13 +20,11 @@ Feature: Tag subtree without dimensions | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "root" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | nodeTypeName | parentNodeAggregateId | nodeName | | a | Neos.ContentRepository.Testing:Document | root | a | @@ -47,7 +45,6 @@ Feature: Tag subtree without dimensions | nodeAggregateId | "a1" | | nodeVariantSelectionStrategy | "allVariants" | | tag | "tag1" | - And the graph projection is fully up to date Then I expect exactly 14 events to be published on stream with prefix "ContentStream:cs-identifier" And event at index 13 is of type "SubtreeWasTagged" with payload: | Key | Expected | @@ -77,7 +74,6 @@ Feature: Tag subtree without dimensions | nodeAggregateId | "a1" | | nodeVariantSelectionStrategy | "allVariants" | | tag | "tag1" | - And the graph projection is fully up to date Then I expect exactly 14 events to be published on stream with prefix "ContentStream:cs-identifier" And event at index 13 is of type "SubtreeWasTagged" with payload: | Key | Expected | @@ -106,8 +102,6 @@ Feature: Tag subtree without dimensions | nodeAggregateId | "a1" | | affectedDimensionSpacePoints | [[]] | | tag | "tag1" | - - When the graph projection is fully up to date And I am in content stream "cs-identifier" Then I expect the graph projection to consist of exactly 12 nodes @@ -137,7 +131,6 @@ Feature: Tag subtree without dimensions | nodeAggregateId | "a1a" | | nodeVariantSelectionStrategy | "allVariants" | | tag | "tag4" | - And the graph projection is fully up to date When I execute the findSubtree query for entry node aggregate id "a" I expect the following tree with tags: """ @@ -161,7 +154,6 @@ Feature: Tag subtree without dimensions | Key | Value | | nodeAggregateId | "a1a" | | newParentNodeAggregateId | "b1" | - And the graph projection is fully up to date When I execute the findSubtree query for entry node aggregate id "a" I expect the following tree with tags: """ a diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W10-IndividualNodeDiscarding/01-ConstraintChecks.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W10-IndividualNodeDiscarding/01-ConstraintChecks.feature index 271e9440ced..cf75d0cc886 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W10-IndividualNodeDiscarding/01-ConstraintChecks.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W10-IndividualNodeDiscarding/01-ConstraintChecks.feature @@ -29,7 +29,6 @@ Feature: Workspace discarding - complex chained functionality | Key | Value | | workspaceName | "live" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language": "de"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | @@ -46,7 +45,6 @@ Feature: Workspace discarding - complex chained functionality | workspaceName | "user-ws" | | baseWorkspaceName | "live" | | newContentStreamId | "user-cs-id" | - And the graph projection is fully up to date Scenario: Vary to generalization, then delete the origin and discard parts of the result so that an exception is thrown. Ensure that the workspace recovers from this When the command CreateNodeVariant is executed with payload: @@ -55,14 +53,12 @@ Feature: Workspace discarding - complex chained functionality | nodeAggregateId | "sir-david-nodenborough" | | sourceOrigin | {"language": "de"} | | targetOrigin | {"language": "en"} | - And the graph projection is fully up to date And the command CreateNodeVariant is executed with payload: | Key | Value | | workspaceName | "user-ws" | | nodeAggregateId | "nody-mc-nodeface" | | sourceOrigin | {"language": "de"} | | targetOrigin | {"language": "en"} | - And the graph projection is fully up to date And the command RemoveNodeAggregate is executed with payload: | Key | Value | @@ -70,7 +66,6 @@ Feature: Workspace discarding - complex chained functionality | nodeAggregateId | "sir-david-nodenborough" | | coveredDimensionSpacePoint | {"language": "en"} | | nodeVariantSelectionStrategy | "allSpecializations" | - And the graph projection is fully up to date When the command DiscardIndividualNodesFromWorkspace is executed with payload and exceptions are caught: | Key | Value | @@ -83,6 +78,5 @@ Feature: Workspace discarding - complex chained functionality | Key | Value | | workspaceName | "user-ws" | | newContentStreamId | "user-cs-id-yet-again-rebased" | - And the graph projection is fully up to date When I am in the active content stream of workspace "user-ws" and dimension space point {"language": "de"} Then I expect node aggregate identifier "nody-mc-nodeface" to lead to node user-cs-id-yet-again-rebased;nody-mc-nodeface;{"language": "de"} diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W10-IndividualNodeDiscarding/02-BasicFeatures.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W10-IndividualNodeDiscarding/02-BasicFeatures.feature index 7698343042a..4e4954b2ce1 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W10-IndividualNodeDiscarding/02-BasicFeatures.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W10-IndividualNodeDiscarding/02-BasicFeatures.feature @@ -29,7 +29,6 @@ Feature: Discard individual nodes (basics) | Key | Value | | workspaceName | "live" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | @@ -65,7 +64,6 @@ Feature: Discard individual nodes (basics) | parentNodeAggregateId | "lady-eleonode-rootford" | | initialPropertyValues | {"image": {"type": "string", "value": "Initial image"}} | | nodeAggregateClassification | "regular" | - And the graph projection is fully up to date # Create user workspace And the command CreateWorkspace is executed with payload: @@ -73,7 +71,6 @@ Feature: Discard individual nodes (basics) | workspaceName | "user-test" | | baseWorkspaceName | "live" | | newContentStreamId | "user-cs-identifier" | - And the graph projection is fully up to date # modify nodes in user WS And the command SetNodeProperties is executed with payload: | Key | Value | @@ -93,7 +90,6 @@ Feature: Discard individual nodes (basics) | nodeAggregateId | "sir-nodeward-nodington-iii" | | originDimensionSpacePoint | {} | | propertyValues | {"image": "Modified image"} | - And the graph projection is fully up to date ################ # DISCARDING @@ -106,8 +102,6 @@ Feature: Discard individual nodes (basics) | nodesToDiscard | [{"workspaceName": "user-test", "dimensionSpacePoint": {}, "nodeAggregateId": "sir-nodeward-nodington-iii"}] | | newContentStreamId | "user-cs-identifier-new" | - And the graph projection is fully up to date - When I am in the active content stream of workspace "user-test" and dimension space point {} Then I expect node aggregate identifier "sir-david-nodenborough" to lead to node user-cs-identifier-new;sir-david-nodenborough;{} And I expect this node to have the following properties: @@ -128,7 +122,6 @@ Feature: Discard individual nodes (basics) | workspaceName | "user-test" | | nodesToDiscard | [] | | newContentStreamId | "user-cs-identifier-new" | - And the graph projection is fully up to date When I am in the active content stream of workspace "user-test" and dimension space point {} Then I expect node aggregate identifier "sir-david-nodenborough" to lead to node user-cs-identifier-new;sir-david-nodenborough;{} @@ -150,7 +143,6 @@ Feature: Discard individual nodes (basics) | workspaceName | "user-test" | | nodesToDiscard | [{"workspaceName": "user-test", "dimensionSpacePoint": {}, "nodeAggregateId": "sir-david-nodenborough"}, {"workspaceName": "user-test", "dimensionSpacePoint": {}, "nodeAggregateId": "nody-mc-nodeface"}, {"workspaceName": "user-test", "dimensionSpacePoint": {}, "nodeAggregateId": "sir-nodeward-nodington-iii"}] | | newContentStreamId | "user-cs-identifier-new" | - And the graph projection is fully up to date When I am in the active content stream of workspace "user-test" and dimension space point {} Then I expect node aggregate identifier "sir-david-nodenborough" to lead to node user-cs-identifier-new;sir-david-nodenborough;{} @@ -172,7 +164,6 @@ Feature: Discard individual nodes (basics) | Key | Value | | workspaceName | "user-test" | | nodesToDiscard | [{"workspaceName": "user-test", "dimensionSpacePoint": {}, "nodeAggregateId": "sir-nodeward-nodington-iii"}] | - And the graph projection is fully up to date # live WS does not change because of a discard When I am in the active content stream of workspace "live" and dimension space point {} diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W6-WorkspaceRebasing/02-RebasingWithAutoCreatedNodes.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W6-WorkspaceRebasing/02-RebasingWithAutoCreatedNodes.feature index cd071f56e12..0d91124b273 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W6-WorkspaceRebasing/02-RebasingWithAutoCreatedNodes.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W6-WorkspaceRebasing/02-RebasingWithAutoCreatedNodes.feature @@ -34,19 +34,16 @@ Feature: Rebasing auto-created nodes works | workspaceName | "live" | | newContentStreamId | "cs-identifier" | And I am in the active content stream of workspace "live" and dimension space point {} - And the graph projection is fully up to date And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date And the command CreateWorkspace is executed with payload: | Key | Value | | workspaceName | "user-test" | | baseWorkspaceName | "live" | | newContentStreamId | "user-cs-identifier" | - And the graph projection is fully up to date Scenario: complex scenario (to reproduce the bug) -- see the feature description # USER workspace: create a new node with auto-created child nodes @@ -58,7 +55,6 @@ Feature: Rebasing auto-created nodes works | nodeName | "mcnodeface" | | originDimensionSpacePoint | {} | | parentNodeAggregateId | "lady-eleonode-rootford" | - And the graph projection is fully up to date And I am in content stream "user-cs-identifier" and dimension space point {} Then I expect node aggregate identifier "nody-mc-nodeface" to lead to node user-cs-identifier;nody-mc-nodeface;{} When I get the node at path "mcnodeface/foo" @@ -72,11 +68,9 @@ Feature: Rebasing auto-created nodes works | originDimensionSpacePoint | {} | | propertyValues | {"text": {"value":"Modified","type":"string"}} | | propertiesToUnset | {} | - And the graph projection is fully up to date When the command RebaseWorkspace is executed with payload: | Key | Value | | workspaceName | "user-test" | - And the graph projection is fully up to date # This should properly work; no error. diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W6-WorkspaceRebasing/03-RebasingWithConflictingChanges.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W6-WorkspaceRebasing/03-RebasingWithConflictingChanges.feature index f47658abbf1..9ef51d5f143 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W6-WorkspaceRebasing/03-RebasingWithConflictingChanges.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W6-WorkspaceRebasing/03-RebasingWithConflictingChanges.feature @@ -22,7 +22,6 @@ Feature: Workspace rebasing - conflicting changes | Key | Value | | workspaceName | "live" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | @@ -38,16 +37,12 @@ Feature: Workspace rebasing - conflicting changes | nodeAggregateId | "nody-mc-nodeface" | | originDimensionSpacePoint | {} | | propertyValues | {"text": "Original"} | - # we need to ensure that the projections are up to date now; otherwise a content stream is forked with an out- - # of-date base version. This means the content stream can never be merged back, but must always be rebased. - And the graph projection is fully up to date And the command CreateWorkspace is executed with payload: | Key | Value | | workspaceName | "user-test" | | baseWorkspaceName | "live" | | newContentStreamId | "user-cs-identifier" | | workspaceOwner | "owner-identifier" | - And the graph projection is fully up to date Scenario: Conflicting changes lead to OUTDATED_CONFLICT which can be recovered from via forced rebase @@ -57,14 +52,12 @@ Feature: Workspace rebasing - conflicting changes | baseWorkspaceName | "live" | | newContentStreamId | "user-cs-one" | | workspaceOwner | "owner-identifier" | - And the graph projection is fully up to date And the command CreateWorkspace is executed with payload: | Key | Value | | workspaceName | "user-ws-two" | | baseWorkspaceName | "live" | | newContentStreamId | "user-cs-two" | | workspaceOwner | "owner-identifier" | - And the graph projection is fully up to date When the command RemoveNodeAggregate is executed with payload: | Key | Value | @@ -72,7 +65,6 @@ Feature: Workspace rebasing - conflicting changes | nodeVariantSelectionStrategy | "allVariants" | | coveredDimensionSpacePoint | {} | | workspaceName | "user-ws-one" | - And the graph projection is fully up to date When the command SetNodeProperties is executed with payload: | Key | Value | @@ -80,7 +72,6 @@ Feature: Workspace rebasing - conflicting changes | nodeAggregateId | "nody-mc-nodeface" | | originDimensionSpacePoint | {} | | propertyValues | {"text": "Modified"} | - And the graph projection is fully up to date And the command CreateNodeAggregateWithNode is executed with payload: | Key | Value | @@ -89,7 +80,6 @@ Feature: Workspace rebasing - conflicting changes | parentNodeAggregateId | "lady-eleonode-rootford" | | originDimensionSpacePoint | {} | | workspaceName | "user-ws-two" | - And the graph projection is fully up to date And the command SetNodeProperties is executed with payload: | Key | Value | @@ -97,12 +87,10 @@ Feature: Workspace rebasing - conflicting changes | nodeAggregateId | "noderus-secundus" | | originDimensionSpacePoint | {} | | propertyValues | {"text": "The other node"} | - And the graph projection is fully up to date And the command PublishWorkspace is executed with payload: | Key | Value | | workspaceName | "user-ws-one" | - And the graph projection is fully up to date Then workspace user-ws-two has status OUTDATED @@ -111,7 +99,6 @@ Feature: Workspace rebasing - conflicting changes | workspaceName | "user-ws-two" | | rebasedContentStreamId | "user-cs-two-rebased" | | rebaseErrorHandlingStrategy | "force" | - And the graph projection is fully up to date Then workspace user-ws-two has status UP_TO_DATE And I expect a node identified by user-cs-two-rebased;noderus-secundus;{} to exist in the content graph diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W7-WorkspacePublication/02-PublishWorkspace.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W7-WorkspacePublication/02-PublishWorkspace.feature index ce52bbcb253..c6da2cb54dd 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W7-WorkspacePublication/02-PublishWorkspace.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W7-WorkspacePublication/02-PublishWorkspace.feature @@ -22,7 +22,6 @@ Feature: Workspace based content publishing | Key | Value | | workspaceName | "live" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | @@ -38,16 +37,12 @@ Feature: Workspace based content publishing | nodeAggregateId | "nody-mc-nodeface" | | originDimensionSpacePoint | {} | | propertyValues | {"text": "Original"} | - # we need to ensure that the projections are up to date now; otherwise a content stream is forked with an out- - # of-date base version. This means the content stream can never be merged back, but must always be rebased. - And the graph projection is fully up to date And the command CreateWorkspace is executed with payload: | Key | Value | | workspaceName | "user-test" | | baseWorkspaceName | "live" | | newContentStreamId | "user-cs-identifier" | | workspaceOwner | "owner-identifier" | - And the graph projection is fully up to date Scenario: Basic events are emitted # LIVE workspace @@ -89,7 +84,6 @@ Feature: Workspace based content publishing | nodeAggregateId | "nody-mc-nodeface" | | originDimensionSpacePoint | {} | | propertyValues | {"text": "Modified"} | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {} Then I expect node aggregate identifier "nody-mc-nodeface" to lead to node cs-identifier;nody-mc-nodeface;{} @@ -107,7 +101,6 @@ Feature: Workspace based content publishing When the command PublishWorkspace is executed with payload: | Key | Value | | workspaceName | "user-test" | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {} Then I expect node aggregate identifier "nody-mc-nodeface" to lead to node cs-identifier;nody-mc-nodeface;{} @@ -123,14 +116,12 @@ Feature: Workspace based content publishing | nodeAggregateId | "nody-mc-nodeface" | | originDimensionSpacePoint | {} | | propertyValues | {"text": "Modified in user workspace"} | - And the graph projection is fully up to date And the command SetNodeProperties is executed with payload: | Key | Value | | workspaceName | "live" | | nodeAggregateId | "nody-mc-nodeface" | | originDimensionSpacePoint | {} | | propertyValues | {"text": "Modified in live workspace"} | - And the graph projection is fully up to date # PUBLISHING without rebase: error When the command PublishWorkspace is executed with payload and exceptions are caught: @@ -144,12 +135,10 @@ Feature: Workspace based content publishing | Key | Value | | workspaceName | "user-test" | | rebasedContentStreamId | "rebased-cs-id" | - And the graph projection is fully up to date And the command PublishWorkspace is executed with payload: | Key | Value | | workspaceName | "user-test" | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {} @@ -167,13 +156,10 @@ Feature: Workspace based content publishing | originDimensionSpacePoint | {} | | propertyValues | {"text": "Modified"} | - And the graph projection is fully up to date - # PUBLISHING And the command PublishWorkspace is executed with payload: | Key | Value | | workspaceName | "user-test" | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {} When the command SetNodeProperties is executed with payload: @@ -183,13 +169,10 @@ Feature: Workspace based content publishing | originDimensionSpacePoint | {} | | propertyValues | {"text": "Modified anew"} | - And the graph projection is fully up to date - # PUBLISHING And the command PublishWorkspace is executed with payload: | Key | Value | | workspaceName | "user-test" | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {} Then I expect node aggregate identifier "nody-mc-nodeface" to lead to node cs-identifier;nody-mc-nodeface;{} diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W8-IndividualNodePublication/01-ConstraintChecks.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W8-IndividualNodePublication/01-ConstraintChecks.feature index 90504e16e75..072304407b0 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W8-IndividualNodePublication/01-ConstraintChecks.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W8-IndividualNodePublication/01-ConstraintChecks.feature @@ -29,7 +29,6 @@ Feature: Workspace publication - complex chained functionality | Key | Value | | workspaceName | "live" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {"language": "de"} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | @@ -46,7 +45,6 @@ Feature: Workspace publication - complex chained functionality | workspaceName | "user-ws" | | baseWorkspaceName | "live" | | newContentStreamId | "user-cs-id" | - And the graph projection is fully up to date Scenario: Vary to generalization, then publish only the child node so that an exception is thrown. Ensure that the workspace recovers from this When the command CreateNodeVariant is executed with payload: @@ -55,14 +53,12 @@ Feature: Workspace publication - complex chained functionality | nodeAggregateId | "sir-david-nodenborough" | | sourceOrigin | {"language": "de"} | | targetOrigin | {"language": "en"} | - And the graph projection is fully up to date And the command CreateNodeVariant is executed with payload: | Key | Value | | workspaceName | "user-ws" | | nodeAggregateId | "nody-mc-nodeface" | | sourceOrigin | {"language": "de"} | | targetOrigin | {"language": "en"} | - And the graph projection is fully up to date When the command PublishIndividualNodesFromWorkspace is executed with payload and exceptions are caught: | Key | Value | @@ -75,6 +71,5 @@ Feature: Workspace publication - complex chained functionality | Key | Value | | workspaceName | "user-ws" | | newContentStreamId | "user-cs-id-yet-again-rebased" | - And the graph projection is fully up to date When I am in the active content stream of workspace "user-ws" and dimension space point {"language": "de"} Then I expect node aggregate identifier "nody-mc-nodeface" to lead to node user-cs-id-yet-again-rebased;nody-mc-nodeface;{"language": "de"} diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W8-IndividualNodePublication/02-BasicFeatures.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W8-IndividualNodePublication/02-BasicFeatures.feature index d7605cc24b9..2a576b6290c 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W8-IndividualNodePublication/02-BasicFeatures.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W8-IndividualNodePublication/02-BasicFeatures.feature @@ -21,14 +21,12 @@ Feature: Individual node publication | Key | Value | | workspaceName | "live" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in workspace "live" And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | workspaceName | "live" | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date # Create user workspace And the command CreateWorkspace is executed with payload: @@ -36,7 +34,6 @@ Feature: Individual node publication | workspaceName | "user-test" | | baseWorkspaceName | "live" | | newContentStreamId | "user-cs-identifier" | - And the graph projection is fully up to date ################ # PUBLISHING @@ -58,7 +55,6 @@ Feature: Individual node publication | nodesToPublish | [{"workspaceName": "user-test", "dimensionSpacePoint": {}, "nodeAggregateId": "sir-david-nodenborough"}] | | contentStreamIdForRemainingPart | "user-cs-identifier-remaining" | | contentStreamIdForMatchingPart | "user-cs-identifier-matching" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W8-IndividualNodePublication/03-MoreBasicFeatures.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W8-IndividualNodePublication/03-MoreBasicFeatures.feature index cd22380f14c..a01e57d467c 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W8-IndividualNodePublication/03-MoreBasicFeatures.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W8-IndividualNodePublication/03-MoreBasicFeatures.feature @@ -29,7 +29,6 @@ Feature: Publishing individual nodes (basics) | Key | Value | | workspaceName | "live" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | @@ -65,7 +64,6 @@ Feature: Publishing individual nodes (basics) | parentNodeAggregateId | "lady-eleonode-rootford" | | initialPropertyValues | {"image": {"type": "string", "value": "Initial image"}} | | nodeAggregateClassification | "regular" | - And the graph projection is fully up to date # Create user workspace And the command CreateWorkspace is executed with payload: @@ -73,7 +71,6 @@ Feature: Publishing individual nodes (basics) | workspaceName | "user-test" | | baseWorkspaceName | "live" | | newContentStreamId | "user-cs-identifier" | - And the graph projection is fully up to date # modify nodes in user WS And the command SetNodeProperties is executed with payload: | Key | Value | @@ -93,7 +90,6 @@ Feature: Publishing individual nodes (basics) | nodeAggregateId | "sir-nodeward-nodington-iii" | | originDimensionSpacePoint | {} | | propertyValues | {"image": "Modified image"} | - And the graph projection is fully up to date ################ # PUBLISHING @@ -106,7 +102,6 @@ Feature: Publishing individual nodes (basics) | nodesToPublish | [{"workspaceName": "user-test", "dimensionSpacePoint": {}, "nodeAggregateId": "sir-nodeward-nodington-iii"}] | | contentStreamIdForRemainingPart | "user-cs-identifier-remaining" | | contentStreamIdForMatchingPart | "user-cs-identifier-matching" | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {} Then I expect node aggregate identifier "sir-david-nodenborough" to lead to node cs-identifier;sir-david-nodenborough;{} @@ -142,7 +137,6 @@ Feature: Publishing individual nodes (basics) | workspaceName | "user-test" | | nodesToPublish | [] | | contentStreamIdForRemainingPart | "user-cs-identifier-remaining" | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {} Then I expect node aggregate identifier "sir-david-nodenborough" to lead to node cs-identifier;sir-david-nodenborough;{} @@ -178,7 +172,6 @@ Feature: Publishing individual nodes (basics) | workspaceName | "user-test" | | nodesToPublish | [{"workspaceName": "user-test", "dimensionSpacePoint": {}, "nodeAggregateId": "sir-david-nodenborough"}, {"workspaceName": "user-test", "dimensionSpacePoint": {}, "nodeAggregateId": "nody-mc-nodeface"}, {"workspaceName": "user-test", "dimensionSpacePoint": {}, "nodeAggregateId": "sir-nodeward-nodington-iii"}] | | contentStreamIdForRemainingPart | "user-cs-identifier-remaining" | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {} Then I expect node aggregate identifier "sir-david-nodenborough" to lead to node cs-identifier;sir-david-nodenborough;{} diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W8-IndividualNodePublication/04-AllFeaturePublication.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W8-IndividualNodePublication/04-AllFeaturePublication.feature index dfdb72c5b5f..c2477cb7a9b 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W8-IndividualNodePublication/04-AllFeaturePublication.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W8-IndividualNodePublication/04-AllFeaturePublication.feature @@ -38,7 +38,6 @@ Feature: Publishing hide/show scenario of nodes | Key | Value | | workspaceName | "live" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | @@ -74,7 +73,6 @@ Feature: Publishing hide/show scenario of nodes | parentNodeAggregateId | "lady-eleonode-rootford" | | initialPropertyValues | {"image": {"type": "image", "value": "Initial image"}} | | nodeAggregateClassification | "regular" | - And the graph projection is fully up to date Scenario: (DisableNode) It is possible to publish hiding of a node. Given the command CreateWorkspace is executed with payload: @@ -82,7 +80,6 @@ Feature: Publishing hide/show scenario of nodes | workspaceName | "user-test" | | baseWorkspaceName | "live" | | newContentStreamId | "user-cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "user-test" # SETUP: hide two nodes in USER workspace @@ -96,7 +93,6 @@ Feature: Publishing hide/show scenario of nodes | nodeAggregateId | "sir-nodeward-nodington-iii" | | coveredDimensionSpacePoint | {} | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date When the command PublishIndividualNodesFromWorkspace is executed with payload: | Key | Value | @@ -104,7 +100,6 @@ Feature: Publishing hide/show scenario of nodes | nodesToPublish | [{"nodeAggregateId": "sir-david-nodenborough", "workspaceName": "user-test", "dimensionSpacePoint": {}}] | | contentStreamIdForRemainingPart | "remaining-cs-id" | | contentStreamIdForMatchingPart | "matching-cs-id" | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {} Then I expect node aggregate identifier "sir-david-nodenborough" to lead to no node @@ -128,15 +123,11 @@ Feature: Publishing hide/show scenario of nodes | nodeAggregateId | "sir-nodeward-nodington-iii" | | coveredDimensionSpacePoint | {} | | nodeVariantSelectionStrategy | "allVariants" | - # we need to ensure that the projections are up to date now; otherwise a content stream is forked with an out- - # of-date base version. This means the content stream can never be merged back, but must always be rebased. - And the graph projection is fully up to date Given the command CreateWorkspace is executed with payload: | Key | Value | | workspaceName | "user-test" | | baseWorkspaceName | "live" | | newContentStreamId | "user-cs-identifier" | - And the graph projection is fully up to date # SETUP: enable two nodes in USER workspace Given the command EnableNodeAggregate is executed with payload: @@ -151,14 +142,12 @@ Feature: Publishing hide/show scenario of nodes | nodeAggregateId | "sir-nodeward-nodington-iii" | | coveredDimensionSpacePoint | {} | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date When the command PublishIndividualNodesFromWorkspace is executed with payload: | Key | Value | | workspaceName | "user-test" | | nodesToPublish | [{"nodeAggregateId": "sir-david-nodenborough", "workspaceName": "user-test", "dimensionSpacePoint": {}}] | | contentStreamIdForRemainingPart | "user-cs-identifier-modified" | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {} Then I expect node aggregate identifier "sir-david-nodenborough" to lead to node cs-identifier;sir-david-nodenborough;{} @@ -179,7 +168,7 @@ Feature: Publishing hide/show scenario of nodes ## | workspaceName | "user-test" | # | baseWorkspaceName | "live" | # | newContentStreamId | "user-cs-identifier" | - # And the graph projection is fully up to date + # # SETUP: change two node names in USER workspace #Given the command "ChangeNodeAggregateName" is executed with payload: @@ -192,13 +181,12 @@ Feature: Publishing hide/show scenario of nodes # | contentStreamId | "user-cs-identifier" | # | nodeAggregateId | "sir-nodeward-nodington-iii" | # | newNodeName | "imagemod" | - # And the graph projection is fully up to date + # # When the command PublishIndividualNodesFromWorkspace is executed with payload: # | Key | Value | # | workspaceName | "user-test" | # | nodesToPublish | [{"nodeAggregateId": "sir-david-nodenborough", "contentStreamId": "user-cs-identifier", "dimensionSpacePoint": {}}] | - #And the graph projection is fully up to date # When I am in the active content stream of workspace "live" and dimension space point {} ## Then I expect the node aggregate "lady-eleonode-rootford" to have the following child nodes: @@ -219,7 +207,6 @@ Feature: Publishing hide/show scenario of nodes | workspaceName | "user-test" | | baseWorkspaceName | "live" | | newContentStreamId | "user-cs-identifier" | - And the graph projection is fully up to date # SETUP: remove two nodes in USER workspace When the command RemoveNodeAggregate is executed with payload: @@ -235,14 +222,12 @@ Feature: Publishing hide/show scenario of nodes | nodeAggregateId | "sir-nodeward-nodington-iii" | | coveredDimensionSpacePoint | {} | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date When the command PublishIndividualNodesFromWorkspace is executed with payload: | Key | Value | | workspaceName | "user-test" | | nodesToPublish | [{"nodeAggregateId": "sir-david-nodenborough", "workspaceName": "user-test", "dimensionSpacePoint": {}}] | | contentStreamIdForRemainingPart | "user-cs-identifier-modified" | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {} Then I expect node aggregate identifier "sir-david-nodenborough" to lead to no node @@ -261,7 +246,6 @@ Feature: Publishing hide/show scenario of nodes | workspaceName | "user-test" | | baseWorkspaceName | "live" | | newContentStreamId | "user-cs-identifier" | - And the graph projection is fully up to date # SETUP: remove two nodes in USER workspace When the command RemoveNodeAggregate is executed with payload: @@ -276,13 +260,11 @@ Feature: Publishing hide/show scenario of nodes | nodeAggregateId | "sir-nodeward-nodington-iii" | | coveredDimensionSpacePoint | {} | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date When the command PublishIndividualNodesFromWorkspace is executed with payload: | Key | Value | | workspaceName | "user-test" | | nodesToPublish | [{"nodeAggregateId": "sir-david-nodenborough", "workspaceName": "user-test", "dimensionSpacePoint": {}}] | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {} Then I expect node aggregate identifier "sir-david-nodenborough" to lead to no node @@ -301,7 +283,6 @@ Feature: Publishing hide/show scenario of nodes | workspaceName | "user-test" | | baseWorkspaceName | "live" | | newContentStreamId | "user-cs-identifier" | - And the graph projection is fully up to date # SETUP: set two node references in USER workspace When the command SetNodeReferences is executed with payload: @@ -318,14 +299,12 @@ Feature: Publishing hide/show scenario of nodes | sourceOriginDimensionSpacePoint | {} | | referenceName | "referenceProperty" | | references | [{"target":"sir-nodeward-nodington-iii"}] | - And the graph projection is fully up to date When the command PublishIndividualNodesFromWorkspace is executed with payload: | Key | Value | | workspaceName | "user-test" | | nodesToPublish | [{"nodeAggregateId": "sir-david-nodenborough", "workspaceName": "user-test", "dimensionSpacePoint": {}}] | | contentStreamIdForRemainingPart | "user-cs-identifier-modified" | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {} Then I expect node aggregate identifier "sir-david-nodenborough" to lead to node cs-identifier;sir-david-nodenborough;{} @@ -361,7 +340,6 @@ Feature: Publishing hide/show scenario of nodes | workspaceName | "user-test" | | baseWorkspaceName | "live" | | newContentStreamId | "user-cs-identifier" | - And the graph projection is fully up to date # SETUP: set two new nodes in USER workspace When the command CreateNodeAggregateWithNodeAndSerializedProperties is executed with payload: @@ -380,14 +358,12 @@ Feature: Publishing hide/show scenario of nodes | originDimensionSpacePoint | {} | | parentNodeAggregateId | "lady-eleonode-rootford" | | nodeName | "foo2" | - And the graph projection is fully up to date When the command PublishIndividualNodesFromWorkspace is executed with payload: | Key | Value | | workspaceName | "user-test" | | nodesToPublish | [{"nodeAggregateId": "new1-agg", "workspaceName": "user-test", "dimensionSpacePoint": {}}] | | contentStreamIdForRemainingPart | "user-cs-identifier-modified" | - And the graph projection is fully up to date When I am in the active content stream of workspace "live" and dimension space point {} Then I expect node aggregate identifier "new1-agg" to lead to node cs-identifier;new1-agg;{} diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W8-IndividualNodePublication/05-PublishMovedNodesWithoutDimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W8-IndividualNodePublication/05-PublishMovedNodesWithoutDimensions.feature index 9b2018d0cb1..37d27954ec5 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W8-IndividualNodePublication/05-PublishMovedNodesWithoutDimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W8-IndividualNodePublication/05-PublishMovedNodesWithoutDimensions.feature @@ -22,7 +22,6 @@ Feature: Publishing moved nodes without dimensions | Key | Value | | workspaceName | "live" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | @@ -58,14 +57,12 @@ Feature: Publishing moved nodes without dimensions | parentNodeAggregateId | "lady-eleonode-rootford" | | nodeName | "esquire" | | nodeAggregateClassification | "regular" | - And the graph projection is fully up to date And the command CreateWorkspace is executed with payload: | Key | Value | | workspaceName | "user" | | baseWorkspaceName | "live" | | newContentStreamId | "user-cs-identifier" | - And the graph projection is fully up to date Scenario: Publish the move of a node to the end of its siblings When the command MoveNodeAggregate is executed with payload: @@ -79,7 +76,6 @@ Feature: Publishing moved nodes without dimensions | Key | Value | | workspaceName | "user" | | nodesToPublish | [{"workspaceName": "user", "dimensionSpacePoint": {}, "nodeAggregateId": "sir-david-nodenborough"}] | - And the graph projection is fully up to date Then I expect the graph projection to consist of exactly 4 nodes And I expect a node identified by cs-identifier;lady-eleonode-rootford;{} to exist in the content graph @@ -119,7 +115,6 @@ Feature: Publishing moved nodes without dimensions | Key | Value | | workspaceName | "user" | | nodesToPublish | [{"workspaceName": "user", "dimensionSpacePoint": {}, "nodeAggregateId": "sir-nodeward-nodington-iii"}] | - And the graph projection is fully up to date Then I expect the graph projection to consist of exactly 4 nodes And I expect a node identified by cs-identifier;lady-eleonode-rootford;{} to exist in the content graph @@ -158,7 +153,6 @@ Feature: Publishing moved nodes without dimensions | parentNodeAggregateId | "sir-nodeward-nodington-iii" | | nodeName | "other-document" | | nodeAggregateClassification | "regular" | - And the graph projection is fully up to date When the command MoveNodeAggregate is executed with payload: | Key | Value | | workspaceName | "user" | @@ -169,7 +163,6 @@ Feature: Publishing moved nodes without dimensions | Key | Value | | workspaceName | "user" | | nodesToPublish | [{"workspaceName": "user", "dimensionSpacePoint": {}, "nodeAggregateId": "sir-david-nodenborough"}] | - And the graph projection is fully up to date Then I expect the graph projection to consist of exactly 5 nodes And I expect a node identified by cs-identifier;lady-eleonode-rootford;{} to exist in the content graph @@ -214,8 +207,6 @@ Feature: Publishing moved nodes without dimensions | Key | Value | | workspaceName | "user" | | nodesToPublish | [{"workspaceName": "user", "dimensionSpacePoint": {}, "nodeAggregateId": "nody-mc-nodeface"}] | - - When the graph projection is fully up to date Then I expect the graph projection to consist of exactly 4 nodes And I expect a node identified by cs-identifier;lady-eleonode-rootford;{} to exist in the content graph And I expect a node identified by cs-identifier;sir-david-nodenborough;{} to exist in the content graph diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W9-WorkspaceDiscarding/02-DiscardWorkspace.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W9-WorkspaceDiscarding/02-DiscardWorkspace.feature index 4f19a7d6741..3e82306a1b5 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W9-WorkspaceDiscarding/02-DiscardWorkspace.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/W9-WorkspaceDiscarding/02-DiscardWorkspace.feature @@ -22,7 +22,6 @@ Feature: Workspace discarding - basic functionality | Key | Value | | workspaceName | "live" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | @@ -38,16 +37,12 @@ Feature: Workspace discarding - basic functionality | nodeAggregateId | "nody-mc-nodeface" | | originDimensionSpacePoint | {} | | propertyValues | {"text": "Original"} | - # we need to ensure that the projections are up to date now; otherwise a content stream is forked with an out- - # of-date base version. This means the content stream can never be merged back, but must always be rebased. - And the graph projection is fully up to date And the command CreateWorkspace is executed with payload: | Key | Value | | workspaceName | "user-test" | | baseWorkspaceName | "live" | | newContentStreamId | "user-cs-identifier" | | workspaceOwner | "owner-identifier" | - And the graph projection is fully up to date Scenario: Discarding a full workspace works When the command SetNodeProperties is executed with payload: @@ -56,7 +51,6 @@ Feature: Workspace discarding - basic functionality | nodeAggregateId | "nody-mc-nodeface" | | originDimensionSpacePoint | {} | | propertyValues | {"text": "Modified"} | - And the graph projection is fully up to date When I am in the active content stream of workspace "user-test" and dimension space point {} Then I expect node aggregate identifier "nody-mc-nodeface" to lead to node user-cs-identifier;nody-mc-nodeface;{} @@ -69,7 +63,6 @@ Feature: Workspace discarding - basic functionality | Key | Value | | workspaceName | "user-test" | | newContentStreamId | "user-cs-identifier-modified" | - And the graph projection is fully up to date When I am in the active content stream of workspace "user-test" and dimension space point {} Then I expect node aggregate identifier "nody-mc-nodeface" to lead to node user-cs-identifier-modified;nody-mc-nodeface;{} @@ -84,7 +77,6 @@ Feature: Workspace discarding - basic functionality | nodeAggregateId | "nody-mc-nodeface" | | originDimensionSpacePoint | {} | | propertyValues | {"text": "Modified"} | - And the graph projection is fully up to date And the command SetNodeProperties is executed with payload: | Key | Value | @@ -92,14 +84,12 @@ Feature: Workspace discarding - basic functionality | nodeAggregateId | "nody-mc-nodeface" | | originDimensionSpacePoint | {} | | propertyValues | {"text": "Modified in live workspace"} | - And the graph projection is fully up to date # Discarding When the command DiscardWorkspace is executed with payload: | Key | Value | | workspaceName | "user-test" | | newContentStreamId | "user-cs-identifier-modified" | - And the graph projection is fully up to date When I am in the active content stream of workspace "user-test" and dimension space point {} Then I expect node aggregate identifier "nody-mc-nodeface" to lead to node user-cs-identifier-modified;nody-mc-nodeface;{} @@ -115,14 +105,12 @@ Feature: Workspace discarding - basic functionality | baseWorkspaceName | "live" | | newContentStreamId | "user-cs-one" | | workspaceOwner | "owner-identifier" | - And the graph projection is fully up to date And the command CreateWorkspace is executed with payload: | Key | Value | | workspaceName | "user-ws-two" | | baseWorkspaceName | "live" | | newContentStreamId | "user-cs-two" | | workspaceOwner | "owner-identifier" | - And the graph projection is fully up to date When the command RemoveNodeAggregate is executed with payload: | Key | Value | @@ -130,7 +118,6 @@ Feature: Workspace discarding - basic functionality | nodeAggregateId | "nody-mc-nodeface" | | nodeVariantSelectionStrategy | "allVariants" | | coveredDimensionSpacePoint | {} | - And the graph projection is fully up to date When the command SetNodeProperties is executed with payload: | Key | Value | @@ -138,12 +125,10 @@ Feature: Workspace discarding - basic functionality | nodeAggregateId | "nody-mc-nodeface" | | originDimensionSpacePoint | {} | | propertyValues | {"text": "Modified"} | - And the graph projection is fully up to date And the command PublishWorkspace is executed with payload: | Key | Value | | workspaceName | "user-ws-one" | - And the graph projection is fully up to date Then workspace user-ws-two has status OUTDATED @@ -158,7 +143,6 @@ Feature: Workspace discarding - basic functionality | Key | Value | | workspaceName | "user-ws-two" | | newContentStreamId | "user-cs-two-discarded" | - And the graph projection is fully up to date Then workspace user-ws-two has status OUTDATED diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/Workspaces/NodeOperationsOnMultipleWorkspaces.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/Workspaces/NodeOperationsOnMultipleWorkspaces.feature index 7e26a903218..7005422b9ff 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/Workspaces/NodeOperationsOnMultipleWorkspaces.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/Workspaces/NodeOperationsOnMultipleWorkspaces.feature @@ -16,7 +16,6 @@ Feature: Single Node operations on multiple workspaces/content streams; e.g. cop | Key | Value | | workspaceName | "live" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | @@ -42,19 +41,16 @@ Feature: Single Node operations on multiple workspaces/content streams; e.g. cop | parentNodeAggregateId | "nody-mc-nodeface" | | nodeName | "pet" | | nodeAggregateClassification | "regular" | - And the graph projection is fully up to date And the command SetNodeProperties is executed with payload: | Key | Value | | nodeAggregateId | "nody-mc-nodeface" | | originDimensionSpacePoint | {} | | propertyValues | {"text": "Original"} | - And the graph projection is fully up to date And the command CreateWorkspace is executed with payload: | Key | Value | | workspaceName | "user-test" | | baseWorkspaceName | "live" | | newContentStreamId | "user-cs-identifier" | - And the graph projection is fully up to date Scenario: Set property of a node Given the command SetNodeProperties is executed with payload: @@ -71,8 +67,6 @@ Feature: Single Node operations on multiple workspaces/content streams; e.g. cop | nodeAggregateId | "nody-mc-nodeface" | | originDimensionSpacePoint | [] | | propertyValues.text.value | "Changed" | - - When the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {} Then I expect node aggregate identifier "nody-mc-nodeface" to lead to node cs-identifier;nody-mc-nodeface;{} And I expect this node to have the following properties: diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/Workspaces/PruneContentStreams.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/Workspaces/PruneContentStreams.feature index 92dc9d8e919..3529984717d 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/Workspaces/PruneContentStreams.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/Workspaces/PruneContentStreams.feature @@ -13,13 +13,11 @@ Feature: If content streams are not in use anymore by the workspace, they can be | Key | Value | | workspaceName | "live" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "root-node" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date Scenario: content streams are marked as IN_USE_BY_WORKSPACE properly after creation Then the content stream "cs-identifier" has state "IN_USE_BY_WORKSPACE" @@ -31,7 +29,6 @@ Feature: If content streams are not in use anymore by the workspace, they can be | workspaceName | "user-test" | | baseWorkspaceName | "live" | | newContentStreamId | "user-cs-identifier" | - And the graph projection is fully up to date Then the content stream "user-cs-identifier" has state "IN_USE_BY_WORKSPACE" @@ -41,11 +38,9 @@ Feature: If content streams are not in use anymore by the workspace, they can be | workspaceName | "user-test" | | baseWorkspaceName | "live" | | newContentStreamId | "user-cs-identifier" | - And the graph projection is fully up to date When the command RebaseWorkspace is executed with payload: | Key | Value | | workspaceName | "user-test" | - And the graph projection is fully up to date When I am in the active content stream of workspace "user-test" and dimension space point {} Then the current content stream has state "IN_USE_BY_WORKSPACE" @@ -58,16 +53,13 @@ Feature: If content streams are not in use anymore by the workspace, they can be | workspaceName | "user-test" | | baseWorkspaceName | "live" | | newContentStreamId | "user-cs-identifier" | - And the graph projection is fully up to date When the command RebaseWorkspace is executed with payload: | Key | Value | | workspaceName | "user-test" | | rebasedContentStreamId | "user-cs-identifier-rebased" | - And the graph projection is fully up to date # now, we have one unused content stream (the old content stream of the user-test workspace) When I prune unused content streams - And the graph projection is fully up to date When I am in content stream "user-cs-identifier" and dimension space point {} Then I expect node aggregate identifier "root-node" to lead to no node @@ -82,15 +74,12 @@ Feature: If content streams are not in use anymore by the workspace, they can be | workspaceName | "user-test" | | baseWorkspaceName | "live" | | newContentStreamId | "user-cs-identifier" | - And the graph projection is fully up to date When the command RebaseWorkspace is executed with payload: | Key | Value | | workspaceName | "user-test" | - And the graph projection is fully up to date # now, we have one unused content stream (the old content stream of the user-test workspace) When I prune unused content streams - And the graph projection is fully up to date And I prune removed content streams from the event stream Then I expect exactly 0 events to be published on stream "ContentStream:user-cs-identifier" @@ -103,13 +92,11 @@ Feature: If content streams are not in use anymore by the workspace, they can be | workspaceName | "review" | | baseWorkspaceName | "live" | | newContentStreamId | "review-cs-identifier" | - And the graph projection is fully up to date And the command CreateWorkspace is executed with payload: | Key | Value | | workspaceName | "user-test" | | baseWorkspaceName | "review" | | newContentStreamId | "user-cs-identifier" | - And the graph projection is fully up to date # now, we rebase the "review" workspace, effectively marking the "review-cs-identifier" content stream as NO_LONGER_IN_USE. # however, we are not allowed to drop the content stream from the event store yet, because the "user-cs-identifier" is based @@ -117,10 +104,8 @@ Feature: If content streams are not in use anymore by the workspace, they can be When the command RebaseWorkspace is executed with payload: | Key | Value | | workspaceName | "review" | - And the graph projection is fully up to date When I prune unused content streams - And the graph projection is fully up to date And I prune removed content streams from the event stream # the events should still exist diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/Workspaces/RemoveNodeAggregateWithDimensions.wip b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/Workspaces/RemoveNodeAggregateWithDimensions.wip index 1ee88a7acea..30f13ab7578 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/Workspaces/RemoveNodeAggregateWithDimensions.wip +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/Workspaces/RemoveNodeAggregateWithDimensions.wip @@ -18,13 +18,11 @@ Feature: Remove NodeAggregate | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "live-cs-identifier" | - And the graph projection is fully up to date And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | contentStreamId | "live-cs-identifier" | | nodeAggregateId | "lady-eleonode-nodesworth" | | nodeTypeName | "Neos.ContentRepository:Root" | - And the graph projection is fully up to date # We have to add another node since root nodes are in all dimension space points and thus cannot be varied # Node /document And the command CreateNodeAggregateWithNodeAndSerializedProperties is executed with payload: @@ -35,7 +33,6 @@ Feature: Remove NodeAggregate | originDimensionSpacePoint | {"language":"de"} | | parentNodeAggregateId | "lady-eleonode-nodesworth" | | nodeName | "document" | - And the graph projection is fully up to date # We also want to add a child node to make sure it is correctly removed when the parent is removed # Node /document/child-document And the command CreateNodeAggregateWithNodeAndSerializedProperties is executed with payload: @@ -46,14 +43,12 @@ Feature: Remove NodeAggregate | originDimensionSpacePoint | {"language":"de"} | | parentNodeAggregateId | "nody-mc-nodeface" | | nodeName | "child-document" | - And the graph projection is fully up to date And the command CreateNodeVariant is executed with payload: | Key | Value | | contentStreamId | "live-cs-identifier" | | nodeAggregateId | "nody-mc-nodeface" | | sourceOrigin | {"language":"de"} | | targetOrigin | {"language":"gsw"} | - And the graph projection is fully up to date ######################## # Section: EXTRA testcases @@ -65,7 +60,6 @@ Feature: Remove NodeAggregate | nodeAggregateId | "nody-mc-nodeface" | | nodeVariantSelectionStrategy | "allVariants" | | coveredDimensionSpacePoint | {"language":"de"} | - And the graph projection is fully up to date Then I expect the graph projection to consist of exactly 1 node And I expect a node identified by live-cs-identifier;lady-eleonode-nodesworth;{} to exist in the content graph @@ -84,7 +78,6 @@ Feature: Remove NodeAggregate | Key | Value | | contentStreamId | "user-cs-identifier" | | sourceContentStreamId | "live-cs-identifier" | - And the graph projection is fully up to date When the command RemoveNodeAggregate is executed with payload: | Key | Value | @@ -92,7 +85,6 @@ Feature: Remove NodeAggregate | nodeAggregateId | "nody-mc-nodeface" | | nodeVariantSelectionStrategy | "allVariants" | | coveredDimensionSpacePoint | {"language":"de"} | - And the graph projection is fully up to date Then I expect the graph projection to consist of exactly 4 nodes And I expect a node identified by live-cs-identifier;lady-eleonode-nodesworth;{} to exist in the content graph diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/Workspaces/RemoveNodesFromAggregate.wip b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/Workspaces/RemoveNodesFromAggregate.wip index 9d5338d22a4..3fe26bf8051 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/Workspaces/RemoveNodesFromAggregate.wip +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/Workspaces/RemoveNodesFromAggregate.wip @@ -29,7 +29,6 @@ Feature: Remove Nodes from Aggregate | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "live-cs-identifier" | - And the graph projection is fully up to date And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | contentStreamId | "live-cs-identifier" | @@ -65,7 +64,6 @@ Feature: Remove Nodes from Aggregate | originDimensionSpacePoint | {"language":"de"} | | parentNodeAggregateId | "nodimus-prime" | | nodeName | "grandchild-document" | - And the graph projection is fully up to date ######################## # Section: EXTRA testcases @@ -96,7 +94,6 @@ Feature: Remove Nodes from Aggregate | contentStreamId | "live-cs-identifier" | | nodeAggregateId | "nodasaurus-rex" | | dimensionSpacePointSet | [{"language":"de"},{"language":"gsw"}] | - And the graph projection is fully up to date Then I expect the graph projection to consist of exactly 3 nodes And I expect a node identified by live-cs-identifier;lady-eleonode-nodesworth;{} to exist in the content graph @@ -121,7 +118,6 @@ Feature: Remove Nodes from Aggregate | contentStreamId | "live-cs-identifier" | | nodeAggregateId | "nodasaurus-rex" | | dimensionSpacePointSet | [{"language":"gsw"}] | - And the graph projection is fully up to date Then I expect the graph projection to consist of exactly 4 nodes And I expect a node identified by live-cs-identifier;lady-eleonode-nodesworth;{} to exist in the content graph @@ -152,7 +148,6 @@ Feature: Remove Nodes from Aggregate | contentStreamId | "live-cs-identifier" | | nodeAggregateId | "nody-mc-nodeface" | | dimensionSpacePointSet | [{"language":"de"}] | - And the graph projection is fully up to date Then I expect the graph projection to consist of exactly 1 nodes And I expect a node identified by live-cs-identifier;lady-eleonode-nodesworth;{} to exist in the content graph @@ -172,7 +167,6 @@ Feature: Remove Nodes from Aggregate | contentStreamId | "live-cs-identifier" | | nodeAggregateId | "nody-mc-nodeface" | | dimensionSpacePointSet | [{"language":"gsw"}] | - And the graph projection is fully up to date Then I expect the graph projection to consist of exactly 4 nodes And I expect a node identified by live-cs-identifier;lady-eleonode-nodesworth;{} to exist in the content graph @@ -200,13 +194,11 @@ Feature: Remove Nodes from Aggregate | Key | Value | | contentStreamId | "user-cs-identifier" | | sourceContentStreamId | "live-cs-identifier" | - And the graph projection is fully up to date When the command RemoveNodesFromAggregate was published with payload: | Key | Value | | contentStreamId | "user-cs-identifier" | | nodeAggregateId | "nodasaurus-rex" | | dimensionSpacePointSet | [{"language":"de"}] | - And the graph projection is fully up to date Then I expect the graph projection to consist of exactly 4 nodes And I expect a node identified by live-cs-identifier;lady-eleonode-nodesworth;{} to exist in the content graph @@ -255,14 +247,12 @@ Feature: Remove Nodes from Aggregate | Key | Value | | contentStreamId | "user-cs-identifier" | | sourceContentStreamId | "live-cs-identifier" | - And the graph projection is fully up to date When the command RemoveNodesFromAggregate was published with payload: | Key | Value | | contentStreamId | "user-cs-identifier" | | nodeAggregateId | "nodimus-prime" | | dimensionSpacePointSet | [{"language":"gsw"}] | - And the graph projection is fully up to date When I am in content stream "user-cs-identifier" and dimension space point {"language":"de"} Then I expect a node "doc-identifier-de" to exist in the graph projection @@ -297,14 +287,12 @@ Feature: Remove Nodes from Aggregate | Key | Value | | contentStreamId | "user-cs-identifier" | | sourceContentStreamId | "live-cs-identifier" | - And the graph projection is fully up to date When the command RemoveNodesFromAggregate was published with payload: | Key | Value | | contentStreamId | "user-cs-identifier" | | nodeAggregateId | "nody-mc-nodeface" | | dimensionSpacePointSet | [{"language":"de"},{"language":"gsw"}] | - And the graph projection is fully up to date When I am in content stream "user-cs-identifier" and dimension space point {"language":"de"} Then I expect a node "doc-identifier-de" not to exist in the graph projection @@ -339,14 +327,12 @@ Feature: Remove Nodes from Aggregate | Key | Value | | contentStreamId | "user-cs-identifier" | | sourceContentStreamId | "live-cs-identifier" | - And the graph projection is fully up to date When the command RemoveNodesFromAggregate was published with payload: | Key | Value | | contentStreamId | "user-cs-identifier" | | nodeAggregateId | "nody-mc-nodeface" | | dimensionSpacePointSet | [{"language":"gsw"}] | - And the graph projection is fully up to date When I am in content stream "user-cs-identifier" and dimension space point {"language":"de"} Then I expect a node "doc-identifier-de" to exist in the graph projection diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/Workspaces/SingleNodeOperationsOnLiveWorkspace.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/Workspaces/SingleNodeOperationsOnLiveWorkspace.feature index 1d68654f937..ac0c815125f 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/Workspaces/SingleNodeOperationsOnLiveWorkspace.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/Workspaces/SingleNodeOperationsOnLiveWorkspace.feature @@ -18,7 +18,6 @@ Feature: Single Node operations on live workspace | Key | Value | | workspaceName | "live" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | @@ -34,7 +33,6 @@ Feature: Single Node operations on live workspace | parentNodeAggregateId | "lady-eleonode-rootford" | | nodeName | "child" | | nodeAggregateClassification | "regular" | - And the graph projection is fully up to date Scenario: Set property of a node Given the command SetNodeProperties is executed with payload: @@ -49,8 +47,6 @@ Feature: Single Node operations on live workspace | nodeAggregateId | "nody-mc-nodeface" | | originDimensionSpacePoint | [] | | propertyValues.text.value | "Hello" | - - When the graph projection is fully up to date And I am in the active content stream of workspace "live" and dimension space point {} Then I expect node aggregate identifier "nody-mc-nodeface" to lead to node cs-identifier;nody-mc-nodeface;{} And I expect this node to have the following properties: diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Functional/Feature/WorkspacePublication/WorkspaceWritingDuringPublication.php b/Neos.ContentRepository.BehavioralTests/Tests/Functional/Feature/WorkspacePublication/WorkspaceWritingDuringPublication.php index 4d532e7a805..8196cbfcd89 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Functional/Feature/WorkspacePublication/WorkspaceWritingDuringPublication.php +++ b/Neos.ContentRepository.BehavioralTests/Tests/Functional/Feature/WorkspacePublication/WorkspaceWritingDuringPublication.php @@ -43,7 +43,7 @@ use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceTitle; use Neos\ContentRepository\TestSuite\Behavior\Features\Bootstrap\CRTestSuiteTrait; use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry; -use Neos\ContentRepositoryRegistry\Factory\ProjectionCatchUpTrigger\CatchUpTriggerWithSynchronousOption; +use Neos\ContentRepositoryRegistry\Factory\ProjectionCatchUpTrigger\DefaultCatchUpTrigger; use Neos\EventStore\Exception\ConcurrencyException; use Neos\Flow\Tests\FunctionalTestCase; use PHPUnit\Framework\Assert; @@ -67,7 +67,6 @@ class WorkspaceWritingDuringPublication extends FunctionalTestCase public function setUp(): void { parent::setUp(); - CatchUpTriggerWithSynchronousOption::enableSynchronicityForSpeedingUpTesting(); GherkinTableNodeBasedContentDimensionSourceFactory::$contentDimensionsToUse = new class implements ContentDimensionSourceInterface { public function getDimension(ContentDimensionId $dimensionId): ?ContentDimension @@ -113,12 +112,12 @@ public function getContentDimensionsOrderedByPriority(): array new WorkspaceTitle('Live'), new WorkspaceDescription('The live workspace'), ContentStreamId::fromString('live-cs-id') - ))->block(); + )); $contentRepository->handle(CreateRootNodeAggregateWithNode::create( WorkspaceName::forLive(), NodeAggregateId::fromString('lady-eleonode-rootford'), NodeTypeName::fromString(NodeTypeName::ROOT_NODE_TYPE_NAME) - ))->block(); + )); $contentRepository->handle(CreateNodeAggregateWithNode::create( WorkspaceName::forLive(), NodeAggregateId::fromString('nody-mc-nodeface'), @@ -128,14 +127,14 @@ public function getContentDimensionsOrderedByPriority(): array initialPropertyValues: PropertyValuesToWrite::fromArray([ 'title' => 'title' ]) - ))->block(); + )); $contentRepository->handle(CreateWorkspace::create( WorkspaceName::fromString('user-test'), WorkspaceName::forLive(), new WorkspaceTitle('User'), new WorkspaceDescription('The user workspace'), ContentStreamId::fromString('user-cs-id') - ))->block(); + )); for ($i = 0; $i <= 1000; $i++) { $contentRepository->handle(CreateNodeAggregateWithNode::create( WorkspaceName::forLive(), @@ -146,7 +145,7 @@ public function getContentDimensionsOrderedByPriority(): array initialPropertyValues: PropertyValuesToWrite::fromArray([ 'title' => 'title' ]) - ))->block(); + )); // give the database lock some time to recover usleep(5000); } @@ -168,7 +167,7 @@ public function whileAWorkspaceIsBeingRebased(): void try { $this->contentRepository->handle(RebaseWorkspace::create( $workspaceName, - )->withRebasedContentStreamId(ContentStreamId::fromString('user-test-rebased')))->block(); + )->withRebasedContentStreamId(ContentStreamId::fromString('user-test-rebased'))); } catch (\RuntimeException $runtimeException) { $exception = $runtimeException; } @@ -196,7 +195,7 @@ public function thenConcurrentCommandsLeadToAnException(): void PropertyValuesToWrite::fromArray([ 'title' => 'title47b' ]) - ))->block(); + )); } catch (\Exception $thrownException) { $exceptionIsThrownAsExpected = $thrownException instanceof ContentStreamIsClosed || $thrownException instanceof ConcurrencyException; diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Functional/Feature/WorkspacePublication/setup-is-running-flag b/Neos.ContentRepository.BehavioralTests/Tests/Functional/Feature/WorkspacePublication/setup-is-running-flag new file mode 100644 index 00000000000..e69de29bb2d diff --git a/Neos.ContentRepository.Core/Classes/CommandHandler/CommandResult.php b/Neos.ContentRepository.Core/Classes/CommandHandler/CommandResult.php deleted file mode 100644 index a3b1ab3701f..00000000000 --- a/Neos.ContentRepository.Core/Classes/CommandHandler/CommandResult.php +++ /dev/null @@ -1,79 +0,0 @@ -pendingProjections->projections as $pendingProjection) { - $expectedSequenceNumber = $this->pendingProjections->getExpectedSequenceNumber($pendingProjection); - $this->blockProjection($pendingProjection, $expectedSequenceNumber); - } - } - - /** - * @param ProjectionInterface $projection - */ - private function blockProjection(ProjectionInterface $projection, SequenceNumber $expectedSequenceNumber): void - { - $attempts = 0; - while ($projection->getCheckpointStorage()->getHighestAppliedSequenceNumber()->value < $expectedSequenceNumber->value) { - usleep(50000); // 50000μs = 50ms - if (++$attempts > 100) { // 5 seconds - throw new \RuntimeException( - sprintf( - 'TIMEOUT while waiting for projection "%s" to catch up to sequence number %d ' . - '- check the error logs for details.', - $projection::class, - $expectedSequenceNumber->value - ), - 1550232279 - ); - } - } - } -} diff --git a/Neos.ContentRepository.Core/Classes/CommandHandler/PendingProjections.php b/Neos.ContentRepository.Core/Classes/CommandHandler/PendingProjections.php deleted file mode 100644 index 9a96085efe1..00000000000 --- a/Neos.ContentRepository.Core/Classes/CommandHandler/PendingProjections.php +++ /dev/null @@ -1,133 +0,0 @@ -> $projections - * @param array $sequenceNumberPerProjection - */ - public function __construct( - public Projections $projections, - private array $sequenceNumberPerProjection, - ) { - } - - public static function empty(): self - { - return new self(Projections::empty(), []); - } - - public static function fromProjectionsAndEventsAndSequenceNumber( - Projections $allProjections, - Events $events, - SequenceNumber $highestCommittedSequenceNumber - ): self { - $sequenceNumberInteger = $highestCommittedSequenceNumber->value - $events->count() + 1; - $pendingProjectionsArray = []; - $sequenceNumberPerProjection = []; - foreach ($events as $event) { - if ($event instanceof DecoratedEvent) { - $event = $event->innerEvent; - } - foreach ($allProjections as $projection) { - if ($projection->canHandle($event)) { - $sequenceNumberPerProjection[$projection::class] = $sequenceNumberInteger; - if (!in_array($projection, $pendingProjectionsArray, true)) { - $pendingProjectionsArray[] = $projection; - } - } - } - $sequenceNumberInteger++; - } - return new self(Projections::fromArray($pendingProjectionsArray), $sequenceNumberPerProjection); - } - - /** - * @param ProjectionInterface $projection - * @return SequenceNumber - */ - public function getExpectedSequenceNumber(ProjectionInterface $projection): SequenceNumber - { - if (!array_key_exists($projection::class, $this->sequenceNumberPerProjection)) { - throw new \InvalidArgumentException( - sprintf('Projection of class "%s" is not pending', $projection::class), - 1652252976 - ); - } - return SequenceNumber::fromInteger($this->sequenceNumberPerProjection[$projection::class]); - } -} diff --git a/Neos.ContentRepository.Core/Classes/ContentRepository.php b/Neos.ContentRepository.Core/Classes/ContentRepository.php index 180e9fd0066..18f0d132b2f 100644 --- a/Neos.ContentRepository.Core/Classes/ContentRepository.php +++ b/Neos.ContentRepository.Core/Classes/ContentRepository.php @@ -16,7 +16,6 @@ use Neos\ContentRepository\Core\CommandHandler\CommandBus; use Neos\ContentRepository\Core\CommandHandler\CommandInterface; -use Neos\ContentRepository\Core\CommandHandler\CommandResult; use Neos\ContentRepository\Core\Dimension\ContentDimensionSourceInterface; use Neos\ContentRepository\Core\DimensionSpace\InterDimensionalVariationGraph; use Neos\ContentRepository\Core\EventStore\DecoratedEvent; @@ -28,6 +27,7 @@ use Neos\ContentRepository\Core\Factory\ContentRepositoryFactory; use Neos\ContentRepository\Core\NodeType\NodeTypeManager; use Neos\ContentRepository\Core\Projection\CatchUp; +use Neos\ContentRepository\Core\Projection\CatchUpHookInterface; use Neos\ContentRepository\Core\Projection\CatchUpOptions; use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphInterface; use Neos\ContentRepository\Core\Projection\ContentStream\ContentStreamFinder; @@ -41,10 +41,14 @@ use Neos\ContentRepository\Core\SharedModel\User\UserIdProviderInterface; use Neos\EventStore\EventStoreInterface; use Neos\EventStore\Model\Event\EventMetadata; +use Neos\EventStore\Model\Event\SequenceNumber; use Neos\EventStore\Model\EventEnvelope; use Neos\EventStore\Model\EventStream\VirtualStreamName; use Psr\Clock\ClockInterface; +use function React\Async\await; +use function React\Async\parallel; + /** * Main Entry Point to the system. Encapsulates the full event-sourced Content Repository. * @@ -84,16 +88,12 @@ public function __construct( /** * The only API to send commands (mutation intentions) to the system. - * - * The system is ASYNCHRONOUS by default, so that means the projection is not directly up to date. If you - * need to be synchronous, call {@see CommandResult::block()} on the returned CommandResult - then the system - * waits until the projections are up to date. - * - * @param CommandInterface $command - * @return CommandResult + * @return object NOTE: This is just a b/c layer to avoid `handle()->block()` from failing but this will change to void with the final release! */ - public function handle(CommandInterface $command): CommandResult + public function handle(CommandInterface $command): object { + #print_r(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS));exit; + #\Neos\Flow\var_dump('HANDLE ' . $command::class); // the commands only calculate which events they want to have published, but do not do the // publishing themselves $eventsToPublish = $this->commandBus->handle($command, $this); @@ -127,7 +127,15 @@ public function handle(CommandInterface $command): CommandResult $eventsToPublish->expectedVersion, ); - return $this->eventPersister->publishEvents($eventsToPublish); + $this->eventPersister->publishEvents($eventsToPublish); + return new class { + /** + * @deprecated backwards compatibility layer + */ + public function block(): void + { + } + }; } @@ -153,6 +161,63 @@ public function projectionState(string $projectionStateClassName): ProjectionSta throw new \InvalidArgumentException(sprintf('A projection state of type "%s" is not registered in this content repository instance.', $projectionStateClassName), 1662033650); } + public function catchUpProjections(): void + { + #print_r(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS)); + $lowestAppliedSequenceNumber = null; + + /** @var array, catchUpHook: CatchUpHookInterface|null}> $projectionsAndCatchUpHooks */ + $projectionsAndCatchUpHooks = []; + foreach ($this->projectionsAndCatchUpHooks->projections as $projectionClassName => $projection) { + $projectionSequenceNumber = $projection->getCheckpointStorage()->acquireLock(); + #\Neos\Flow\var_dump('ACQUIRE LOCK FOR ' . $projectionClassName . ': ' . $projectionSequenceNumber->value); + if ($lowestAppliedSequenceNumber === null || $projectionSequenceNumber->value < $lowestAppliedSequenceNumber->value) { + $lowestAppliedSequenceNumber = $projectionSequenceNumber; + } + $catchUpHookFactory = $this->projectionsAndCatchUpHooks->getCatchUpHookFactoryForProjection($projection); + $projectionsAndCatchUpHooks[$projectionClassName] = [ + 'projection' => $projection, + 'catchUpHook' => $catchUpHookFactory?->build($this), + ]; + $projectionsAndCatchUpHooks[$projectionClassName]['catchUpHook']?->onBeforeCatchUp(); + } + #\Neos\Flow\var_dump('CATCHUP from ' . $lowestAppliedSequenceNumber->value); + assert($lowestAppliedSequenceNumber instanceof SequenceNumber); + $eventStream = $this->eventStore->load(VirtualStreamName::all())->withMinimumSequenceNumber($lowestAppliedSequenceNumber->next()); + $eventEnvelope = null; + foreach ($eventStream as $eventEnvelope) { + #\Neos\Flow\var_dump('EVENT ' . $eventEnvelope->event->type->value); + $event = $this->eventNormalizer->denormalize($eventEnvelope->event); + $futures = []; + /** @var array{projection: ProjectionInterface, catchUpHook: CatchUpHookInterface|null} $projectionAndCatchUpHook */ + foreach ($projectionsAndCatchUpHooks as $projectionClassName => $projectionAndCatchUpHook) { + #$projectionAndCatchUpHook['catchUpHook']?->onBeforeEvent($event, $eventEnvelope); + #\Neos\Flow\var_dump('APPLY ' . $eventEnvelope->event->type->value . ' (' . $eventEnvelope->sequenceNumber->value . ') TO ' . $projectionClassName); + #$futures[] = function () => $projectionAndCatchUpHook['projection']->apply($event, $eventEnvelope); + #$projectionAndCatchUpHook['catchUpHook']?->onAfterEvent($event, $eventEnvelope); + $futures[] = function () use ($projectionAndCatchUpHook, $event, $eventEnvelope) { + $projectionAndCatchUpHook['catchUpHook']?->onBeforeEvent($event, $eventEnvelope); + #\Neos\Flow\var_dump('APPLY ' . $eventEnvelope->event->type->value . ' (' . $eventEnvelope->sequenceNumber->value . ') TO ' . $projectionClassName); + $promise = $projectionAndCatchUpHook['projection']->apply($event, $eventEnvelope); + $projectionAndCatchUpHook['catchUpHook']?->onAfterEvent($event, $eventEnvelope); + return $promise; + }; + #$projectionAndCatchUpHook['projection']->getCheckpointStorage()->updateAndReleaseLock($eventEnvelope->sequenceNumber); + #\Neos\Flow\var_dump('UPDATE CHECKPOINT for ' . $projectionClassName . ' to ' . $eventEnvelope->sequenceNumber->value); + } + await(parallel($futures)); + } + assert($eventEnvelope instanceof EventEnvelope); + /** @var array{projection: ProjectionInterface, catchUpHook: CatchUpHookInterface|null} $projectionAndCatchUpHook */ + foreach ($projectionsAndCatchUpHooks as $projectionClassName => $projectionAndCatchUpHook) { + $projectionAndCatchUpHook['catchUpHook']?->onBeforeBatchCompleted(); + $projectionAndCatchUpHook['projection']->getCheckpointStorage()->updateAndReleaseLock($eventEnvelope->sequenceNumber); + #\Neos\Flow\var_dump('UPDATE SQN FOR ' . $projectionClassName . ': ' . $eventEnvelope->sequenceNumber->value); + #\Neos\Flow\var_dump('UPDATE CHECKPOINT for ' . $projectionClassName . ' to ' . $eventEnvelope->sequenceNumber->value); + $projectionAndCatchUpHook['catchUpHook']?->onAfterCatchUp(); + } + } + /** * @param class-string> $projectionClassName */ @@ -175,9 +240,6 @@ public function catchUpProjection(string $projectionClassName, CatchUpOptions $o if ($options->progressCallback !== null) { ($options->progressCallback)($event, $eventEnvelope); } - if (!$projection->canHandle($event)) { - return; - } $catchUpHook?->onBeforeEvent($event, $eventEnvelope); $projection->apply($event, $eventEnvelope); $catchUpHook?->onAfterEvent($event, $eventEnvelope); @@ -193,6 +255,7 @@ public function catchUpProjection(string $projectionClassName, CatchUpOptions $o $catchUpHook?->onAfterCatchUp(); } + public function setUp(): void { $this->eventStore->setup(); @@ -216,7 +279,7 @@ public function status(): ContentRepositoryStatus public function resetProjectionStates(): void { foreach ($this->projectionsAndCatchUpHooks->projections as $projection) { - $projection->reset(); + await($projection->reset()); } } @@ -226,7 +289,7 @@ public function resetProjectionStates(): void public function resetProjectionState(string $projectionClassName): void { $projection = $this->projectionsAndCatchUpHooks->projections->get($projectionClassName); - $projection->reset(); + await($projection->reset()); } public function getNodeTypeManager(): NodeTypeManager diff --git a/Neos.ContentRepository.Core/Classes/EventStore/EventPersister.php b/Neos.ContentRepository.Core/Classes/EventStore/EventPersister.php index 80b4aa07c94..04cc11ba712 100644 --- a/Neos.ContentRepository.Core/Classes/EventStore/EventPersister.php +++ b/Neos.ContentRepository.Core/Classes/EventStore/EventPersister.php @@ -4,8 +4,6 @@ namespace Neos\ContentRepository\Core\EventStore; -use Neos\ContentRepository\Core\CommandHandler\CommandResult; -use Neos\ContentRepository\Core\CommandHandler\PendingProjections; use Neos\ContentRepository\Core\Projection\ProjectionCatchUpTriggerInterface; use Neos\ContentRepository\Core\Projection\Projections; use Neos\ContentRepository\Core\Projection\WithMarkStaleInterface; @@ -33,42 +31,29 @@ public function __construct( /** * @param EventsToPublish $eventsToPublish - * @return CommandResult * @throws ConcurrencyException in case the expectedVersion does not match */ - public function publishEvents(EventsToPublish $eventsToPublish): CommandResult + public function publishEvents(EventsToPublish $eventsToPublish): void { if ($eventsToPublish->events->isEmpty()) { - return CommandResult::empty(); + return; } // the following logic could also be done in an AppEventStore::commit method (being called // directly from the individual Command Handlers). $normalizedEvents = Events::fromArray( $eventsToPublish->events->map(fn(EventInterface|DecoratedEvent $event) => $this->normalizeEvent($event)) ); - $commitResult = $this->eventStore->commit( + $this->eventStore->commit( $eventsToPublish->streamName, $normalizedEvents, $eventsToPublish->expectedVersion ); - // for performance reasons, we do not want to update ALL projections all the time; but instead only - // the projections which are interested in the events from above. - // Further details can be found in the docs of PendingProjections. - $pendingProjections = PendingProjections::fromProjectionsAndEventsAndSequenceNumber( - $this->projections, - $eventsToPublish->events, - $commitResult->highestCommittedSequenceNumber - ); - - foreach ($pendingProjections->projections as $projection) { + foreach ($this->projections as $projection) { if ($projection instanceof WithMarkStaleInterface) { $projection->markStale(); } } - $this->projectionCatchUpTrigger->triggerCatchUp($pendingProjections->projections); - - // The CommandResult can be used to block until projections are up to date. - return new CommandResult($pendingProjections, $commitResult); + $this->projectionCatchUpTrigger->triggerCatchUp(); } private function normalizeEvent(EventInterface|DecoratedEvent $event): Event diff --git a/Neos.ContentRepository.Core/Classes/Feature/WorkspaceCommandHandler.php b/Neos.ContentRepository.Core/Classes/Feature/WorkspaceCommandHandler.php index f03b3a20633..24e44575341 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/WorkspaceCommandHandler.php +++ b/Neos.ContentRepository.Core/Classes/Feature/WorkspaceCommandHandler.php @@ -16,7 +16,6 @@ use Neos\ContentRepository\Core\CommandHandler\CommandHandlerInterface; use Neos\ContentRepository\Core\CommandHandler\CommandInterface; -use Neos\ContentRepository\Core\CommandHandler\CommandResult; use Neos\ContentRepository\Core\ContentRepository; use Neos\ContentRepository\Core\EventStore\DecoratedEvent; use Neos\ContentRepository\Core\EventStore\EventInterface; @@ -148,7 +147,7 @@ private function handleCreateWorkspace( $command->newContentStreamId, $baseWorkspace->currentContentStreamId, ) - )->block(); + ); $events = Events::with( new WorkspaceWasCreated( @@ -213,7 +212,7 @@ private function handleCreateRootWorkspace( CreateContentStream::create( $newContentStreamId, ) - )->block(); + ); $events = Events::with( new RootWorkspaceWasCreated( @@ -250,7 +249,7 @@ private function handlePublishWorkspace( $this->publishContentStream( $workspace->currentContentStreamId, $baseWorkspace->currentContentStreamId - )?->block(); + ); // After publishing a workspace, we need to again fork from Base. $contentRepository->handle( @@ -258,7 +257,7 @@ private function handlePublishWorkspace( $command->newContentStreamId, $baseWorkspace->currentContentStreamId, ) - )->block(); + ); $streamName = WorkspaceEventStreamName::fromWorkspaceName($command->workspaceName)->getEventStreamName(); $events = Events::with( @@ -284,7 +283,7 @@ private function handlePublishWorkspace( private function publishContentStream( ContentStreamId $contentStreamId, ContentStreamId $baseContentStreamId, - ): ?CommandResult { + ): void { $baseWorkspaceContentStreamName = ContentStreamEventStreamName::fromContentStreamId( $baseContentStreamId ); @@ -329,10 +328,10 @@ private function publishContentStream( } if (count($events) === 0) { - return null; + return; } try { - return $this->eventPersister->publishEvents( + $this->eventPersister->publishEvents( new EventsToPublish( $baseWorkspaceContentStreamName->getEventStreamName(), Events::fromArray($events), @@ -370,7 +369,7 @@ private function handleRebaseWorkspace( // 0) close old content stream $contentRepository->handle( CloseContentStream::create($oldWorkspaceContentStreamId) - )->block(); + ); // 1) fork a new content stream $rebasedContentStreamId = $command->rebasedContentStreamId; @@ -379,7 +378,7 @@ private function handleRebaseWorkspace( $command->rebasedContentStreamId, $baseWorkspace->currentContentStreamId, ) - )->block(); + ); $workspaceStreamName = WorkspaceEventStreamName::fromWorkspaceName($command->workspaceName)->getEventStreamName(); $workspaceContentStreamName = ContentStreamEventStreamName::fromContentStreamId( @@ -395,7 +394,7 @@ function () use ($originalCommands, $contentRepository, &$commandsThatFailed): v foreach ($originalCommands as $sequenceNumber => $originalCommand) { // We no longer need to adjust commands as the workspace stays the same try { - $contentRepository->handle($originalCommand)->block(); + $contentRepository->handle($originalCommand); } catch (\Exception $e) { $commandsThatFailed = $commandsThatFailed->add( new CommandThatFailedDuringRebase( @@ -431,12 +430,12 @@ function () use ($originalCommands, $contentRepository, &$commandsThatFailed): v $oldWorkspaceContentStreamId, $oldWorkspaceContentStreamIdState, ) - )->block(); + ); // ... remove the newly created one... $contentRepository->handle(RemoveContentStream::create( $rebasedContentStreamId - ))->block(); + )); // ...and throw an exception that contains all the information about what exactly failed throw new WorkspaceRebaseFailed($commandsThatFailed, 'Rebase failed', 1711713880); @@ -517,7 +516,7 @@ private function handlePublishIndividualNodesFromWorkspace( $command->contentStreamIdForMatchingPart, $baseWorkspace->currentContentStreamId, ) - )->block(); + ); try { // 4) using the new content stream, apply the matching commands @@ -534,7 +533,7 @@ function () use ($matchingCommands, $contentRepository, $baseWorkspace): void { $contentRepository->handle($matchingCommand->createCopyForWorkspace( $baseWorkspace->workspaceName, - ))->block(); + )); } } ); @@ -543,7 +542,7 @@ function () use ($matchingCommands, $contentRepository, $baseWorkspace): void { $this->publishContentStream( $command->contentStreamIdForMatchingPart, $baseWorkspace->currentContentStreamId - )?->block(); + ); // 6) fork a new content stream, based on the base WS, and apply REST $contentRepository->handle( @@ -551,14 +550,14 @@ function () use ($matchingCommands, $contentRepository, $baseWorkspace): void { $command->contentStreamIdForRemainingPart, $baseWorkspace->currentContentStreamId ) - )->block(); + ); // 7) apply REMAINING commands to the workspace's new content stream ContentStreamIdOverride::applyContentStreamIdToClosure( $command->contentStreamIdForRemainingPart, function () use ($contentRepository, $remainingCommands) { foreach ($remainingCommands as $remainingCommand) { - $contentRepository->handle($remainingCommand)->block(); + $contentRepository->handle($remainingCommand); } } ); @@ -569,16 +568,16 @@ function () use ($contentRepository, $remainingCommands) { $oldWorkspaceContentStreamId, $oldWorkspaceContentStreamIdState, ) - )->block(); + ); $contentRepository->handle(RemoveContentStream::create( $command->contentStreamIdForMatchingPart - ))->block(); + )); try { $contentRepository->handle(RemoveContentStream::create( $command->contentStreamIdForRemainingPart - ))->block(); + )); } catch (ContentStreamDoesNotExistYet $contentStreamDoesNotExistYet) { // in case the exception was thrown before 6), this does not exist } @@ -637,7 +636,7 @@ private function handleDiscardIndividualNodesFromWorkspace( // 1) close old content stream $contentRepository->handle( CloseContentStream::create($oldWorkspaceContentStreamId) - )->block(); + ); // 2) filter commands, only keeping the ones NOT MATCHING the nodes from the command // (i.e. the modifications we want to keep) @@ -653,7 +652,7 @@ private function handleDiscardIndividualNodesFromWorkspace( $command->newContentStreamId, $baseWorkspace->currentContentStreamId, ) - )->block(); + ); // 4) using the new content stream, apply the commands to keep try { @@ -670,7 +669,7 @@ function () use ($commandsToKeep, $contentRepository, $baseWorkspace): void { $contentRepository->handle($matchingCommand->createCopyForWorkspace( $baseWorkspace->workspaceName, - ))->block(); + )); } } ); @@ -681,11 +680,11 @@ function () use ($commandsToKeep, $contentRepository, $baseWorkspace): void { $oldWorkspaceContentStreamId, $oldWorkspaceContentStreamIdState, ) - )->block(); + ); $contentRepository->handle(RemoveContentStream::create( $command->newContentStreamId - ))->block(); + )); throw $exception; } @@ -693,7 +692,7 @@ function () use ($commandsToKeep, $contentRepository, $baseWorkspace): void { // 5) If everything worked, to avoid dangling content streams, we need to remove the old content stream $contentRepository->handle(RemoveContentStream::create( $oldWorkspaceContentStreamId - ))->block(); + )); $streamName = WorkspaceEventStreamName::fromWorkspaceName($command->workspaceName)->getEventStreamName(); @@ -778,7 +777,7 @@ private function handleDiscardWorkspace( $newContentStream, $baseWorkspace->currentContentStreamId, ) - )->block(); + ); // if we got so far without an Exception, we can switch the Workspace's active Content stream. $streamName = WorkspaceEventStreamName::fromWorkspaceName($command->workspaceName)->getEventStreamName(); @@ -824,7 +823,7 @@ private function handleChangeBaseWorkspace( $command->newContentStreamId, $baseWorkspace->currentContentStreamId, ) - )->block(); + ); $streamName = WorkspaceEventStreamName::fromWorkspaceName($command->workspaceName)->getEventStreamName(); $events = Events::with( @@ -855,7 +854,7 @@ private function handleDeleteWorkspace( RemoveContentStream::create( $workspace->currentContentStreamId ) - )->block(); + ); $events = Events::with( new WorkspaceWasRemoved( diff --git a/Neos.ContentRepository.Core/Classes/Infrastructure/DbalCheckpointStorage.php b/Neos.ContentRepository.Core/Classes/Infrastructure/DbalCheckpointStorage.php index dac81690564..b9d124b5aef 100644 --- a/Neos.ContentRepository.Core/Classes/Infrastructure/DbalCheckpointStorage.php +++ b/Neos.ContentRepository.Core/Classes/Infrastructure/DbalCheckpointStorage.php @@ -26,9 +26,6 @@ */ final class DbalCheckpointStorage implements CheckpointStorageInterface { - private MySqlPlatform|PostgreSqlPlatform $platform; - private SequenceNumber|null $lockedSequenceNumber = null; - public function __construct( private readonly Connection $connection, private readonly string $tableName, @@ -41,7 +38,6 @@ public function __construct( if (strlen($this->subscriberId) > 255) { throw new \InvalidArgumentException('The subscriberId must not exceed 255 characters', 1705673456); } - $this->platform = $platform; } public function setUp(): void @@ -84,52 +80,12 @@ public function status(): CheckpointStorageStatus public function acquireLock(): SequenceNumber { - if ($this->connection->isTransactionActive()) { - throw new \RuntimeException(sprintf('Failed to acquire checkpoint lock for subscriber "%s" because a transaction is active already', $this->subscriberId), 1652268416); - } - $this->connection->beginTransaction(); - try { - $highestAppliedSequenceNumber = $this->connection->fetchOne('SELECT appliedsequencenumber FROM ' . $this->connection->quoteIdentifier($this->tableName) . ' WHERE subscriberid = :subscriberId ' . $this->platform->getForUpdateSQL() . ' NOWAIT', [ - 'subscriberId' => $this->subscriberId - ]); - } catch (DBALException $exception) { - $this->connection->rollBack(); - if ($exception instanceof LockWaitTimeoutException || ($exception instanceof DBALDriverException && ($exception->getErrorCode() === 3572 || $exception->getErrorCode() === 7))) { - throw new \RuntimeException(sprintf('Failed to acquire checkpoint lock for subscriber "%s" because it is acquired already', $this->subscriberId), 1652279016); - } - throw new \RuntimeException($exception->getMessage(), 1544207778, $exception); - } - if (!is_numeric($highestAppliedSequenceNumber)) { - $this->connection->rollBack(); - throw new \RuntimeException(sprintf('Failed to fetch highest applied sequence number for subscriber "%s". Please run %s::setUp()', $this->subscriberId, $this::class), 1652279139); - } - $this->lockedSequenceNumber = SequenceNumber::fromInteger((int)$highestAppliedSequenceNumber); - return $this->lockedSequenceNumber; + return $this->getHighestAppliedSequenceNumber(); } public function updateAndReleaseLock(SequenceNumber $sequenceNumber): void { - if ($this->lockedSequenceNumber === null) { - throw new \RuntimeException(sprintf('Failed to update and commit checkpoint for subscriber "%s" because the lock has not been acquired successfully before', $this->subscriberId), 1660556344); - } - if (!$this->connection->isTransactionActive()) { - throw new \RuntimeException(sprintf('Failed to update and commit checkpoint for subscriber "%s" because no transaction is active', $this->subscriberId), 1652279314); - } - if ($this->connection->isRollbackOnly()) { - // TODO as described in https://github.com/neos/neos-development-collection/issues/4970 we are in a bad state and cannot commit after a nested transaction was rolled back. - throw new \RuntimeException(sprintf('Failed to update and commit checkpoint for subscriber "%s" because the transaction has been marked for rollback only. See https://github.com/neos/neos-development-collection/issues/4970', $this->subscriberId), 1711964313); - } - try { - if (!$this->lockedSequenceNumber->equals($sequenceNumber)) { - $this->connection->update($this->tableName, ['appliedsequencenumber' => $sequenceNumber->value], ['subscriberid' => $this->subscriberId]); - } - $this->connection->commit(); - } catch (DBALException $exception) { - $this->connection->rollBack(); - throw new \RuntimeException(sprintf('Failed to update and commit highest applied sequence number for subscriber "%s". Please run %s::setUp()', $this->subscriberId, $this::class), 1652279375, $exception); - } finally { - $this->lockedSequenceNumber = null; - } + $this->connection->update($this->tableName, ['appliedsequencenumber' => $sequenceNumber->value], ['subscriberid' => $this->subscriberId]); } public function getHighestAppliedSequenceNumber(): SequenceNumber diff --git a/Neos.ContentRepository.Core/Classes/Projection/CatchUpHookInterface.php b/Neos.ContentRepository.Core/Classes/Projection/CatchUpHookInterface.php index b487fc21b72..374e1165564 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/CatchUpHookInterface.php +++ b/Neos.ContentRepository.Core/Classes/Projection/CatchUpHookInterface.php @@ -3,7 +3,6 @@ namespace Neos\ContentRepository\Core\Projection; use Neos\ContentRepository\Core\EventStore\EventInterface; -use Neos\EventStore\CatchUp\CheckpointStorageInterface; use Neos\EventStore\Model\EventEnvelope; /** diff --git a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentGraphProjection.php b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentGraphProjection.php index 018bcb8414d..2ac3923feb9 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentGraphProjection.php +++ b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentGraphProjection.php @@ -10,6 +10,7 @@ use Neos\ContentRepository\Core\Projection\ProjectionStatus; use Neos\ContentRepository\Core\Projection\WithMarkStaleInterface; use Neos\EventStore\Model\EventEnvelope; +use React\Promise\PromiseInterface; /** * @implements ProjectionInterface @@ -35,14 +36,9 @@ public function status(): ProjectionStatus return $this->projectionImplementation->status(); } - public function reset(): void + public function reset(): PromiseInterface { - $this->projectionImplementation->reset(); - } - - public function canHandle(EventInterface $event): bool - { - return $this->projectionImplementation->canHandle($event); + return $this->projectionImplementation->reset(); } public function getState(): ContentGraphInterface @@ -50,9 +46,9 @@ public function getState(): ContentGraphInterface return $this->projectionImplementation->getState(); } - public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void + public function apply(EventInterface $event, EventEnvelope $eventEnvelope): PromiseInterface { - $this->projectionImplementation->apply($event, $eventEnvelope); + return $this->projectionImplementation->apply($event, $eventEnvelope); } public function getCheckpointStorage(): CheckpointStorageInterface diff --git a/Neos.ContentRepository.Core/Classes/Projection/ContentStream/ContentStreamProjection.php b/Neos.ContentRepository.Core/Classes/Projection/ContentStream/ContentStreamProjection.php index 0878d3fe1cd..61fe00ab567 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/ContentStream/ContentStreamProjection.php +++ b/Neos.ContentRepository.Core/Classes/Projection/ContentStream/ContentStreamProjection.php @@ -50,6 +50,9 @@ use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamState; use Neos\EventStore\Model\Event\SequenceNumber; use Neos\EventStore\Model\EventEnvelope; +use React\Promise\PromiseInterface; + +use function React\Promise\resolve; /** * See {@see ContentStreamFinder} for explanation. @@ -141,39 +144,19 @@ private function determineRequiredSqlStatements(): array return DbalSchemaDiff::determineRequiredSqlStatements($connection, $schema); } - public function reset(): void + public function reset(): PromiseInterface { $this->getDatabaseConnection()->executeStatement('TRUNCATE table ' . $this->tableName); $this->checkpointStorage->acquireLock(); $this->checkpointStorage->updateAndReleaseLock(SequenceNumber::none()); + return resolve(null); } - public function canHandle(EventInterface $event): bool - { - return in_array($event::class, [ - ContentStreamWasCreated::class, - RootWorkspaceWasCreated::class, - WorkspaceWasCreated::class, - ContentStreamWasForked::class, - WorkspaceWasDiscarded::class, - WorkspaceWasPartiallyDiscarded::class, - WorkspaceWasPartiallyPublished::class, - WorkspaceWasPublished::class, - WorkspaceWasRebased::class, - WorkspaceRebaseFailed::class, - ContentStreamWasClosed::class, - ContentStreamWasReopened::class, - ContentStreamWasRemoved::class, - DimensionShineThroughWasAdded::class, - ]) - || $event instanceof EmbedsContentStreamAndNodeAggregateId; - } - - public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void + public function apply(EventInterface $event, EventEnvelope $eventEnvelope): PromiseInterface { if ($event instanceof EmbedsContentStreamAndNodeAggregateId) { $this->updateContentStreamVersion($event, $eventEnvelope); - return; + return resolve(null); } match ($event::class) { ContentStreamWasCreated::class => $this->whenContentStreamWasCreated($event, $eventEnvelope), @@ -190,8 +173,9 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void ContentStreamWasReopened::class => $this->whenContentStreamWasReopened($event, $eventEnvelope), ContentStreamWasRemoved::class => $this->whenContentStreamWasRemoved($event, $eventEnvelope), DimensionShineThroughWasAdded::class => $this->whenDimensionShineThroughWasAdded($event, $eventEnvelope), - default => throw new \InvalidArgumentException(sprintf('Unsupported event %s', get_debug_type($event))), + default => null, }; + return resolve(null); } public function getCheckpointStorage(): CheckpointStorageInterface diff --git a/Neos.ContentRepository.Core/Classes/Projection/ProjectionCatchUpTriggerInterface.php b/Neos.ContentRepository.Core/Classes/Projection/ProjectionCatchUpTriggerInterface.php index 1fb20d34cbe..d4b7331533e 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/ProjectionCatchUpTriggerInterface.php +++ b/Neos.ContentRepository.Core/Classes/Projection/ProjectionCatchUpTriggerInterface.php @@ -10,11 +10,9 @@ * Interface for a class that (asynchronously) triggers a catchup of affected projections after a * {@see ContentRepository::handle()} call. * - * Usually, this (asynchronously) triggers {@see ProjectionInterface::catchUp()} via a subprocess or an event queue. - * * @api */ interface ProjectionCatchUpTriggerInterface { - public function triggerCatchUp(Projections $projections): void; + public function triggerCatchUp(): void; } diff --git a/Neos.ContentRepository.Core/Classes/Projection/ProjectionInterface.php b/Neos.ContentRepository.Core/Classes/Projection/ProjectionInterface.php index 22c65ced9f7..f2c3f1a592f 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/ProjectionInterface.php +++ b/Neos.ContentRepository.Core/Classes/Projection/ProjectionInterface.php @@ -7,6 +7,7 @@ use Neos\ContentRepository\Core\ContentRepository; use Neos\ContentRepository\Core\EventStore\EventInterface; use Neos\EventStore\Model\EventEnvelope; +use React\Promise\PromiseInterface; /** * Common interface for a Content Repository projection. This API is NOT exposed to the outside world, but is @@ -30,9 +31,10 @@ public function setUp(): void; */ public function status(): ProjectionStatus; - public function canHandle(EventInterface $event): bool; - - public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void; + /** + * @return PromiseInterface + */ + public function apply(EventInterface $event, EventEnvelope $eventEnvelope): PromiseInterface; public function getCheckpointStorage(): CheckpointStorageInterface; @@ -46,5 +48,8 @@ public function getCheckpointStorage(): CheckpointStorageInterface; */ public function getState(): ProjectionStateInterface; - public function reset(): void; + /** + * @return PromiseInterface + */ + public function reset(): PromiseInterface; } diff --git a/Neos.ContentRepository.Core/Classes/Projection/Workspace/WorkspaceProjection.php b/Neos.ContentRepository.Core/Classes/Projection/Workspace/WorkspaceProjection.php index ac526c6576f..7ef1c864a36 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/Workspace/WorkspaceProjection.php +++ b/Neos.ContentRepository.Core/Classes/Projection/Workspace/WorkspaceProjection.php @@ -45,6 +45,9 @@ use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName; use Neos\EventStore\Model\Event\SequenceNumber; use Neos\EventStore\Model\EventEnvelope; +use React\Promise\PromiseInterface; + +use function React\Promise\resolve; /** * @internal @@ -133,32 +136,15 @@ private function determineRequiredSqlStatements(): array return DbalSchemaDiff::determineRequiredSqlStatements($connection, $schema); } - public function reset(): void + public function reset(): PromiseInterface { $this->getDatabaseConnection()->exec('TRUNCATE ' . $this->tableName); $this->checkpointStorage->acquireLock(); $this->checkpointStorage->updateAndReleaseLock(SequenceNumber::none()); + return resolve(null); } - public function canHandle(EventInterface $event): bool - { - return in_array($event::class, [ - WorkspaceWasCreated::class, - WorkspaceWasRenamed::class, - RootWorkspaceWasCreated::class, - WorkspaceWasDiscarded::class, - WorkspaceWasPartiallyDiscarded::class, - WorkspaceWasPartiallyPublished::class, - WorkspaceWasPublished::class, - WorkspaceWasRebased::class, - WorkspaceRebaseFailed::class, - WorkspaceWasRemoved::class, - WorkspaceOwnerWasChanged::class, - WorkspaceBaseWorkspaceWasChanged::class, - ]); - } - - public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void + public function apply(EventInterface $event, EventEnvelope $eventEnvelope): PromiseInterface { match ($event::class) { WorkspaceWasCreated::class => $this->whenWorkspaceWasCreated($event), @@ -173,8 +159,9 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void WorkspaceWasRemoved::class => $this->whenWorkspaceWasRemoved($event), WorkspaceOwnerWasChanged::class => $this->whenWorkspaceOwnerWasChanged($event), WorkspaceBaseWorkspaceWasChanged::class => $this->whenWorkspaceBaseWorkspaceWasChanged($event), - default => throw new \InvalidArgumentException(sprintf('Unsupported event %s', get_debug_type($event))), + default => null, }; + return resolve(null); } public function getCheckpointStorage(): DbalCheckpointStorage diff --git a/Neos.ContentRepository.Core/Classes/Service/ContentRepositoryBootstrapper.php b/Neos.ContentRepository.Core/Classes/Service/ContentRepositoryBootstrapper.php index 0b65f505f1c..01e5219a5bd 100644 --- a/Neos.ContentRepository.Core/Classes/Service/ContentRepositoryBootstrapper.php +++ b/Neos.ContentRepository.Core/Classes/Service/ContentRepositoryBootstrapper.php @@ -52,7 +52,7 @@ public function getOrCreateLiveWorkspace(): Workspace WorkspaceDescription::fromString('Public live workspace'), ContentStreamId::create() ) - )->block(); + ); $liveWorkspace = $this->contentRepository->getWorkspaceFinder()->findOneByName($liveWorkspaceName); if (!$liveWorkspace) { throw new \Exception('Live workspace creation failed', 1699002435); @@ -83,7 +83,7 @@ public function getOrCreateRootNodeAggregate( $workspace->workspaceName, $rootNodeAggregateId, $rootNodeTypeName, - ))->block(); + )); return $rootNodeAggregateId; } } diff --git a/Neos.ContentRepository.Core/Classes/Service/ContentStreamPruner.php b/Neos.ContentRepository.Core/Classes/Service/ContentStreamPruner.php index eb5f5540917..ac6c6653c93 100644 --- a/Neos.ContentRepository.Core/Classes/Service/ContentStreamPruner.php +++ b/Neos.ContentRepository.Core/Classes/Service/ContentStreamPruner.php @@ -4,7 +4,6 @@ namespace Neos\ContentRepository\Core\Service; -use Neos\ContentRepository\Core\CommandHandler\CommandResult; use Neos\ContentRepository\Core\ContentRepository; use Neos\ContentRepository\Core\Factory\ContentRepositoryServiceInterface; use Neos\ContentRepository\Core\Feature\ContentStreamEventStreamName; @@ -20,8 +19,6 @@ */ class ContentStreamPruner implements ContentRepositoryServiceInterface { - private ?CommandResult $lastCommandResult; - public function __construct( private readonly ContentRepository $contentRepository, private readonly EventStoreInterface $eventStore, @@ -51,7 +48,7 @@ public function prune(bool $removeTemporary = false): iterable ); foreach ($unusedContentStreams as $contentStream) { - $this->lastCommandResult = $this->contentRepository->handle( + $this->contentRepository->handle( RemoveContentStream::create($contentStream) ); } @@ -93,9 +90,4 @@ public function pruneAll(): void $this->eventStore->deleteStream($streamName); } } - - public function getLastCommandResult(): ?CommandResult - { - return $this->lastCommandResult; - } } diff --git a/Neos.ContentRepository.Core/Classes/Service/WorkspaceMaintenanceService.php b/Neos.ContentRepository.Core/Classes/Service/WorkspaceMaintenanceService.php index dd3f10a1464..053d0dc3565 100644 --- a/Neos.ContentRepository.Core/Classes/Service/WorkspaceMaintenanceService.php +++ b/Neos.ContentRepository.Core/Classes/Service/WorkspaceMaintenanceService.php @@ -41,7 +41,7 @@ public function rebaseOutdatedWorkspaces(?RebaseErrorHandlingStrategy $strategy if ($strategy) { $rebaseCommand = $rebaseCommand->withErrorHandlingStrategy($strategy); } - $this->contentRepository->handle($rebaseCommand)->block(); + $this->contentRepository->handle($rebaseCommand); } return $outdatedWorkspaces; diff --git a/Neos.ContentRepository.Core/composer.json b/Neos.ContentRepository.Core/composer.json index 56bdba56ad6..1c7f92c949a 100644 --- a/Neos.ContentRepository.Core/composer.json +++ b/Neos.ContentRepository.Core/composer.json @@ -21,7 +21,9 @@ "symfony/serializer": "^6.3", "psr/clock": "^1", "behat/transliterator": "~1.0", - "ramsey/uuid": "^3.0 || ^4.0" + "ramsey/uuid": "^3.0 || ^4.0", + "react/promise": "^3.1", + "react/async": "^v4.2" }, "require-dev": { "roave/security-advisories": "dev-latest", diff --git a/Neos.ContentRepository.Export/Tests/Behavior/Features/Bootstrap/FeatureContext.php b/Neos.ContentRepository.Export/Tests/Behavior/Features/Bootstrap/FeatureContext.php index bc5ea2a6d7d..01310c7beff 100644 --- a/Neos.ContentRepository.Export/Tests/Behavior/Features/Bootstrap/FeatureContext.php +++ b/Neos.ContentRepository.Export/Tests/Behavior/Features/Bootstrap/FeatureContext.php @@ -44,7 +44,6 @@ public function __construct() self::bootstrapFlow(); $this->contentRepositoryRegistry = $this->getObject(ContentRepositoryRegistry::class); - $this->setupCRTestSuiteTrait(); $this->setupCrImportExportTrait(); } diff --git a/Neos.ContentRepository.Export/Tests/Behavior/Features/Export/Export.feature b/Neos.ContentRepository.Export/Tests/Behavior/Features/Export/Export.feature index 4ec48a59b49..d2580ce81c2 100644 --- a/Neos.ContentRepository.Export/Tests/Behavior/Features/Export/Export.feature +++ b/Neos.ContentRepository.Export/Tests/Behavior/Features/Export/Export.feature @@ -17,7 +17,6 @@ Feature: As a user of the CR I want to export the event stream | workspaceTitle | "Live" | | workspaceDescription | "The live workspace" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in workspace "live" And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | @@ -33,7 +32,6 @@ Feature: As a user of the CR I want to export the event stream | parentNodeAggregateId | "lady-eleonode-rootford" | | nodeName | "child-document" | | nodeAggregateClassification | "regular" | - And the graph projection is fully up to date Scenario: Export the event stream Then I expect exactly 3 events to be published on stream with prefix "ContentStream:cs-identifier" diff --git a/Neos.ContentRepository.LegacyNodeMigration/Tests/Behavior/Bootstrap/FeatureContext.php b/Neos.ContentRepository.LegacyNodeMigration/Tests/Behavior/Bootstrap/FeatureContext.php index ff9511a1011..75b7a41d9c0 100644 --- a/Neos.ContentRepository.LegacyNodeMigration/Tests/Behavior/Bootstrap/FeatureContext.php +++ b/Neos.ContentRepository.LegacyNodeMigration/Tests/Behavior/Bootstrap/FeatureContext.php @@ -78,7 +78,6 @@ public function __construct() $this->mockFilesystemAdapter = new InMemoryFilesystemAdapter(); $this->mockFilesystem = new Filesystem($this->mockFilesystemAdapter); - $this->setupCRTestSuiteTrait(); } /** diff --git a/Neos.ContentRepository.NodeMigration/src/NodeMigrationService.php b/Neos.ContentRepository.NodeMigration/src/NodeMigrationService.php index 8bd7c065860..26c4e5b889f 100644 --- a/Neos.ContentRepository.NodeMigration/src/NodeMigrationService.php +++ b/Neos.ContentRepository.NodeMigration/src/NodeMigrationService.php @@ -78,7 +78,7 @@ public function executeMigration(ExecuteMigration $command): void WorkspaceDescription::fromString(''), $contentStreamForWriting, ) - )->block(); + ); /** array $migrationDescription */ $this->executeSubMigrationAndBlock( $migrationDescription, diff --git a/Neos.ContentRepository.NodeMigration/src/Transformation/AddDimensionShineThroughTransformationFactory.php b/Neos.ContentRepository.NodeMigration/src/Transformation/AddDimensionShineThroughTransformationFactory.php index 824dcae90a4..f8decab4901 100644 --- a/Neos.ContentRepository.NodeMigration/src/Transformation/AddDimensionShineThroughTransformationFactory.php +++ b/Neos.ContentRepository.NodeMigration/src/Transformation/AddDimensionShineThroughTransformationFactory.php @@ -14,7 +14,6 @@ namespace Neos\ContentRepository\NodeMigration\Transformation; -use Neos\ContentRepository\Core\CommandHandler\CommandResult; use Neos\ContentRepository\Core\ContentRepository; use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePoint; use Neos\ContentRepository\Core\Feature\DimensionSpaceAdjustment\Command\AddDimensionShineThrough; @@ -50,8 +49,8 @@ public function __construct( public function execute( WorkspaceName $workspaceNameForWriting, - ): CommandResult { - return $this->contentRepository->handle( + ): void { + $this->contentRepository->handle( AddDimensionShineThrough::create( $workspaceNameForWriting, $this->from, diff --git a/Neos.ContentRepository.NodeMigration/src/Transformation/AddNewPropertyTransformationFactory.php b/Neos.ContentRepository.NodeMigration/src/Transformation/AddNewPropertyTransformationFactory.php index 74bc503c913..cf05f8b4549 100644 --- a/Neos.ContentRepository.NodeMigration/src/Transformation/AddNewPropertyTransformationFactory.php +++ b/Neos.ContentRepository.NodeMigration/src/Transformation/AddNewPropertyTransformationFactory.php @@ -14,7 +14,6 @@ namespace Neos\ContentRepository\NodeMigration\Transformation; -use Neos\ContentRepository\Core\CommandHandler\CommandResult; use Neos\ContentRepository\Core\ContentRepository; use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePointSet; use Neos\ContentRepository\Core\Feature\NodeModification\Command\SetSerializedNodeProperties; @@ -59,14 +58,14 @@ public function execute( DimensionSpacePointSet $coveredDimensionSpacePoints, WorkspaceName $workspaceNameForWriting, ContentStreamId $contentStreamForWriting - ): ?CommandResult { + ): void { if ($this->serializedValue === null) { // we don't need to unset a non-existing property - return null; + return; } if (!$node->hasProperty($this->newPropertyName)) { - return $this->contentRepository->handle( + $this->contentRepository->handle( SetSerializedNodeProperties::create( $workspaceNameForWriting, $node->nodeAggregateId, @@ -81,8 +80,6 @@ public function execute( ) ); } - - return null; } }; } diff --git a/Neos.ContentRepository.NodeMigration/src/Transformation/ChangeNodeTypeTransformationFactory.php b/Neos.ContentRepository.NodeMigration/src/Transformation/ChangeNodeTypeTransformationFactory.php index 2c584214551..42ec7df2b4c 100644 --- a/Neos.ContentRepository.NodeMigration/src/Transformation/ChangeNodeTypeTransformationFactory.php +++ b/Neos.ContentRepository.NodeMigration/src/Transformation/ChangeNodeTypeTransformationFactory.php @@ -14,7 +14,6 @@ namespace Neos\ContentRepository\NodeMigration\Transformation; -use Neos\ContentRepository\Core\CommandHandler\CommandResult; use Neos\ContentRepository\Core\ContentRepository; use Neos\ContentRepository\Core\Feature\NodeTypeChange\Command\ChangeNodeAggregateType; use Neos\ContentRepository\Core\Feature\NodeTypeChange\Dto\NodeAggregateTypeChangeChildConstraintConflictResolutionStrategy; @@ -65,8 +64,8 @@ public function execute( NodeAggregate $nodeAggregate, WorkspaceName $workspaceNameForWriting, ContentStreamId $contentStreamForWriting - ): CommandResult { - return $this->contentRepository->handle(ChangeNodeAggregateType::create( + ): void { + $this->contentRepository->handle(ChangeNodeAggregateType::create( $workspaceNameForWriting, $nodeAggregate->nodeAggregateId, NodeTypeName::fromString($this->newType), diff --git a/Neos.ContentRepository.NodeMigration/src/Transformation/ChangePropertyValueTransformationFactory.php b/Neos.ContentRepository.NodeMigration/src/Transformation/ChangePropertyValueTransformationFactory.php index 6ed394e9a68..8b107f64777 100644 --- a/Neos.ContentRepository.NodeMigration/src/Transformation/ChangePropertyValueTransformationFactory.php +++ b/Neos.ContentRepository.NodeMigration/src/Transformation/ChangePropertyValueTransformationFactory.php @@ -14,7 +14,6 @@ namespace Neos\ContentRepository\NodeMigration\Transformation; -use Neos\ContentRepository\Core\CommandHandler\CommandResult; use Neos\ContentRepository\Core\ContentRepository; use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePointSet; use Neos\ContentRepository\Core\Feature\NodeModification\Command\SetSerializedNodeProperties; @@ -106,7 +105,7 @@ public function execute( DimensionSpacePointSet $coveredDimensionSpacePoints, WorkspaceName $workspaceNameForWriting, ContentStreamId $contentStreamForWriting - ): ?CommandResult { + ): void { $currentProperty = $node->properties->serialized()->getProperty($this->propertyName); if ($currentProperty !== null) { $value = $currentProperty->value; @@ -128,7 +127,7 @@ public function execute( $newValueWithReplacedCurrentValue ); - return $this->contentRepository->handle( + $this->contentRepository->handle( SetSerializedNodeProperties::create( $workspaceNameForWriting, $node->nodeAggregateId, @@ -143,8 +142,6 @@ public function execute( ) ); } - - return null; } }; } diff --git a/Neos.ContentRepository.NodeMigration/src/Transformation/GlobalTransformationInterface.php b/Neos.ContentRepository.NodeMigration/src/Transformation/GlobalTransformationInterface.php index a8017546f84..7fed0930401 100644 --- a/Neos.ContentRepository.NodeMigration/src/Transformation/GlobalTransformationInterface.php +++ b/Neos.ContentRepository.NodeMigration/src/Transformation/GlobalTransformationInterface.php @@ -14,8 +14,6 @@ namespace Neos\ContentRepository\NodeMigration\Transformation; -use Neos\ContentRepository\Core\CommandHandler\CommandResult; -use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName; /** @@ -27,5 +25,5 @@ interface GlobalTransformationInterface { public function execute( WorkspaceName $workspaceNameForWriting, - ): CommandResult; + ): void; } diff --git a/Neos.ContentRepository.NodeMigration/src/Transformation/MoveDimensionSpacePointTransformationFactory.php b/Neos.ContentRepository.NodeMigration/src/Transformation/MoveDimensionSpacePointTransformationFactory.php index eeda40a3ea5..0b7cc1b7679 100644 --- a/Neos.ContentRepository.NodeMigration/src/Transformation/MoveDimensionSpacePointTransformationFactory.php +++ b/Neos.ContentRepository.NodeMigration/src/Transformation/MoveDimensionSpacePointTransformationFactory.php @@ -14,7 +14,6 @@ namespace Neos\ContentRepository\NodeMigration\Transformation; -use Neos\ContentRepository\Core\CommandHandler\CommandResult; use Neos\ContentRepository\Core\ContentRepository; use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePoint; use Neos\ContentRepository\Core\Feature\DimensionSpaceAdjustment\Command\MoveDimensionSpacePoint; @@ -48,8 +47,8 @@ public function __construct( public function execute( WorkspaceName $workspaceNameForWriting, - ): CommandResult { - return $this->contentRepository->handle( + ): void { + $this->contentRepository->handle( MoveDimensionSpacePoint::create( $workspaceNameForWriting, $this->from, diff --git a/Neos.ContentRepository.NodeMigration/src/Transformation/NodeAggregateBasedTransformationInterface.php b/Neos.ContentRepository.NodeMigration/src/Transformation/NodeAggregateBasedTransformationInterface.php index e5421f8114a..8b2ebd2787c 100644 --- a/Neos.ContentRepository.NodeMigration/src/Transformation/NodeAggregateBasedTransformationInterface.php +++ b/Neos.ContentRepository.NodeMigration/src/Transformation/NodeAggregateBasedTransformationInterface.php @@ -14,7 +14,6 @@ namespace Neos\ContentRepository\NodeMigration\Transformation; -use Neos\ContentRepository\Core\CommandHandler\CommandResult; use Neos\ContentRepository\Core\Projection\ContentGraph\NodeAggregate; use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName; @@ -30,5 +29,5 @@ public function execute( NodeAggregate $nodeAggregate, WorkspaceName $workspaceNameForWriting, ContentStreamId $contentStreamForWriting - ): CommandResult; + ): void; } diff --git a/Neos.ContentRepository.NodeMigration/src/Transformation/NodeBasedTransformationInterface.php b/Neos.ContentRepository.NodeMigration/src/Transformation/NodeBasedTransformationInterface.php index 88a1573f674..1b2ab86ae4f 100644 --- a/Neos.ContentRepository.NodeMigration/src/Transformation/NodeBasedTransformationInterface.php +++ b/Neos.ContentRepository.NodeMigration/src/Transformation/NodeBasedTransformationInterface.php @@ -14,7 +14,6 @@ namespace Neos\ContentRepository\NodeMigration\Transformation; -use Neos\ContentRepository\Core\CommandHandler\CommandResult; use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePointSet; use Neos\ContentRepository\Core\Projection\ContentGraph\Node; use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; @@ -32,5 +31,5 @@ public function execute( DimensionSpacePointSet $coveredDimensionSpacePoints, WorkspaceName $workspaceNameForWriting, ContentStreamId $contentStreamForWriting - ): ?CommandResult; + ): void; } diff --git a/Neos.ContentRepository.NodeMigration/src/Transformation/RemoveNodeTransformationFactory.php b/Neos.ContentRepository.NodeMigration/src/Transformation/RemoveNodeTransformationFactory.php index 2db6a3a046e..8e1b7f95ba4 100644 --- a/Neos.ContentRepository.NodeMigration/src/Transformation/RemoveNodeTransformationFactory.php +++ b/Neos.ContentRepository.NodeMigration/src/Transformation/RemoveNodeTransformationFactory.php @@ -14,7 +14,6 @@ namespace Neos\ContentRepository\NodeMigration\Transformation; -use Neos\ContentRepository\Core\CommandHandler\CommandResult; use Neos\ContentRepository\Core\ContentRepository; use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePoint; use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePointSet; @@ -66,7 +65,7 @@ public function execute( DimensionSpacePointSet $coveredDimensionSpacePoints, WorkspaceName $workspaceNameForWriting, ContentStreamId $contentStreamForWriting - ): ?CommandResult { + ): void { if ($this->strategy === null) { $this->strategy = NodeVariantSelectionStrategy::STRATEGY_ALL_SPECIALIZATIONS; } @@ -84,10 +83,10 @@ public function execute( if (!$coveredDimensionSpacePoints->contains($coveredDimensionSpacePoint)) { // we are currently in a Node which has other covered dimension space points than the target ones, // so we do not need to do anything. - return null; + return; } - return $this->contentRepository->handle(RemoveNodeAggregate::create( + $this->contentRepository->handle(RemoveNodeAggregate::create( $workspaceNameForWriting, $node->nodeAggregateId, $coveredDimensionSpacePoint, diff --git a/Neos.ContentRepository.NodeMigration/src/Transformation/RemovePropertyTransformationFactory.php b/Neos.ContentRepository.NodeMigration/src/Transformation/RemovePropertyTransformationFactory.php index e47bfcfefec..1e6cab56985 100644 --- a/Neos.ContentRepository.NodeMigration/src/Transformation/RemovePropertyTransformationFactory.php +++ b/Neos.ContentRepository.NodeMigration/src/Transformation/RemovePropertyTransformationFactory.php @@ -14,7 +14,6 @@ namespace Neos\ContentRepository\NodeMigration\Transformation; -use Neos\ContentRepository\Core\CommandHandler\CommandResult; use Neos\ContentRepository\Core\ContentRepository; use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePointSet; use Neos\ContentRepository\Core\Feature\NodeModification\Command\SetSerializedNodeProperties; @@ -54,9 +53,9 @@ public function execute( DimensionSpacePointSet $coveredDimensionSpacePoints, WorkspaceName $workspaceNameForWriting, ContentStreamId $contentStreamForWriting - ): ?CommandResult { + ): void { if ($node->hasProperty($this->propertyName)) { - return $this->contentRepository->handle( + $this->contentRepository->handle( SetSerializedNodeProperties::create( $workspaceNameForWriting, $node->nodeAggregateId, @@ -66,8 +65,6 @@ public function execute( ) ); } - - return null; } }; } diff --git a/Neos.ContentRepository.NodeMigration/src/Transformation/RenameNodeAggregateTransformationFactory.php b/Neos.ContentRepository.NodeMigration/src/Transformation/RenameNodeAggregateTransformationFactory.php index 207a34b3869..3e05d002d1b 100644 --- a/Neos.ContentRepository.NodeMigration/src/Transformation/RenameNodeAggregateTransformationFactory.php +++ b/Neos.ContentRepository.NodeMigration/src/Transformation/RenameNodeAggregateTransformationFactory.php @@ -14,7 +14,6 @@ namespace Neos\ContentRepository\NodeMigration\Transformation; -use Neos\ContentRepository\Core\CommandHandler\CommandResult; use Neos\ContentRepository\Core\ContentRepository; use Neos\ContentRepository\Core\Feature\NodeRenaming\Command\ChangeNodeAggregateName; use Neos\ContentRepository\Core\Projection\ContentGraph\NodeAggregate; @@ -50,8 +49,8 @@ public function execute( NodeAggregate $nodeAggregate, WorkspaceName $workspaceNameForWriting, ContentStreamId $contentStreamForWriting - ): CommandResult { - return $this->contentRepository->handle(ChangeNodeAggregateName::create( + ): void { + $this->contentRepository->handle(ChangeNodeAggregateName::create( $workspaceNameForWriting, $nodeAggregate->nodeAggregateId, NodeName::fromString($this->newNodeName), diff --git a/Neos.ContentRepository.NodeMigration/src/Transformation/RenamePropertyTransformationFactory.php b/Neos.ContentRepository.NodeMigration/src/Transformation/RenamePropertyTransformationFactory.php index b9fe78e8f50..c1968308760 100644 --- a/Neos.ContentRepository.NodeMigration/src/Transformation/RenamePropertyTransformationFactory.php +++ b/Neos.ContentRepository.NodeMigration/src/Transformation/RenamePropertyTransformationFactory.php @@ -14,7 +14,6 @@ namespace Neos\ContentRepository\NodeMigration\Transformation; -use Neos\ContentRepository\Core\CommandHandler\CommandResult; use Neos\ContentRepository\Core\ContentRepository; use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePointSet; use Neos\ContentRepository\Core\Feature\NodeModification\Command\SetSerializedNodeProperties; @@ -61,11 +60,11 @@ public function execute( DimensionSpacePointSet $coveredDimensionSpacePoints, WorkspaceName $workspaceNameForWriting, ContentStreamId $contentStreamForWriting - ): ?CommandResult + ): void { $serializedPropertyValue = $node->properties->serialized()->getProperty($this->from); if ($serializedPropertyValue !== null) { - return $this->contentRepository->handle( + $this->contentRepository->handle( SetSerializedNodeProperties::create( $workspaceNameForWriting, $node->nodeAggregateId, @@ -77,8 +76,6 @@ public function execute( ) ); } - - return null; } }; } diff --git a/Neos.ContentRepository.NodeMigration/src/Transformation/StripTagsOnPropertyTransformationFactory.php b/Neos.ContentRepository.NodeMigration/src/Transformation/StripTagsOnPropertyTransformationFactory.php index ff9b5113af8..81d22fc5896 100644 --- a/Neos.ContentRepository.NodeMigration/src/Transformation/StripTagsOnPropertyTransformationFactory.php +++ b/Neos.ContentRepository.NodeMigration/src/Transformation/StripTagsOnPropertyTransformationFactory.php @@ -14,7 +14,6 @@ namespace Neos\ContentRepository\NodeMigration\Transformation; -use Neos\ContentRepository\Core\CommandHandler\CommandResult; use Neos\ContentRepository\Core\ContentRepository; use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePointSet; use Neos\ContentRepository\Core\Feature\NodeModification\Command\SetSerializedNodeProperties; @@ -55,7 +54,7 @@ public function execute( DimensionSpacePointSet $coveredDimensionSpacePoints, WorkspaceName $workspaceNameForWriting, ContentStreamId $contentStreamForWriting - ): ?CommandResult { + ): void { $serializedPropertyValue = $node->properties->serialized()->getProperty($this->propertyName); if ($serializedPropertyValue !== null) { $propertyValue = $serializedPropertyValue->value; @@ -66,7 +65,7 @@ public function execute( ); } $newValue = strip_tags($propertyValue); - return $this->contentRepository->handle( + $this->contentRepository->handle( SetSerializedNodeProperties::create( $workspaceNameForWriting, $node->nodeAggregateId, @@ -81,8 +80,6 @@ public function execute( ) ); } - - return null; } }; } diff --git a/Neos.ContentRepository.NodeMigration/src/Transformation/Transformations.php b/Neos.ContentRepository.NodeMigration/src/Transformation/Transformations.php index cbc86408335..cd95b41e224 100644 --- a/Neos.ContentRepository.NodeMigration/src/Transformation/Transformations.php +++ b/Neos.ContentRepository.NodeMigration/src/Transformation/Transformations.php @@ -94,7 +94,7 @@ public function executeGlobalAndBlock( WorkspaceName $workspaceNameForWriting, ): void { foreach ($this->globalTransformations as $globalTransformation) { - $globalTransformation->execute($workspaceNameForWriting)->block(); + $globalTransformation->execute($workspaceNameForWriting); } } @@ -104,7 +104,7 @@ public function executeNodeAggregateBasedAndBlock( ContentStreamId $contentStreamForWriting ): void { foreach ($this->nodeAggregateBasedTransformations as $nodeAggregateBasedTransformation) { - $nodeAggregateBasedTransformation->execute($nodeAggregate, $workspaceNameForWriting, $contentStreamForWriting)->block(); + $nodeAggregateBasedTransformation->execute($nodeAggregate, $workspaceNameForWriting, $contentStreamForWriting); } } @@ -115,7 +115,7 @@ public function executeNodeBasedAndBlock( ContentStreamId $contentStreamForWriting ): void { foreach ($this->nodeBasedTransformations as $nodeBasedTransformation) { - $nodeBasedTransformation->execute($node, $coveredDimensionSpacePoints, $workspaceNameForWriting, $contentStreamForWriting)?->block(); + $nodeBasedTransformation->execute($node, $coveredDimensionSpacePoints, $workspaceNameForWriting, $contentStreamForWriting); } } } diff --git a/Neos.ContentRepository.StructureAdjustment/src/StructureAdjustmentService.php b/Neos.ContentRepository.StructureAdjustment/src/StructureAdjustmentService.php index 3f50d52afe7..811d8dd0f25 100644 --- a/Neos.ContentRepository.StructureAdjustment/src/StructureAdjustmentService.php +++ b/Neos.ContentRepository.StructureAdjustment/src/StructureAdjustmentService.php @@ -97,7 +97,7 @@ public function fixError(StructureAdjustment $adjustment): void $remediation = $adjustment->remediation; $eventsToPublish = $remediation(); assert($eventsToPublish instanceof EventsToPublish); - $this->eventPersister->publishEvents($eventsToPublish)->block(); + $this->eventPersister->publishEvents($eventsToPublish); } } } diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteRuntimeVariables.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteRuntimeVariables.php index a19eb219002..2be41899d8d 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteRuntimeVariables.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteRuntimeVariables.php @@ -14,7 +14,6 @@ namespace Neos\ContentRepository\TestSuite\Behavior\Features\Bootstrap; -use Neos\ContentRepository\Core\CommandHandler\CommandResult; use Neos\ContentRepository\Core\ContentRepository; use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePoint; use Neos\ContentRepository\Core\Projection\ContentGraph\ContentSubgraphInterface; @@ -47,8 +46,6 @@ trait CRTestSuiteRuntimeVariables protected ?NodeAggregateId $currentRootNodeAggregateId = null; - protected ?CommandResult $lastCommandOrEventResult = null; - protected ?\Exception $lastCommandException = null; protected ?Node $currentNode = null; diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteTrait.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteTrait.php index 832cfcef5fa..f2c0210cf4d 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteTrait.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteTrait.php @@ -49,7 +49,7 @@ use Neos\ContentRepository\TestSuite\Behavior\Features\Bootstrap\Features\WorkspaceCreation; use Neos\ContentRepository\TestSuite\Behavior\Features\Bootstrap\Features\WorkspaceDiscarding; use Neos\ContentRepository\TestSuite\Behavior\Features\Bootstrap\Features\WorkspacePublishing; -use Neos\ContentRepositoryRegistry\Factory\ProjectionCatchUpTrigger\CatchUpTriggerWithSynchronousOption; +use Neos\ContentRepositoryRegistry\Factory\ProjectionCatchUpTrigger\DefaultCatchUpTrigger; use Neos\EventStore\EventStoreInterface; use PHPUnit\Framework\Assert; @@ -85,13 +85,6 @@ trait CRTestSuiteTrait use WorkspaceDiscarding; use WorkspacePublishing; - protected function setupCRTestSuiteTrait(): void - { - if (getenv('CATCHUPTRIGGER_ENABLE_SYNCHRONOUS_OPTION')) { - CatchUpTriggerWithSynchronousOption::enableSynchronicityForSpeedingUpTesting(); - } - } - /** * @BeforeScenario * @throws \Exception @@ -139,18 +132,6 @@ protected function readPayloadTable(TableNode $payloadTable): array return $eventPayload; } - /** - * @When /^the graph projection is fully up to date$/ - */ - public function theGraphProjectionIsFullyUpToDate(): void - { - if ($this->lastCommandOrEventResult === null) { - throw new \RuntimeException('lastCommandOrEventResult not filled; so I cannot block!'); - } - $this->lastCommandOrEventResult->block(); - $this->lastCommandOrEventResult = null; - } - /** * @Then /^workspace "([^"]*)" points to another content stream than workspace "([^"]*)"$/ */ @@ -299,7 +280,6 @@ public function iPruneUnusedContentStreams(): void /** @var ContentStreamPruner $contentStreamPruner */ $contentStreamPruner = $this->getContentRepositoryService(new ContentStreamPrunerFactory()); $contentStreamPruner->prune(); - $this->lastCommandOrEventResult = $contentStreamPruner->getLastCommandResult(); } /** diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/ContentStreamClosing.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/ContentStreamClosing.php index 8e9589fc490..45095ce4619 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/ContentStreamClosing.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/ContentStreamClosing.php @@ -41,7 +41,7 @@ public function theCommandCloseContentStreamIsExecutedWithPayload(TableNode $pay $command = CloseContentStream::create($contentStreamId); - $this->lastCommandOrEventResult = $this->currentContentRepository->handle($command); + $this->currentContentRepository->handle($command); } /** diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/ContentStreamForking.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/ContentStreamForking.php index c6c887a0770..8fd8d7003ad 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/ContentStreamForking.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/ContentStreamForking.php @@ -45,7 +45,7 @@ public function theCommandForkContentStreamIsExecutedWithPayload(TableNode $payl $sourceContentStreamId, ); - $this->lastCommandOrEventResult = $this->currentContentRepository->handle($command); + $this->currentContentRepository->handle($command); } /** diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeCopying.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeCopying.php index f9c85562631..039c829218b 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeCopying.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeCopying.php @@ -68,6 +68,6 @@ public function theCommandCopyNodesRecursivelyIsExecutedCopyingTheCurrentNodeAgg ); $command = $command->withNodeAggregateIdMapping(NodeAggregateIdMapping::fromArray($commandArguments['nodeAggregateIdMapping'])); - $this->lastCommandOrEventResult = $this->currentContentRepository->handle($command); + $this->currentContentRepository->handle($command); } } diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeCreation.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeCreation.php index e9338a046b8..9aebe808fd9 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeCreation.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeCreation.php @@ -69,7 +69,7 @@ public function theCommandCreateRootNodeAggregateWithNodeIsExecutedWithPayload(T $command = $command->withTetheredDescendantNodeAggregateIds(NodeAggregateIdsByNodePaths::fromArray($commandArguments['tetheredDescendantNodeAggregateIds'])); } - $this->lastCommandOrEventResult = $this->currentContentRepository->handle($command); + $this->currentContentRepository->handle($command); $this->currentRootNodeAggregateId = $nodeAggregateId; } @@ -124,7 +124,7 @@ public function theCommandUpdateRootNodeAggregateDimensionsIsExecutedWithPayload $nodeAggregateId, ); - $this->lastCommandOrEventResult = $this->currentContentRepository->handle($command); + $this->currentContentRepository->handle($command); $this->currentRootNodeAggregateId = $nodeAggregateId; } @@ -161,7 +161,7 @@ public function theCommandCreateNodeAggregateWithNodeIsExecutedWithPayload(Table if (isset($commandArguments['tetheredDescendantNodeAggregateIds'])) { $command = $command->withTetheredDescendantNodeAggregateIds(NodeAggregateIdsByNodePaths::fromArray($commandArguments['tetheredDescendantNodeAggregateIds'])); } - $this->lastCommandOrEventResult = $this->currentContentRepository->handle($command); + $this->currentContentRepository->handle($command); } /** @@ -211,8 +211,7 @@ public function theFollowingCreateNodeAggregateWithNodeCommandsAreExecuted(Table if (isset($row['tetheredDescendantNodeAggregateIds'])) { $command = $command->withTetheredDescendantNodeAggregateIds(NodeAggregateIdsByNodePaths::fromJsonString($row['tetheredDescendantNodeAggregateIds'])); } - $this->lastCommandOrEventResult = $this->currentContentRepository->handle($command); - $this->theGraphProjectionIsFullyUpToDate(); + $this->currentContentRepository->handle($command); } } @@ -257,7 +256,7 @@ public function theCommandCreateNodeAggregateWithNodeAndSerializedPropertiesIsEx if (isset($commandArguments['tetheredDescendantNodeAggregateIds'])) { $command = $command->withTetheredDescendantNodeAggregateIds(NodeAggregateIdsByNodePaths::fromArray($commandArguments['tetheredDescendantNodeAggregateIds'])); } - $this->lastCommandOrEventResult = $this->currentContentRepository->handle($command); + $this->currentContentRepository->handle($command); } /** diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeDisabling.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeDisabling.php index 998f2862bb7..62c6948d904 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeDisabling.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeDisabling.php @@ -57,7 +57,7 @@ public function theCommandDisableNodeAggregateIsExecutedWithPayload(TableNode $p NodeVariantSelectionStrategy::from($commandArguments['nodeVariantSelectionStrategy']), ); - $this->lastCommandOrEventResult = $this->currentContentRepository->handle($command); + $this->currentContentRepository->handle($command); } /** @@ -95,7 +95,7 @@ public function theCommandEnableNodeAggregateIsExecutedWithPayload(TableNode $pa NodeVariantSelectionStrategy::from($commandArguments['nodeVariantSelectionStrategy']), ); - $this->lastCommandOrEventResult = $this->currentContentRepository->handle($command); + $this->currentContentRepository->handle($command); } /** diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeModification.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeModification.php index fcf7c31be82..8618ca89372 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeModification.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeModification.php @@ -61,7 +61,7 @@ public function theCommandSetPropertiesIsExecutedWithPayload(TableNode $payloadT $this->deserializeProperties($commandArguments['propertyValues']), ); - $this->lastCommandOrEventResult = $this->currentContentRepository->handle($command); + $this->currentContentRepository->handle($command); } /** diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeMove.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeMove.php index e965c3e1ca6..a52c6a38518 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeMove.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeMove.php @@ -73,7 +73,7 @@ public function theCommandMoveNodeIsExecutedWithPayload(TableNode $payloadTable) $newSucceedingSiblingNodeAggregateId, ); - $this->lastCommandOrEventResult = $this->currentContentRepository->handle($command); + $this->currentContentRepository->handle($command); } /** diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeReferencing.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeReferencing.php index ea391b1d359..e49210c0e9b 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeReferencing.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeReferencing.php @@ -75,7 +75,7 @@ public function theCommandSetNodeReferencesIsExecutedWithPayload(TableNode $payl $references, ); - $this->lastCommandOrEventResult = $this->currentContentRepository->handle($command); + $this->currentContentRepository->handle($command); } /** diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeRemoval.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeRemoval.php index e6e28de0bd6..1112796f306 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeRemoval.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeRemoval.php @@ -61,7 +61,7 @@ public function theCommandRemoveNodeAggregateIsExecutedWithPayload(TableNode $pa $command = $command->withRemovalAttachmentPoint(NodeAggregateId::fromString($commandArguments['removalAttachmentPoint'])); } - $this->lastCommandOrEventResult = $this->currentContentRepository->handle($command); + $this->currentContentRepository->handle($command); } /** diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeRenaming.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeRenaming.php index f6161196102..3288b58930f 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeRenaming.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeRenaming.php @@ -47,7 +47,7 @@ public function theCommandChangeNodeAggregateNameIsExecutedWithPayload(TableNode NodeName::fromString($commandArguments['newNodeName']), ); - $this->lastCommandOrEventResult = $this->currentContentRepository->handle($command); + $this->currentContentRepository->handle($command); } /** diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeTypeChange.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeTypeChange.php index 045b34a62ba..76eb758223e 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeTypeChange.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeTypeChange.php @@ -53,7 +53,7 @@ public function theCommandChangeNodeAggregateTypeIsExecutedWithPayload(TableNode $command = $command->withTetheredDescendantNodeAggregateIds(NodeAggregateIdsByNodePaths::fromArray($commandArguments['tetheredDescendantNodeAggregateIds'])); } - $this->lastCommandOrEventResult = $this->currentContentRepository->handle($command); + $this->currentContentRepository->handle($command); } /** diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeVariation.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeVariation.php index b73ed130810..3ead5a2de26 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeVariation.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeVariation.php @@ -51,7 +51,7 @@ public function theCommandCreateNodeVariantIsExecutedWithPayload(TableNode $payl OriginDimensionSpacePoint::fromArray($commandArguments['sourceOrigin']), OriginDimensionSpacePoint::fromArray($commandArguments['targetOrigin']), ); - $this->lastCommandOrEventResult = $this->currentContentRepository->handle($command); + $this->currentContentRepository->handle($command); } /** diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/SubtreeTagging.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/SubtreeTagging.php index 0eae60a160f..2a23f47867e 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/SubtreeTagging.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/SubtreeTagging.php @@ -61,7 +61,7 @@ public function theCommandTagSubtreeIsExecutedWithPayload(TableNode $payloadTabl SubtreeTag::fromString($commandArguments['tag']), ); - $this->lastCommandOrEventResult = $this->currentContentRepository->handle($command); + $this->currentContentRepository->handle($command); } /** @@ -136,7 +136,7 @@ public function theCommandUntagSubtreeIsExecutedWithPayload(TableNode $payloadTa SubtreeTag::fromString($commandArguments['tag']), ); - $this->lastCommandOrEventResult = $this->currentContentRepository->handle($command); + $this->currentContentRepository->handle($command); } /** diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/WorkspaceCreation.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/WorkspaceCreation.php index c1db79de268..fec6f30e5a5 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/WorkspaceCreation.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/WorkspaceCreation.php @@ -15,6 +15,7 @@ namespace Neos\ContentRepository\TestSuite\Behavior\Features\Bootstrap\Features; use Behat\Gherkin\Node\TableNode; +use Neos\ContentRepository\Core\Feature\ContentStreamCreation\Command\CreateContentStream; use Neos\ContentRepository\Core\Feature\ContentStreamEventStreamName; use Neos\ContentRepository\Core\Feature\WorkspaceCreation\Command\CreateRootWorkspace; use Neos\ContentRepository\Core\Feature\WorkspaceCreation\Command\CreateWorkspace; @@ -39,6 +40,22 @@ abstract protected function readPayloadTable(TableNode $payloadTable): array; abstract protected function publishEvent(string $eventType, StreamName $streamName, array $eventPayload): void; + /** + * @When /^the command CreateContentStream is executed with payload:$/ + * @param TableNode $payloadTable + * @throws \Exception + */ + public function theCommandCreateContentStreamIsExecutedWithPayload(TableNode $payloadTable) + { + $commandArguments = $this->readPayloadTable($payloadTable); + + $command = CreateContentStream::create( + ContentStreamId::fromString($commandArguments['contentStreamId']), + ); + + $this->currentContentRepository->handle($command); + } + /** * @When /^the command CreateRootWorkspace is executed with payload:$/ * @param TableNode $payloadTable @@ -55,7 +72,7 @@ public function theCommandCreateRootWorkspaceIsExecutedWithPayload(TableNode $pa ContentStreamId::fromString($commandArguments['newContentStreamId']) ); - $this->lastCommandOrEventResult = $this->currentContentRepository->handle($command); + $this->currentContentRepository->handle($command); } /** * @Given /^the event RootWorkspaceWasCreated was published with payload:$/ @@ -88,7 +105,7 @@ public function theCommandCreateWorkspaceIsExecutedWithPayload(TableNode $payloa isset($commandArguments['workspaceOwner']) ? UserId::fromString($commandArguments['workspaceOwner']) : null ); - $this->lastCommandOrEventResult = $this->currentContentRepository->handle($command); + $this->currentContentRepository->handle($command); } @@ -110,7 +127,7 @@ public function theCommandRebaseWorkspaceIsExecutedWithPayload(TableNode $payloa $command = $command->withErrorHandlingStrategy(RebaseErrorHandlingStrategy::from($commandArguments['rebaseErrorHandlingStrategy'])); } - $this->lastCommandOrEventResult = $this->currentContentRepository->handle($command); + $this->currentContentRepository->handle($command); } /** diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/WorkspaceDiscarding.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/WorkspaceDiscarding.php index 3cd4136c4f5..28aaf305b73 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/WorkspaceDiscarding.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/WorkspaceDiscarding.php @@ -46,7 +46,7 @@ public function theCommandDiscardWorkspaceIsExecuted(TableNode $payloadTable): v $command = $command->withNewContentStreamId(ContentStreamId::fromString($commandArguments['newContentStreamId'])); } - $this->lastCommandOrEventResult = $this->currentContentRepository->handle($command); + $this->currentContentRepository->handle($command); } @@ -67,7 +67,7 @@ public function theCommandDiscardIndividualNodesFromWorkspaceIsExecuted(TableNod $command = $command->withNewContentStreamId(ContentStreamId::fromString($commandArguments['newContentStreamId'])); } - $this->lastCommandOrEventResult = $this->currentContentRepository->handle($command); + $this->currentContentRepository->handle($command); } diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/WorkspacePublishing.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/WorkspacePublishing.php index 9f74b4a5bee..0b7c9cf04e9 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/WorkspacePublishing.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/WorkspacePublishing.php @@ -53,7 +53,7 @@ public function theCommandPublishIndividualNodesFromWorkspaceIsExecuted(TableNod $command = $command->withContentStreamIdForRemainingPart(ContentStreamId::fromString($commandArguments['contentStreamIdForRemainingPart'])); } - $this->lastCommandOrEventResult = $this->currentContentRepository->handle($command); + $this->currentContentRepository->handle($command); } /** @@ -85,7 +85,7 @@ public function theCommandPublishWorkspaceIsExecuted(TableNode $payloadTable): v ); } - $this->lastCommandOrEventResult = $this->currentContentRepository->handle($command); + $this->currentContentRepository->handle($command); } /** diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/GenericCommandExecutionAndEventPublication.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/GenericCommandExecutionAndEventPublication.php index 114a73ce42f..c8e2118d5e4 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/GenericCommandExecutionAndEventPublication.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/GenericCommandExecutionAndEventPublication.php @@ -81,7 +81,7 @@ public function theCommandIsExecutedWithPayload(string $shortCommandName, TableN $command = $commandClassName::fromArray($commandArguments); - $this->lastCommandOrEventResult = $this->currentContentRepository->handle($command); + $this->currentContentRepository->handle($command); } /** @@ -140,7 +140,7 @@ protected function publishEvent(string $eventType, StreamName $streamName, array ->getValue($eventPersister); $event = $eventNormalizer->denormalize($artificiallyConstructedEvent); - $this->lastCommandOrEventResult = $eventPersister->publishEvents(new EventsToPublish( + $eventPersister->publishEvents(new EventsToPublish( $streamName, Events::with($event), ExpectedVersion::ANY() diff --git a/Neos.ContentRepositoryRegistry/Classes/Command/ContentCommandController.php b/Neos.ContentRepositoryRegistry/Classes/Command/ContentCommandController.php index d4b5c15dc61..469b2d0dc99 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Command/ContentCommandController.php +++ b/Neos.ContentRepositoryRegistry/Classes/Command/ContentCommandController.php @@ -27,7 +27,6 @@ use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId; use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName; use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry; -use Neos\ContentRepositoryRegistry\Factory\ProjectionCatchUpTrigger\CatchUpTriggerWithSynchronousOption; use Neos\Flow\Cli\CommandController; final class ContentCommandController extends CommandController @@ -75,7 +74,7 @@ public function refreshRootNodeDimensionsCommand(string $contentRepository = 'de $workspaceInstance->workspaceName, $rootNodeAggregate->nodeAggregateId ) - )->block(); + ); } $this->outputLine('Done!'); } @@ -118,7 +117,7 @@ public function moveDimensionSpacePointCommand(string $source, string $target, s $sourceDimensionSpacePoint, $targetDimensionSpacePoint ) - )->block(); + ); $this->outputLine('Done!'); } @@ -164,15 +163,13 @@ public function createVariantsRecursivelyCommand(string $source, string $target, foreach ($rootNodeAggregates as $rootNodeAggregate) { - CatchUpTriggerWithSynchronousOption::synchronously(fn() => - $this->createVariantRecursivelyInternal( - 0, - $rootNodeAggregate->nodeAggregateId, - $sourceSubgraph, - $targetSpacePoint, - $workspaceInstance->workspaceName, - $contentRepositoryInstance, - ) + $this->createVariantRecursivelyInternal( + 0, + $rootNodeAggregate->nodeAggregateId, + $sourceSubgraph, + $targetSpacePoint, + $workspaceInstance->workspaceName, + $contentRepositoryInstance, ); } @@ -202,7 +199,7 @@ private function createVariantRecursivelyInternal(int $level, NodeAggregateId $p $childNode->nodeAggregateId, $childNode->originDimensionSpacePoint, $target - ))->block(); + )); } catch (DimensionSpacePointIsAlreadyOccupied $e) { if ($childNodeType?->isOfType('Neos.Neos:Document')) { $this->output("%s (already exists)\n", [ diff --git a/Neos.ContentRepositoryRegistry/Classes/Command/SubprocessProjectionCatchUpCommandController.php b/Neos.ContentRepositoryRegistry/Classes/Command/SubprocessProjectionCatchUpCommandController.php deleted file mode 100644 index f22557e0c21..00000000000 --- a/Neos.ContentRepositoryRegistry/Classes/Command/SubprocessProjectionCatchUpCommandController.php +++ /dev/null @@ -1,37 +0,0 @@ -> $projectionClassName fully qualified class name of the projection to catch up - * @internal - */ - public function catchupCommand(string $contentRepositoryIdentifier, string $projectionClassName): void - { - $contentRepository = $this->contentRepositoryRegistry->get(ContentRepositoryId::fromString($contentRepositoryIdentifier)); - $contentRepository->catchUpProjection($projectionClassName, CatchUpOptions::create()); - } -} diff --git a/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/CatchUpTriggerWithSynchronousOption.php b/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/CatchUpTriggerWithSynchronousOption.php deleted file mode 100644 index 2a9e68d90dc..00000000000 --- a/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/CatchUpTriggerWithSynchronousOption.php +++ /dev/null @@ -1,75 +0,0 @@ -contentRepositoryRegistry->get($this->contentRepositoryId); - foreach ($projections as $projection) { - $projectionClassName = get_class($projection); - $contentRepository->catchUpProjection($projectionClassName, CatchUpOptions::create()); - } - } else { - $this->inner->triggerCatchUp($projections); - } - } -} diff --git a/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/DefaultCatchUpTrigger.php b/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/DefaultCatchUpTrigger.php new file mode 100644 index 00000000000..d37045664b9 --- /dev/null +++ b/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/DefaultCatchUpTrigger.php @@ -0,0 +1,30 @@ +contentRepositoryRegistry->get($this->contentRepositoryId); + $contentRepository->catchUpProjections(); + } +} diff --git a/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/DefaultProjectionCatchUpTriggerFactory.php b/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/DefaultProjectionCatchUpTriggerFactory.php new file mode 100644 index 00000000000..7d7948ecce6 --- /dev/null +++ b/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/DefaultProjectionCatchUpTriggerFactory.php @@ -0,0 +1,23 @@ + $options */ + public function build(ContentRepositoryId $contentRepositoryId, array $options): DefaultCatchUpTrigger + { + return new DefaultCatchUpTrigger($this->contentRepositoryRegistry, $contentRepositoryId); + } +} diff --git a/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/SubprocessProjectionCatchUpTrigger.php b/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/SubprocessProjectionCatchUpTrigger.php deleted file mode 100644 index f72541368a4..00000000000 --- a/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/SubprocessProjectionCatchUpTrigger.php +++ /dev/null @@ -1,43 +0,0 @@ - - */ - protected $flowSettings; - - public function __construct( - private readonly ContentRepositoryId $contentRepositoryId - ) { - } - - public function triggerCatchUp(Projections $projections): void - { - // modelled after https://github.com/neos/Neos.EventSourcing/blob/master/Classes/EventPublisher/JobQueueEventPublisher.php#L103 - // and https://github.com/Flowpack/jobqueue-common/blob/master/Classes/Queue/FakeQueue.php - foreach ($projections as $projection) { - Scripts::executeCommandAsync( - 'neos.contentrepositoryregistry:subprocessprojectioncatchup:catchup', - $this->flowSettings, - [ - 'contentRepositoryIdentifier' => $this->contentRepositoryId->value, - 'projectionClassName' => get_class($projection) - ] - ); - } - } -} diff --git a/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/SubprocessProjectionCatchUpTriggerFactory.php b/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/SubprocessProjectionCatchUpTriggerFactory.php deleted file mode 100644 index 8695f517d82..00000000000 --- a/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/SubprocessProjectionCatchUpTriggerFactory.php +++ /dev/null @@ -1,22 +0,0 @@ - $options */ - public function build(ContentRepositoryId $contentRepositoryId, array $options): ProjectionCatchUpTriggerInterface - { - return new CatchUpTriggerWithSynchronousOption( - $contentRepositoryId, - new SubprocessProjectionCatchUpTrigger($contentRepositoryId) - ); - } -} diff --git a/Neos.ContentRepositoryRegistry/Classes/Service/EventMigrationService.php b/Neos.ContentRepositoryRegistry/Classes/Service/EventMigrationService.php index a22831bf7bf..32d6acc5a46 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Service/EventMigrationService.php +++ b/Neos.ContentRepositoryRegistry/Classes/Service/EventMigrationService.php @@ -318,7 +318,6 @@ public function migrateMetaDataToWorkspaceName(\Closure $outputFn) private function updateEventPayload(SequenceNumber $sequenceNumber, array $payload): void { $eventTableName = DoctrineEventStoreFactory::databaseTableName($this->contentRepositoryId); - $this->connection->beginTransaction(); $this->connection->executeStatement( 'UPDATE ' . $eventTableName . ' SET payload=:payload WHERE sequencenumber=:sequenceNumber', [ @@ -326,7 +325,6 @@ private function updateEventPayload(SequenceNumber $sequenceNumber, array $paylo 'payload' => json_encode($payload), ] ); - $this->connection->commit(); $this->eventsModified[$sequenceNumber->value] = true; } @@ -336,7 +334,6 @@ private function updateEventPayload(SequenceNumber $sequenceNumber, array $paylo private function updateEventMetaData(SequenceNumber $sequenceNumber, array $eventMetaData): void { $eventTableName = DoctrineEventStoreFactory::databaseTableName($this->contentRepositoryId); - $this->connection->beginTransaction(); $this->connection->executeStatement( 'UPDATE ' . $eventTableName . ' SET metadata=:metadata WHERE sequencenumber=:sequenceNumber', [ @@ -344,7 +341,6 @@ private function updateEventMetaData(SequenceNumber $sequenceNumber, array $even 'metadata' => json_encode($eventMetaData), ] ); - $this->connection->commit(); $this->eventsModified[$sequenceNumber->value] = true; } diff --git a/Neos.ContentRepositoryRegistry/Configuration/Settings.yaml b/Neos.ContentRepositoryRegistry/Configuration/Settings.yaml index 37d72c41045..2b7446d75ad 100644 --- a/Neos.ContentRepositoryRegistry/Configuration/Settings.yaml +++ b/Neos.ContentRepositoryRegistry/Configuration/Settings.yaml @@ -32,7 +32,7 @@ Neos: factoryObjectName: Neos\ContentRepositoryRegistry\Factory\ContentDimensionSource\ConfigurationBasedContentDimensionSourceFactory projectionCatchUpTrigger: - factoryObjectName: Neos\ContentRepositoryRegistry\Factory\ProjectionCatchUpTrigger\SubprocessProjectionCatchUpTriggerFactory + factoryObjectName: Neos\ContentRepositoryRegistry\Factory\ProjectionCatchUpTrigger\DefaultProjectionCatchUpTriggerFactory userIdProvider: factoryObjectName: Neos\ContentRepositoryRegistry\Factory\UserIdProvider\StaticUserIdProviderFactory diff --git a/Neos.Neos/Classes/AssetUsage/Projection/AssetUsageProjection.php b/Neos.Neos/Classes/AssetUsage/Projection/AssetUsageProjection.php index ec762433ff9..c1a6f70ea95 100644 --- a/Neos.Neos/Classes/AssetUsage/Projection/AssetUsageProjection.php +++ b/Neos.Neos/Classes/AssetUsage/Projection/AssetUsageProjection.php @@ -35,6 +35,9 @@ use Neos\Neos\AssetUsage\Dto\AssetUsageNodeAddress; use Neos\Utility\Exception\InvalidTypeException; use Neos\Utility\TypeHandling; +use React\Promise\PromiseInterface; + +use function React\Promise\resolve; /** * @implements ProjectionInterface @@ -62,11 +65,12 @@ public function __construct( ); } - public function reset(): void + public function reset(): PromiseInterface { $this->repository->reset(); $this->checkpointStorage->acquireLock(); $this->checkpointStorage->updateAndReleaseLock(SequenceNumber::none()); + return resolve(null); } public function whenNodeAggregateWithNodeWasCreated(NodeAggregateWithNodeWasCreated $event, EventEnvelope $eventEnvelope): void @@ -253,24 +257,7 @@ public function status(): ProjectionStatus return ProjectionStatus::ok(); } - public function canHandle(EventInterface $event): bool - { - return in_array($event::class, [ - NodeAggregateWithNodeWasCreated::class, - NodePropertiesWereSet::class, - NodeAggregateWasRemoved::class, - NodePeerVariantWasCreated::class, - ContentStreamWasForked::class, - WorkspaceWasDiscarded::class, - WorkspaceWasPartiallyDiscarded::class, - WorkspaceWasPartiallyPublished::class, - WorkspaceWasPublished::class, - WorkspaceWasRebased::class, - ContentStreamWasRemoved::class, - ]); - } - - public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void + public function apply(EventInterface $event, EventEnvelope $eventEnvelope): PromiseInterface { match ($event::class) { NodeAggregateWithNodeWasCreated::class => $this->whenNodeAggregateWithNodeWasCreated($event, $eventEnvelope), @@ -284,8 +271,9 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void WorkspaceWasPublished::class => $this->whenWorkspaceWasPublished($event), WorkspaceWasRebased::class => $this->whenWorkspaceWasRebased($event), ContentStreamWasRemoved::class => $this->whenContentStreamWasRemoved($event), - default => throw new \InvalidArgumentException(sprintf('Unsupported event %s', get_debug_type($event))), + default => null, }; + return resolve(null); } public function getCheckpointStorage(): DbalCheckpointStorage diff --git a/Neos.Neos/Classes/Command/WorkspaceCommandController.php b/Neos.Neos/Classes/Command/WorkspaceCommandController.php index eb0b631a6eb..64d86078143 100644 --- a/Neos.Neos/Classes/Command/WorkspaceCommandController.php +++ b/Neos.Neos/Classes/Command/WorkspaceCommandController.php @@ -153,7 +153,7 @@ public function createRootCommand(string $name, string $contentRepositoryIdentif WorkspaceTitle::fromString($name), WorkspaceDescription::fromString($name), ContentStreamId::create() - ))->block(); + )); } /** @@ -199,7 +199,7 @@ public function createCommand( WorkspaceDescription::fromString($description ?: $workspace), ContentStreamId::create(), $workspaceOwnerUserId - ))->block(); + )); } catch (WorkspaceAlreadyExists $workspaceAlreadyExists) { $this->outputLine('Workspace "%s" already exists', [$workspace]); $this->quit(1); @@ -309,7 +309,7 @@ public function deleteCommand(string $workspace, bool $force = false, string $co DeleteWorkspace::create( $workspaceName ) - )->block(); + ); $this->outputLine('Deleted workspace "%s"', [$workspaceName->value]); } diff --git a/Neos.Neos/Classes/Controller/Module/Management/WorkspacesController.php b/Neos.Neos/Classes/Controller/Module/Management/WorkspacesController.php index 4db51ab429e..cf051375850 100644 --- a/Neos.Neos/Classes/Controller/Module/Management/WorkspacesController.php +++ b/Neos.Neos/Classes/Controller/Module/Management/WorkspacesController.php @@ -240,7 +240,7 @@ public function createAction( ContentStreamId::create(), $visibility === 'private' ? $currentUserIdentifier : null ) - )->block(); + ); } catch (WorkspaceAlreadyExists $exception) { $this->addFlashMessage( $this->getModuleLabel('workspaces.workspaceWithThisTitleAlreadyExists'), @@ -319,7 +319,7 @@ public function updateAction( $title, $description ) - )->block(); + ); } if ($workspace->workspaceOwner !== $workspaceOwner) { @@ -328,7 +328,7 @@ public function updateAction( $workspaceName, $workspaceOwner ?: null, ) - )->block(); + ); } $this->addFlashMessage($this->translator->translateById( @@ -428,7 +428,7 @@ public function deleteAction(WorkspaceName $workspaceName): void DeleteWorkspace::create( $workspaceName, ) - )->block(); + ); $this->addFlashMessage($this->translator->translateById( 'workspaces.workspaceHasBeenRemoved', @@ -531,7 +531,7 @@ public function publishNodeAction(string $nodeAddress, WorkspaceName $selectedWo ), ); $contentRepository->handle($command) - ->block(); + ; $this->addFlashMessage($this->translator->translateById( 'workspaces.selectedChangeHasBeenPublished', @@ -568,7 +568,7 @@ public function discardNodeAction(string $nodeAddress, WorkspaceName $selectedWo ), ); $contentRepository->handle($command) - ->block(); + ; $this->addFlashMessage($this->translator->translateById( 'workspaces.selectedChangeHasBeenDiscarded', @@ -611,7 +611,7 @@ public function publishOrDiscardNodesAction(array $nodes, string $action, string NodeIdsToPublishOrDiscard::create(...$nodesToPublishOrDiscard), ); $contentRepository->handle($command) - ->block(); + ; $this->addFlashMessage($this->translator->translateById( 'workspaces.selectedChangesHaveBeenPublished', [], @@ -627,7 +627,7 @@ public function publishOrDiscardNodesAction(array $nodes, string $action, string NodeIdsToPublishOrDiscard::create(...$nodesToPublishOrDiscard), ); $contentRepository->handle($command) - ->block(); + ; $this->addFlashMessage($this->translator->translateById( 'workspaces.selectedChangesHaveBeenDiscarded', [], diff --git a/Neos.Neos/Classes/Controller/Service/NodesController.php b/Neos.Neos/Classes/Controller/Service/NodesController.php index d8db9a2fcc7..7a1ca0371e0 100644 --- a/Neos.Neos/Classes/Controller/Service/NodesController.php +++ b/Neos.Neos/Classes/Controller/Service/NodesController.php @@ -31,7 +31,6 @@ use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName; use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry; -use Neos\ContentRepositoryRegistry\Factory\ProjectionCatchUpTrigger\CatchUpTriggerWithSynchronousOption; use Neos\Flow\Annotations as Flow; use Neos\Flow\Mvc\Controller\ActionController; use Neos\Flow\Property\PropertyMapper; @@ -296,16 +295,15 @@ public function createAction( ); if ($mode === 'adoptFromAnotherDimension' || $mode === 'adoptFromAnotherDimensionAndCopyContent') { - CatchUpTriggerWithSynchronousOption::synchronously(fn() => - $this->adoptNodeAndParents( - $workspace->workspaceName, - $nodeAggregateId, - $sourceSubgraph, - $targetSubgraph, - $targetDimensionSpacePoint, - $contentRepository, - $mode === 'adoptFromAnotherDimensionAndCopyContent' - )); + $this->adoptNodeAndParents( + $workspace->workspaceName, + $nodeAggregateId, + $sourceSubgraph, + $targetSubgraph, + $targetDimensionSpacePoint, + $contentRepository, + $mode === 'adoptFromAnotherDimensionAndCopyContent' + ); $this->redirect('show', null, null, [ 'identifier' => $nodeAggregateId->value, @@ -424,7 +422,7 @@ protected function adoptNodeAndParents( $sourceNode->originDimensionSpacePoint, OriginDimensionSpacePoint::fromDimensionSpacePoint($targetDimensionSpacePoint), ) - )->block(); + ); if ($copyContent === true) { $contentNodeConstraint = NodeTypeCriteria::fromFilterString('!' . NodeTypeNameFactory::NAME_DOCUMENT); @@ -466,7 +464,7 @@ private function createNodeVariantsForChildNodes( $childNode->originDimensionSpacePoint, OriginDimensionSpacePoint::fromDimensionSpacePoint($targetDimensionSpacePoint), ) - )->block(); + ); } $this->createNodeVariantsForChildNodes( diff --git a/Neos.Neos/Classes/Domain/Service/SiteServiceInternals.php b/Neos.Neos/Classes/Domain/Service/SiteServiceInternals.php index 7dbe858a5c5..082efb5e3a4 100644 --- a/Neos.Neos/Classes/Domain/Service/SiteServiceInternals.php +++ b/Neos.Neos/Classes/Domain/Service/SiteServiceInternals.php @@ -130,7 +130,7 @@ public function createSiteNodeIfNotExists(Site $site, string $nodeTypeName): voi PropertyValuesToWrite::fromArray([ 'title' => $site->getName() ]) - ))->block(); + )); // Handle remaining root dimension space points by creating peer variants foreach ($rootDimensionSpacePoints as $rootDimensionSpacePoint) { @@ -139,7 +139,7 @@ public function createSiteNodeIfNotExists(Site $site, string $nodeTypeName): voi $siteNodeAggregateId, OriginDimensionSpacePoint::fromDimensionSpacePoint($arbitraryRootDimensionSpacePoint), OriginDimensionSpacePoint::fromDimensionSpacePoint($rootDimensionSpacePoint), - ))->block(); + )); } } } diff --git a/Neos.Neos/Classes/Domain/Workspace/Workspace.php b/Neos.Neos/Classes/Domain/Workspace/Workspace.php index 670a4d9f7f7..cab3ed668a7 100644 --- a/Neos.Neos/Classes/Domain/Workspace/Workspace.php +++ b/Neos.Neos/Classes/Domain/Workspace/Workspace.php @@ -241,7 +241,7 @@ public function rebase(RebaseErrorHandlingStrategy $rebaseErrorHandlingStrategy $this->name )->withErrorHandlingStrategy($rebaseErrorHandlingStrategy); - $this->contentRepository->handle($rebaseCommand)->block(); + $this->contentRepository->handle($rebaseCommand); $this->updateCurrentState(); } @@ -253,7 +253,7 @@ public function changeBaseWorkspace(WorkspaceName $baseWorkspaceName): void $this->name, $baseWorkspaceName ) - )->block(); + ); $this->updateCurrentState(); } @@ -291,7 +291,7 @@ private function publish(): void PublishWorkspace::create( $this->name, ) - )->block(); + ); $this->updateCurrentState(); } @@ -307,14 +307,14 @@ private function publishNodes( RebaseWorkspace::create( $this->name ) - )->block(); + ); $this->contentRepository->handle( PublishIndividualNodesFromWorkspace::create( $this->name, $nodeIdsToPublish ) - )->block(); + ); $this->updateCurrentState(); } @@ -325,7 +325,7 @@ private function discard(): void DiscardWorkspace::create( $this->name, ) - )->block(); + ); $this->updateCurrentState(); } @@ -341,14 +341,14 @@ private function discardNodes( RebaseWorkspace::create( $this->name ) - )->block(); + ); $this->contentRepository->handle( DiscardIndividualNodesFromWorkspace::create( $this->name, $nodeIdsToDiscard ) - )->block(); + ); $this->updateCurrentState(); } diff --git a/Neos.Neos/Classes/FrontendRouting/Projection/DocumentUriPathProjection.php b/Neos.Neos/Classes/FrontendRouting/Projection/DocumentUriPathProjection.php index c6e503d57c8..90413cf21e8 100644 --- a/Neos.Neos/Classes/FrontendRouting/Projection/DocumentUriPathProjection.php +++ b/Neos.Neos/Classes/FrontendRouting/Projection/DocumentUriPathProjection.php @@ -43,6 +43,9 @@ use Neos\Neos\Domain\Model\SiteNodeName; use Neos\Neos\Domain\Service\NodeTypeNameFactory; use Neos\Neos\FrontendRouting\Exception\NodeNotFoundException; +use React\Promise\PromiseInterface; + +use function React\Promise\resolve; /** * @implements ProjectionInterface @@ -120,12 +123,13 @@ private function determineRequiredSqlStatements(): array } - public function reset(): void + public function reset(): PromiseInterface { $this->truncateDatabaseTables(); $this->checkpointStorage->acquireLock(); $this->checkpointStorage->updateAndReleaseLock(SequenceNumber::none()); $this->stateAccessor = null; + return resolve(null); } private function truncateDatabaseTables(): void @@ -138,29 +142,7 @@ private function truncateDatabaseTables(): void } } - - public function canHandle(EventInterface $event): bool - { - return in_array($event::class, [ - RootWorkspaceWasCreated::class, - RootNodeAggregateWithNodeWasCreated::class, - RootNodeAggregateDimensionsWereUpdated::class, - NodeAggregateWithNodeWasCreated::class, - NodeAggregateTypeWasChanged::class, - NodePeerVariantWasCreated::class, - NodeGeneralizationVariantWasCreated::class, - NodeSpecializationVariantWasCreated::class, - SubtreeWasTagged::class, - SubtreeWasUntagged::class, - NodeAggregateWasRemoved::class, - NodePropertiesWereSet::class, - NodeAggregateWasMoved::class, - DimensionSpacePointWasMoved::class, - DimensionShineThroughWasAdded::class, - ]); - } - - public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void + public function apply(EventInterface $event, EventEnvelope $eventEnvelope): PromiseInterface { match ($event::class) { RootWorkspaceWasCreated::class => $this->whenRootWorkspaceWasCreated($event), @@ -178,8 +160,9 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void NodeAggregateWasMoved::class => $this->whenNodeAggregateWasMoved($event), DimensionSpacePointWasMoved::class => $this->whenDimensionSpacePointWasMoved($event), DimensionShineThroughWasAdded::class => $this->whenDimensionShineThroughWasAdded($event), - default => throw new \InvalidArgumentException(sprintf('Unsupported event %s', get_debug_type($event))), + default => null, }; + return resolve(null); } public function getCheckpointStorage(): DbalCheckpointStorage diff --git a/Neos.Neos/Classes/Fusion/Cache/GraphProjectorCatchUpHookForCacheFlushing.php b/Neos.Neos/Classes/Fusion/Cache/GraphProjectorCatchUpHookForCacheFlushing.php index e26a5d526e9..66c00cf5cb0 100644 --- a/Neos.Neos/Classes/Fusion/Cache/GraphProjectorCatchUpHookForCacheFlushing.php +++ b/Neos.Neos/Classes/Fusion/Cache/GraphProjectorCatchUpHookForCacheFlushing.php @@ -28,9 +28,7 @@ * is not needed: * * By calling {@see self::disabled(\Closure)} in your code, all projection updates - * will never trigger catch up hooks. This will only work when - * {@see CatchUpTriggerWithSynchronousOption::synchronously()} is called, - * as otherwise this subprocess won't be called. + * will never trigger catch up hooks. * * * The following scenario explains how to think about cache flushing. diff --git a/Neos.Neos/Classes/PendingChangesProjection/ChangeProjection.php b/Neos.Neos/Classes/PendingChangesProjection/ChangeProjection.php index fd67227a3de..c833a48f4d6 100644 --- a/Neos.Neos/Classes/PendingChangesProjection/ChangeProjection.php +++ b/Neos.Neos/Classes/PendingChangesProjection/ChangeProjection.php @@ -46,6 +46,9 @@ use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; use Neos\EventStore\Model\Event\SequenceNumber; use Neos\EventStore\Model\EventEnvelope; +use React\Promise\PromiseInterface; + +use function React\Promise\resolve; /** * TODO: this class needs testing and probably a major refactoring! @@ -153,33 +156,16 @@ private function determineRequiredSqlStatements(): array return DbalSchemaDiff::determineRequiredSqlStatements($connection, $schema); } - public function reset(): void + public function reset(): PromiseInterface { $this->getDatabaseConnection()->exec('TRUNCATE ' . $this->tableNamePrefix); $this->getDatabaseConnection()->exec('TRUNCATE ' . $this->tableNamePrefix . '_livecontentstreams'); $this->checkpointStorage->acquireLock(); $this->checkpointStorage->updateAndReleaseLock(SequenceNumber::none()); + return resolve(null); } - public function canHandle(EventInterface $event): bool - { - return in_array($event::class, [ - RootWorkspaceWasCreated::class, - NodeAggregateWasMoved::class, - NodePropertiesWereSet::class, - NodeReferencesWereSet::class, - NodeAggregateWithNodeWasCreated::class, - SubtreeWasTagged::class, - SubtreeWasUntagged::class, - NodeAggregateWasRemoved::class, - DimensionSpacePointWasMoved::class, - NodeGeneralizationVariantWasCreated::class, - NodeSpecializationVariantWasCreated::class, - NodePeerVariantWasCreated::class - ]); - } - - public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void + public function apply(EventInterface $event, EventEnvelope $eventEnvelope): PromiseInterface { match ($event::class) { RootWorkspaceWasCreated::class => $this->whenRootWorkspaceWasCreated($event), @@ -194,8 +180,9 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void NodeSpecializationVariantWasCreated::class => $this->whenNodeSpecializationVariantWasCreated($event), NodeGeneralizationVariantWasCreated::class => $this->whenNodeGeneralizationVariantWasCreated($event), NodePeerVariantWasCreated::class => $this->whenNodePeerVariantWasCreated($event), - default => throw new \InvalidArgumentException(sprintf('Unsupported event %s', get_debug_type($event))), + default => null, }; + return resolve(null); } public function getCheckpointStorage(): DbalCheckpointStorage @@ -297,79 +284,75 @@ private function whenSubtreeWasUntagged(SubtreeWasUntagged $event): void private function whenNodeAggregateWasRemoved(NodeAggregateWasRemoved $event): void { - $this->transactional(function () use ($event) { - if ($this->isLiveContentStream($event->contentStreamId)) { - return; - } + if ($this->isLiveContentStream($event->contentStreamId)) { + return; + } + + $this->getDatabaseConnection()->executeUpdate( + 'DELETE FROM ' . $this->tableNamePrefix . ' + WHERE + contentStreamId = :contentStreamId + AND nodeAggregateId = :nodeAggregateId + AND originDimensionSpacePointHash IN (:affectedDimensionSpacePointHashes) + ', + [ + 'contentStreamId' => $event->contentStreamId->value, + 'nodeAggregateId' => $event->nodeAggregateId->value, + 'affectedDimensionSpacePointHashes' => $event->affectedCoveredDimensionSpacePoints + ->getPointHashes() + ], + [ + 'affectedDimensionSpacePointHashes' => Connection::PARAM_STR_ARRAY + ] + ); + foreach ($event->affectedOccupiedDimensionSpacePoints as $occupiedDimensionSpacePoint) { $this->getDatabaseConnection()->executeUpdate( - 'DELETE FROM ' . $this->tableNamePrefix . ' - WHERE - contentStreamId = :contentStreamId - AND nodeAggregateId = :nodeAggregateId - AND originDimensionSpacePointHash IN (:affectedDimensionSpacePointHashes) - ', + 'INSERT INTO ' . $this->tableNamePrefix . ' + (contentStreamId, nodeAggregateId, originDimensionSpacePoint, + originDimensionSpacePointHash, created, deleted, changed, moved, removalAttachmentPoint) + VALUES ( + :contentStreamId, + :nodeAggregateId, + :originDimensionSpacePoint, + :originDimensionSpacePointHash, + 0, + 1, + 0, + 0, + :removalAttachmentPoint + ) + ', [ 'contentStreamId' => $event->contentStreamId->value, 'nodeAggregateId' => $event->nodeAggregateId->value, - 'affectedDimensionSpacePointHashes' => $event->affectedCoveredDimensionSpacePoints - ->getPointHashes() - ], - [ - 'affectedDimensionSpacePointHashes' => Connection::PARAM_STR_ARRAY + 'originDimensionSpacePoint' => json_encode($occupiedDimensionSpacePoint), + 'originDimensionSpacePointHash' => $occupiedDimensionSpacePoint->hash, + 'removalAttachmentPoint' => $event->removalAttachmentPoint?->value, ] ); - - foreach ($event->affectedOccupiedDimensionSpacePoints as $occupiedDimensionSpacePoint) { - $this->getDatabaseConnection()->executeUpdate( - 'INSERT INTO ' . $this->tableNamePrefix . ' - (contentStreamId, nodeAggregateId, originDimensionSpacePoint, - originDimensionSpacePointHash, created, deleted, changed, moved, removalAttachmentPoint) - VALUES ( - :contentStreamId, - :nodeAggregateId, - :originDimensionSpacePoint, - :originDimensionSpacePointHash, - 0, - 1, - 0, - 0, - :removalAttachmentPoint - ) - ', - [ - 'contentStreamId' => $event->contentStreamId->value, - 'nodeAggregateId' => $event->nodeAggregateId->value, - 'originDimensionSpacePoint' => json_encode($occupiedDimensionSpacePoint), - 'originDimensionSpacePointHash' => $occupiedDimensionSpacePoint->hash, - 'removalAttachmentPoint' => $event->removalAttachmentPoint?->value, - ] - ); - } - }); + } } private function whenDimensionSpacePointWasMoved(DimensionSpacePointWasMoved $event): void { - $this->transactional(function () use ($event) { - $this->getDatabaseConnection()->executeStatement( - ' - UPDATE ' . $this->tableNamePrefix . ' c - SET - c.originDimensionSpacePoint = :newDimensionSpacePoint, - c.originDimensionSpacePointHash = :newDimensionSpacePointHash - WHERE - c.originDimensionSpacePointHash = :originalDimensionSpacePointHash - AND c.contentStreamId = :contentStreamId - ', - [ - 'originalDimensionSpacePointHash' => $event->source->hash, - 'newDimensionSpacePointHash' => $event->target->hash, - 'newDimensionSpacePoint' => $event->target->toJson(), - 'contentStreamId' => $event->contentStreamId->value - ] - ); - }); + $this->getDatabaseConnection()->executeStatement( + ' + UPDATE ' . $this->tableNamePrefix . ' c + SET + c.originDimensionSpacePoint = :newDimensionSpacePoint, + c.originDimensionSpacePointHash = :newDimensionSpacePointHash + WHERE + c.originDimensionSpacePointHash = :originalDimensionSpacePointHash + AND c.contentStreamId = :contentStreamId + ', + [ + 'originalDimensionSpacePointHash' => $event->source->hash, + 'newDimensionSpacePointHash' => $event->target->hash, + 'newDimensionSpacePoint' => $event->target->toJson(), + 'contentStreamId' => $event->contentStreamId->value + ] + ); } @@ -452,27 +435,20 @@ private function modifyChange( OriginDimensionSpacePoint $originDimensionSpacePoint, callable $modifyFn ): void { - $this->transactional(function () use ( - $contentStreamId, - $nodeAggregateId, - $originDimensionSpacePoint, - $modifyFn - ) { - if ($this->isLiveContentStream($contentStreamId)) { - return; - } + if ($this->isLiveContentStream($contentStreamId)) { + return; + } - $change = $this->getChange($contentStreamId, $nodeAggregateId, $originDimensionSpacePoint); + $change = $this->getChange($contentStreamId, $nodeAggregateId, $originDimensionSpacePoint); - if ($change === null) { - $change = new Change($contentStreamId, $nodeAggregateId, $originDimensionSpacePoint, false, false, false, false); - $modifyFn($change); - $change->addToDatabase($this->getDatabaseConnection(), $this->tableNamePrefix); - } else { - $modifyFn($change); - $change->updateToDatabase($this->getDatabaseConnection(), $this->tableNamePrefix); - } - }); + if ($change === null) { + $change = new Change($contentStreamId, $nodeAggregateId, $originDimensionSpacePoint, false, false, false, false); + $modifyFn($change); + $change->addToDatabase($this->getDatabaseConnection(), $this->tableNamePrefix); + } else { + $modifyFn($change); + $change->updateToDatabase($this->getDatabaseConnection(), $this->tableNamePrefix); + } } private function getChange( @@ -496,11 +472,6 @@ private function getChange( return $changeRow ? Change::fromDatabaseRow($changeRow) : null; } - private function transactional(\Closure $operations): void - { - $this->getDatabaseConnection()->transactional($operations); - } - /** * @return Connection */ diff --git a/Neos.Neos/Classes/Service/EditorContentStreamZookeeper.php b/Neos.Neos/Classes/Service/EditorContentStreamZookeeper.php index 1842236da31..f4e18d0a96d 100644 --- a/Neos.Neos/Classes/Service/EditorContentStreamZookeeper.php +++ b/Neos.Neos/Classes/Service/EditorContentStreamZookeeper.php @@ -136,6 +136,6 @@ public function relayEditorAuthentication(Authentication\TokenInterface $token): $editorsNewContentStreamId, UserId::fromString($this->persistenceManager->getIdentifierByObject($user)) ) - )->block(); + ); } } diff --git a/Neos.Neos/Tests/Behavior/Features/Bootstrap/FeatureContext.php b/Neos.Neos/Tests/Behavior/Features/Bootstrap/FeatureContext.php index 340bff03d86..4b0d8175170 100644 --- a/Neos.Neos/Tests/Behavior/Features/Bootstrap/FeatureContext.php +++ b/Neos.Neos/Tests/Behavior/Features/Bootstrap/FeatureContext.php @@ -49,7 +49,6 @@ public function __construct() $this->environment = $this->getObject(Environment::class); $this->contentRepositoryRegistry = $this->getObject(ContentRepositoryRegistry::class); - $this->setupCRTestSuiteTrait(); } /* diff --git a/Neos.Neos/Tests/Behavior/Features/Bootstrap/RoutingTrait.php b/Neos.Neos/Tests/Behavior/Features/Bootstrap/RoutingTrait.php index ed45891c0b7..07957742e4e 100644 --- a/Neos.Neos/Tests/Behavior/Features/Bootstrap/RoutingTrait.php +++ b/Neos.Neos/Tests/Behavior/Features/Bootstrap/RoutingTrait.php @@ -164,18 +164,6 @@ public function anAssetExists(string $assetIdentifier, string $fileName, string $persistenceManager->clearState(); } - /** - * @When The documenturipath projection is up to date - */ - public function theDocumenturipathProjectionIsUpToDate(): void - { - if ($this->lastCommandOrEventResult === null) { - // we just blocked in "The graph projection is up to date" - return; - } - $this->lastCommandOrEventResult->block(); - } - /** * @When I am on URL :url */ diff --git a/Neos.Neos/Tests/Behavior/Features/FrontendRouting/Basic.feature b/Neos.Neos/Tests/Behavior/Features/FrontendRouting/Basic.feature index 42fdfa0c5d4..a1b4c2d97f6 100644 --- a/Neos.Neos/Tests/Behavior/Features/FrontendRouting/Basic.feature +++ b/Neos.Neos/Tests/Behavior/Features/FrontendRouting/Basic.feature @@ -36,7 +36,6 @@ Feature: Basic routing functionality (match & resolve document nodes in one dime | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.Neos:Sites" | - And the graph projection is fully up to date # lady-eleonode-rootford # shernode-homes @@ -65,7 +64,6 @@ Feature: Basic routing functionality (match & resolve document nodes in one dime resolver: factoryClassName: Neos\Neos\FrontendRouting\DimensionResolution\Resolver\NoopResolverFactory """ - And The documenturipath projection is up to date Scenario: Match homepage URL When I am on URL "/" @@ -93,7 +91,6 @@ Feature: Basic routing functionality (match & resolve document nodes in one dime | nodeAggregateId | "sir-david-nodenborough" | | originDimensionSpacePoint | {} | | propertyValues | {"uriPathSegment": "david-nodenborough-updated"} | - And The documenturipath projection is up to date And I am on URL "/" Then the node "sir-david-nodenborough" in content stream "cs-identifier" and dimension "{}" should resolve to URL "/david-nodenborough-updated" And the node "earl-o-documentbourgh" in content stream "cs-identifier" and dimension "{}" should resolve to URL "/david-nodenborough-updated/earl-document" @@ -104,13 +101,11 @@ Feature: Basic routing functionality (match & resolve document nodes in one dime | nodeAggregateId | "sir-david-nodenborough" | | originDimensionSpacePoint | {} | | propertyValues | {"uriPathSegment": "david-nodenborough-updated-a"} | - And The documenturipath projection is up to date When the command SetNodeProperties is executed with payload: | Key | Value | | nodeAggregateId | "sir-david-nodenborough" | | originDimensionSpacePoint | {} | | propertyValues | {"uriPathSegment": "david-nodenborough-updated-b"} | - And The documenturipath projection is up to date And I am on URL "/" Then the node "sir-david-nodenborough" in content stream "cs-identifier" and dimension "{}" should resolve to URL "/david-nodenborough-updated-b" @@ -130,7 +125,6 @@ Feature: Basic routing functionality (match & resolve document nodes in one dime | dimensionSpacePoint | {} | | newParentNodeAggregateId | "shernode-homes" | | newSucceedingSiblingNodeAggregateId | null | - And The documenturipath projection is up to date And I am on URL "/earl-document" Then the matched node should be "earl-o-documentbourgh" in content stream "cs-identifier" and dimension "{}" And the node "earl-o-documentbourgh" in content stream "cs-identifier" and dimension "{}" should resolve to URL "/earl-document" @@ -142,7 +136,6 @@ Feature: Basic routing functionality (match & resolve document nodes in one dime | dimensionSpacePoint | {} | | newParentNodeAggregateId | "earl-o-documentbourgh" | | newSucceedingSiblingNodeAggregateId | null | - And The documenturipath projection is up to date And I am on URL "/david-nodenborough/earl-document/nody" Then the matched node should be "nody-mc-nodeface" in content stream "cs-identifier" and dimension "{}" And the node "nody-mc-nodeface" in content stream "cs-identifier" and dimension "{}" should resolve to URL "/david-nodenborough/earl-document/nody" diff --git a/Neos.Neos/Tests/Behavior/Features/FrontendRouting/Dimensions.feature b/Neos.Neos/Tests/Behavior/Features/FrontendRouting/Dimensions.feature index 4e4fcc69784..05e72be025a 100644 --- a/Neos.Neos/Tests/Behavior/Features/FrontendRouting/Dimensions.feature +++ b/Neos.Neos/Tests/Behavior/Features/FrontendRouting/Dimensions.feature @@ -48,7 +48,6 @@ Feature: Routing functionality with multiple content dimensions | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.Neos:Sites" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | parentNodeAggregateId | nodeTypeName | initialPropertyValues | nodeName | | sir-david-nodenborough | lady-eleonode-rootford | Neos.Neos:Test.Routing.Page | {"uriPathSegment": "ignore-me"} | node1 | @@ -59,7 +58,6 @@ Feature: Routing functionality with multiple content dimensions | nodeAggregateId | "carl-destinode" | | sourceOrigin | {"market":"DE", "language":"en"} | | targetOrigin | {"market":"DE", "language":"de"} | - And the graph projection is fully up to date And the command SetNodeProperties is executed with payload: | Key | Value | | nodeAggregateId | "carl-destinode" | @@ -93,9 +91,6 @@ Feature: Routing functionality with multiple content dimensions DE: '' """ - And the graph projection is fully up to date - And The documenturipath projection is up to date - Scenario: Resolve homepage URL in multiple dimensions When I am on URL "/" Then the node "sir-david-nodenborough" in content stream "cs-identifier" and dimension '{"market":"DE", "language":"en"}' should resolve to URL "/" @@ -204,8 +199,6 @@ Feature: Routing functionality with multiple content dimensions When the command PublishWorkspace is executed with payload: | Key | Value | | workspaceName | "migration-cs" | - And the graph projection is fully up to date - And The documenturipath projection is up to date When I am on URL "/" Then the node "carl-destinode" in content stream "cs-identifier" and dimension '{"market":"CH", "language":"en"}' should resolve to URL "/nody/carl" @@ -274,8 +267,6 @@ Feature: Routing functionality with multiple content dimensions When the command PublishWorkspace is executed with payload: | Key | Value | | workspaceName | "migration-cs" | - And the graph projection is fully up to date - And The documenturipath projection is up to date When I am on URL "/" And the node "carl-destinode" in content stream "cs-identifier" and dimension '{"market":"DE", "language":"de"}' should resolve to URL "/de/nody/karl-de" @@ -288,7 +279,6 @@ Feature: Routing functionality with multiple content dimensions | nodeAggregateId | "carl-destinode" | | originDimensionSpacePoint | {"market":"DE", "language":"de"} | | propertyValues | {"uriPathSegment": "karl-aktualisiert"} | - And The documenturipath projection is up to date When I am on URL "/" And the node "carl-destinode" in content stream "cs-identifier" and dimension '{"market":"DE", "language":"de"}' should resolve to URL "/de/nody/karl-aktualisiert" # testcase for #4256 @@ -328,29 +318,23 @@ Feature: Routing functionality with multiple content dimensions And the command UpdateRootNodeAggregateDimensions is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | - And the graph projection is fully up to date # create variant for fr and sites node When the command CreateNodeVariant is executed with payload: | Key | Value | | nodeAggregateId | "sir-david-nodenborough" | | sourceOrigin | {"market":"DE", "language":"en"} | | targetOrigin | {"market":"DE", "language":"fr"} | - And the graph projection is fully up to date When the command CreateNodeVariant is executed with payload: | Key | Value | | nodeAggregateId | "nody-mc-nodeface" | | sourceOrigin | {"market":"DE", "language":"en"} | | targetOrigin | {"market":"DE", "language":"fr"} | - - And the graph projection is fully up to date And the command SetNodeProperties is executed with payload: | Key | Value | | nodeAggregateId | "nody-mc-nodeface" | | originDimensionSpacePoint | {"market":"DE", "language":"fr"} | | propertyValues | {"uriPathSegment": "nody-fr"} | - And the graph projection is fully up to date - When I am on URL "/" Then the node "sir-david-nodenborough" in content stream "cs-identifier" and dimension '{"market":"DE", "language":"fr"}' should resolve to URL "/fr/" Then the node "nody-mc-nodeface" in content stream "cs-identifier" and dimension '{"market":"DE", "language":"fr"}' should resolve to URL "/fr/nody-fr" @@ -389,28 +373,23 @@ Feature: Routing functionality with multiple content dimensions And the command UpdateRootNodeAggregateDimensions is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | - And the graph projection is fully up to date # create variant for fr and sites node When the command CreateNodeVariant is executed with payload: | Key | Value | | nodeAggregateId | "sir-david-nodenborough" | | sourceOrigin | {"market":"DE", "language":"en"} | | targetOrigin | {"market":"DE", "language":"fr"} | - And the graph projection is fully up to date When the command CreateNodeVariant is executed with payload: | Key | Value | | nodeAggregateId | "nody-mc-nodeface" | | sourceOrigin | {"market":"DE", "language":"en"} | | targetOrigin | {"market":"DE", "language":"fr"} | - And the graph projection is fully up to date - And the command SetNodeProperties is executed with payload: | Key | Value | | nodeAggregateId | "nody-mc-nodeface" | | originDimensionSpacePoint | {"market":"DE", "language":"fr"} | | propertyValues | {"uriPathSegment": "nody-fr"} | - And the graph projection is fully up to date When the command MoveNodeAggregate is executed with payload: | Key | Value | @@ -419,9 +398,6 @@ Feature: Routing functionality with multiple content dimensions | newParentNodeAggregateId | "lady-eleonode-rootford" | | newSucceedingSiblingNodeAggregateId | null | | relationDistributionStrategy | "scatter" | - And The documenturipath projection is up to date - - And the graph projection is fully up to date When I am on URL "/" Then the node "sir-david-nodenborough" in content stream "cs-identifier" and dimension '{"market":"DE", "language":"en"}' should resolve to URL "/" diff --git a/Neos.Neos/Tests/Behavior/Features/FrontendRouting/DisableNodes.feature b/Neos.Neos/Tests/Behavior/Features/FrontendRouting/DisableNodes.feature index 786be2fb737..6fad5f62eef 100644 --- a/Neos.Neos/Tests/Behavior/Features/FrontendRouting/DisableNodes.feature +++ b/Neos.Neos/Tests/Behavior/Features/FrontendRouting/DisableNodes.feature @@ -35,7 +35,6 @@ Feature: Routing behavior of removed, disabled and re-enabled nodes | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.Neos:Sites" | - And the graph projection is fully up to date # lady-eleonode-rootford # shernode-homes @@ -66,15 +65,12 @@ Feature: Routing behavior of removed, disabled and re-enabled nodes factoryClassName: Neos\Neos\FrontendRouting\DimensionResolution\Resolver\NoopResolverFactory """ - And The documenturipath projection is up to date - Scenario: Disable leaf node When the command DisableNodeAggregate is executed with payload: | Key | Value | | nodeAggregateId | "leaf-mc-node" | | coveredDimensionSpacePoint | {} | | nodeVariantSelectionStrategy | "allVariants" | - And The documenturipath projection is up to date Then No node should match URL "/david-nodenborough/earl-document/leaf" And The node "leaf-mc-node" in content stream "cs-identifier" and dimension "{}" should resolve to URL "/david-nodenborough/earl-document/leaf" @@ -84,7 +80,6 @@ Feature: Routing behavior of removed, disabled and re-enabled nodes | nodeAggregateId | "sir-david-nodenborough" | | coveredDimensionSpacePoint | {} | | nodeVariantSelectionStrategy | "allVariants" | - And The documenturipath projection is up to date Then No node should match URL "/david-nodenborough" And No node should match URL "/david-nodenborough/earl-document" And The node "sir-david-nodenborough" in content stream "cs-identifier" and dimension "{}" should resolve to URL "/david-nodenborough" @@ -101,8 +96,6 @@ Feature: Routing behavior of removed, disabled and re-enabled nodes | nodeAggregateId | "earl-o-documentbourgh" | | coveredDimensionSpacePoint | {} | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date - And The documenturipath projection is up to date Then No node should match URL "/david-nodenborough" And No node should match URL "/david-nodenborough/earl-document" And The node "sir-david-nodenborough" in content stream "cs-identifier" and dimension "{}" should resolve to URL "/david-nodenborough" @@ -112,8 +105,6 @@ Feature: Routing behavior of removed, disabled and re-enabled nodes | nodeAggregateId | "sir-david-nodenborough" | | coveredDimensionSpacePoint | {} | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date - And The documenturipath projection is up to date When I am on URL "/david-nodenborough" Then the matched node should be "sir-david-nodenborough" in content stream "cs-identifier" and dimension "{}" And No node should match URL "/david-nodenborough/earl-document" @@ -131,8 +122,6 @@ Feature: Routing behavior of removed, disabled and re-enabled nodes | nodeAggregateId | "earl-o-documentbourgh" | | coveredDimensionSpacePoint | {} | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date - And The documenturipath projection is up to date Then No node should match URL "/david-nodenborough" And No node should match URL "/david-nodenborough/earl-document" And The node "sir-david-nodenborough" in content stream "cs-identifier" and dimension "{}" should resolve to URL "/david-nodenborough" @@ -142,8 +131,6 @@ Feature: Routing behavior of removed, disabled and re-enabled nodes | nodeAggregateId | "earl-o-documentbourgh" | | coveredDimensionSpacePoint | {} | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date - And The documenturipath projection is up to date Then No node should match URL "/david-nodenborough" And No node should match URL "/david-nodenborough/earl-document" And The node "sir-david-nodenborough" in content stream "cs-identifier" and dimension "{}" should resolve to URL "/david-nodenborough" @@ -161,8 +148,6 @@ Feature: Routing behavior of removed, disabled and re-enabled nodes | nodeAggregateId | "sir-david-nodenborough" | | affectedDimensionSpacePoints | [{}] | | tag | "disabled" | - And the graph projection is fully up to date - And The documenturipath projection is up to date Then No node should match URL "/david-nodenborough" And No node should match URL "/david-nodenborough/earl-document" And The node "sir-david-nodenborough" in content stream "cs-identifier" and dimension "{}" should resolve to URL "/david-nodenborough" @@ -172,8 +157,6 @@ Feature: Routing behavior of removed, disabled and re-enabled nodes | nodeAggregateId | "sir-david-nodenborough" | | coveredDimensionSpacePoint | {} | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date - And The documenturipath projection is up to date When I am on URL "/david-nodenborough" Then the matched node should be "sir-david-nodenborough" in content stream "cs-identifier" and dimension "{}" And The node "sir-david-nodenborough" in content stream "cs-identifier" and dimension "{}" should resolve to URL "/david-nodenborough" @@ -191,8 +174,6 @@ Feature: Routing behavior of removed, disabled and re-enabled nodes | nodeAggregateId | "earl-o-documentbourgh" | | affectedDimensionSpacePoints | [{}] | | tag | "disabled" | - And the graph projection is fully up to date - And The documenturipath projection is up to date Then No node should match URL "/david-nodenborough" And No node should match URL "/david-nodenborough/earl-document" And The node "sir-david-nodenborough" in content stream "cs-identifier" and dimension "{}" should resolve to URL "/david-nodenborough" @@ -208,8 +189,6 @@ Feature: Routing behavior of removed, disabled and re-enabled nodes | nodeAggregateId | "sir-david-nodenborough" | | affectedDimensionSpacePoints | [{}] | | tag | "disabled" | - And the graph projection is fully up to date - And The documenturipath projection is up to date When I am on URL "/david-nodenborough" Then the matched node should be "sir-david-nodenborough" in content stream "cs-identifier" and dimension "{}" And The node "sir-david-nodenborough" in content stream "cs-identifier" and dimension "{}" should resolve to URL "/david-nodenborough" @@ -221,14 +200,12 @@ Feature: Routing behavior of removed, disabled and re-enabled nodes | nodeAggregateId | "sir-david-nodenborough" | | coveredDimensionSpacePoint | {} | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date When the command MoveNodeAggregate is executed with payload: | Key | Value | | nodeAggregateId | "earl-o-documentbourgh" | | dimensionSpacePoint | {} | | newParentNodeAggregateId | "nody-mc-nodeface" | | newSucceedingSiblingNodeAggregateId | null | - And The documenturipath projection is up to date When I am on URL "/nody/earl-document" Then the matched node should be "earl-o-documentbourgh" in content stream "cs-identifier" and dimension "{}" @@ -238,14 +215,12 @@ Feature: Routing behavior of removed, disabled and re-enabled nodes | nodeAggregateId | "earl-o-documentbourgh" | | coveredDimensionSpacePoint | {} | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date When the command MoveNodeAggregate is executed with payload: | Key | Value | | nodeAggregateId | "earl-o-documentbourgh" | | dimensionSpacePoint | {} | | newParentNodeAggregateId | "nody-mc-nodeface" | | newSucceedingSiblingNodeAggregateId | null | - And The documenturipath projection is up to date Then No node should match URL "/nody/earl-document" And The node "leaf-mc-node" in content stream "cs-identifier" and dimension "{}" should resolve to URL "/nody/earl-document/leaf" @@ -255,11 +230,9 @@ Feature: Routing behavior of removed, disabled and re-enabled nodes | nodeAggregateId | "nody-mc-nodeface" | | coveredDimensionSpacePoint | {} | | nodeVariantSelectionStrategy | "allVariants" | - And the graph projection is fully up to date When the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | parentNodeAggregateId | nodeTypeName | initialPropertyValues | | nody-mc-nodeface-child | nody-mc-nodeface | Neos.Neos:Test.Routing.Page | {"uriPathSegment": "nody-child"} | - And The documenturipath projection is up to date When the command EnableNodeAggregate is executed with payload: | Key | Value | | nodeAggregateId | "nody-mc-nodeface" | diff --git a/Neos.Neos/Tests/Behavior/Features/FrontendRouting/Lowlevel_ProjectionTests.feature b/Neos.Neos/Tests/Behavior/Features/FrontendRouting/Lowlevel_ProjectionTests.feature index 2ca042c1632..b83d1edad68 100644 --- a/Neos.Neos/Tests/Behavior/Features/FrontendRouting/Lowlevel_ProjectionTests.feature +++ b/Neos.Neos/Tests/Behavior/Features/FrontendRouting/Lowlevel_ProjectionTests.feature @@ -44,7 +44,6 @@ Feature: Low level tests covering the inner behavior of the routing projection | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.Neos:Sites" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | parentNodeAggregateId | nodeTypeName | initialPropertyValues | nodeName | @@ -53,7 +52,6 @@ Feature: Low level tests covering the inner behavior of the routing projection | b | shernode-homes | Neos.Neos:Test.Routing.Page | {"uriPathSegment": "b"} | b | | c | shernode-homes | Neos.Neos:Test.Routing.Page | {"uriPathSegment": "c"} | c | And A site exists for node name "site" - And The documenturipath projection is up to date Scenario: initial state Then I expect the documenturipath table to contain exactly: @@ -71,7 +69,6 @@ Feature: Low level tests covering the inner behavior of the routing projection | dimensionSpacePoint | {} | | newParentNodeAggregateId | null | | newSucceedingSiblingNodeAggregateId | null | - And The documenturipath projection is up to date Then I expect the documenturipath table to contain exactly: | uripath | nodeaggregateidpath | nodeaggregateid | parentnodeaggregateid | precedingnodeaggregateid | succeedingnodeaggregateid | nodetypename | | "" | "lady-eleonode-rootford" | "lady-eleonode-rootford" | null | null | null | "Neos.Neos:Sites" | @@ -87,7 +84,6 @@ Feature: Low level tests covering the inner behavior of the routing projection | dimensionSpacePoint | {} | | newParentNodeAggregateId | null | | newSucceedingSiblingNodeAggregateId | "b" | - And The documenturipath projection is up to date Then I expect the documenturipath table to contain exactly: | uripath | nodeaggregateidpath | nodeaggregateid | parentnodeaggregateid | precedingnodeaggregateid | succeedingnodeaggregateid | nodetypename | | "" | "lady-eleonode-rootford" | "lady-eleonode-rootford" | null | null | null | "Neos.Neos:Sites" | @@ -103,7 +99,6 @@ Feature: Low level tests covering the inner behavior of the routing projection | dimensionSpacePoint | {} | | newParentNodeAggregateId | null | | newSucceedingSiblingNodeAggregateId | "a" | - And The documenturipath projection is up to date Then I expect the documenturipath table to contain exactly: | uripath | nodeaggregateidpath | nodeaggregateid | parentnodeaggregateid | precedingnodeaggregateid | succeedingnodeaggregateid | nodetypename | | "" | "lady-eleonode-rootford" | "lady-eleonode-rootford" | null | null | null | "Neos.Neos:Sites" | @@ -119,7 +114,6 @@ Feature: Low level tests covering the inner behavior of the routing projection | dimensionSpacePoint | {} | | newParentNodeAggregateId | null | | newSucceedingSiblingNodeAggregateId | "c" | - And The documenturipath projection is up to date Then I expect the documenturipath table to contain exactly: | uripath | nodeaggregateidpath | nodeaggregateid | parentnodeaggregateid | precedingnodeaggregateid | succeedingnodeaggregateid | nodetypename | | "" | "lady-eleonode-rootford" | "lady-eleonode-rootford" | null | null | null | "Neos.Neos:Sites" | @@ -135,7 +129,6 @@ Feature: Low level tests covering the inner behavior of the routing projection | dimensionSpacePoint | {} | | newParentNodeAggregateId | null | | newSucceedingSiblingNodeAggregateId | null | - And The documenturipath projection is up to date Then I expect the documenturipath table to contain exactly: | uripath | nodeaggregateidpath | nodeaggregateid | parentnodeaggregateid | precedingnodeaggregateid | succeedingnodeaggregateid | nodetypename | | "" | "lady-eleonode-rootford" | "lady-eleonode-rootford" | null | null | null | "Neos.Neos:Sites" | @@ -151,14 +144,12 @@ Feature: Low level tests covering the inner behavior of the routing projection | dimensionSpacePoint | {} | | newParentNodeAggregateId | null | | newSucceedingSiblingNodeAggregateId | "a" | - And the graph projection is fully up to date And the command MoveNodeAggregate is executed with payload: | Key | Value | | nodeAggregateId | "c" | | dimensionSpacePoint | {} | | newParentNodeAggregateId | null | | newSucceedingSiblingNodeAggregateId | "a" | - And The documenturipath projection is up to date Then I expect the documenturipath table to contain exactly: | uripath | nodeaggregateidpath | nodeaggregateid | parentnodeaggregateid | precedingnodeaggregateid | succeedingnodeaggregateid | nodetypename | | "" | "lady-eleonode-rootford" | "lady-eleonode-rootford" | null | null | null | "Neos.Neos:Sites" | @@ -174,7 +165,6 @@ Feature: Low level tests covering the inner behavior of the routing projection | dimensionSpacePoint | {} | | newParentNodeAggregateId | "a" | | newSucceedingSiblingNodeAggregateId | null | - And The documenturipath projection is up to date Then I expect the documenturipath table to contain exactly: | uripath | nodeaggregateidpath | nodeaggregateid | parentnodeaggregateid | precedingnodeaggregateid | succeedingnodeaggregateid | nodetypename | | "" | "lady-eleonode-rootford" | "lady-eleonode-rootford" | null | null | null | "Neos.Neos:Sites" | @@ -192,14 +182,12 @@ Feature: Low level tests covering the inner behavior of the routing projection | parentNodeAggregateId | "b" | | initialPropertyValues | {"uriPathSegment": "b1"} | | succeedingSiblingNodeAggregateId | null | - And the graph projection is fully up to date And the command MoveNodeAggregate is executed with payload: | Key | Value | | nodeAggregateId | "b" | | dimensionSpacePoint | {} | | newParentNodeAggregateId | "a" | | newSucceedingSiblingNodeAggregateId | null | - And The documenturipath projection is up to date Then I expect the documenturipath table to contain exactly: | uripath | nodeaggregateidpath | nodeaggregateid | parentnodeaggregateid | precedingnodeaggregateid | succeedingnodeaggregateid | nodetypename | | "" | "lady-eleonode-rootford" | "lady-eleonode-rootford" | null | null | null | "Neos.Neos:Sites" | @@ -218,14 +206,12 @@ Feature: Low level tests covering the inner behavior of the routing projection | parentNodeAggregateId | "b" | | initialPropertyValues | {"uriPathSegment": "b1"} | | succeedingSiblingNodeAggregateId | null | - And the graph projection is fully up to date And the command MoveNodeAggregate is executed with payload: | Key | Value | | nodeAggregateId | "b1" | | dimensionSpacePoint | {} | | newParentNodeAggregateId | "a" | | newSucceedingSiblingNodeAggregateId | null | - And The documenturipath projection is up to date Then I expect the documenturipath table to contain exactly: | uripath | nodeaggregateidpath | nodeaggregateid | parentnodeaggregateid | precedingnodeaggregateid | succeedingnodeaggregateid | nodetypename | | "" | "lady-eleonode-rootford" | "lady-eleonode-rootford" | null | null | null | "Neos.Neos:Sites" | @@ -248,7 +234,6 @@ Feature: Low level tests covering the inner behavior of the routing projection | dimensionSpacePoint | {} | | newParentNodeAggregateId | "a" | | newSucceedingSiblingNodeAggregateId | null | - And The documenturipath projection is up to date Then I expect the documenturipath table to contain exactly: | uripath | nodeaggregateidpath | nodeaggregateid | parentnodeaggregateid | precedingnodeaggregateid | succeedingnodeaggregateid | nodetypename | | "" | "lady-eleonode-rootford" | "lady-eleonode-rootford" | null | null | null | "Neos.Neos:Sites" | @@ -273,7 +258,6 @@ Feature: Low level tests covering the inner behavior of the routing projection | dimensionSpacePoint | {} | | newParentNodeAggregateId | "b" | | newSucceedingSiblingNodeAggregateId | "b2" | - And The documenturipath projection is up to date Then I expect the documenturipath table to contain exactly: | uripath | nodeaggregateidpath | nodeaggregateid | parentnodeaggregateid | precedingnodeaggregateid | succeedingnodeaggregateid | nodetypename | | "" | "lady-eleonode-rootford" | "lady-eleonode-rootford" | null | null | null | "Neos.Neos:Sites" | @@ -291,7 +275,6 @@ Feature: Low level tests covering the inner behavior of the routing projection | nodeAggregateId | "c" | | newNodeTypeName | "Neos.Neos:Test.Routing.SomeOtherPage" | | strategy | "happypath" | - And The documenturipath projection is up to date Then I expect the documenturipath table to contain exactly: | uripath | nodeaggregateidpath | nodeaggregateid | parentnodeaggregateid | precedingnodeaggregateid | succeedingnodeaggregateid | nodetypename | | "" | "lady-eleonode-rootford" | "lady-eleonode-rootford" | null | null | null | "Neos.Neos:Sites" | diff --git a/Neos.Neos/Tests/Behavior/Features/FrontendRouting/MultiSiteLinking.feature b/Neos.Neos/Tests/Behavior/Features/FrontendRouting/MultiSiteLinking.feature index b054eb1f25d..e7f77e89947 100644 --- a/Neos.Neos/Tests/Behavior/Features/FrontendRouting/MultiSiteLinking.feature +++ b/Neos.Neos/Tests/Behavior/Features/FrontendRouting/MultiSiteLinking.feature @@ -44,7 +44,6 @@ Feature: Linking between multiple websites | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.Neos:Sites" | - And the graph projection is fully up to date # lady-eleonode-rootford # shernode-homes @@ -71,7 +70,6 @@ Feature: Linking between multiple websites resolver: factoryClassName: Neos\Neos\FrontendRouting\DimensionResolution\Resolver\NoopResolverFactory """ - And The documenturipath projection is up to date Scenario: Resolve foreign website homepage node When I am on URL "http://domain1.tld/" diff --git a/Neos.Neos/Tests/Behavior/Features/FrontendRouting/RouteCache.feature b/Neos.Neos/Tests/Behavior/Features/FrontendRouting/RouteCache.feature index 046c965289e..c4ae47031e4 100644 --- a/Neos.Neos/Tests/Behavior/Features/FrontendRouting/RouteCache.feature +++ b/Neos.Neos/Tests/Behavior/Features/FrontendRouting/RouteCache.feature @@ -35,7 +35,6 @@ Feature: Route cache invalidation | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.Neos:Sites" | - And the graph projection is fully up to date # lady-eleonode-rootford # shernode-homes @@ -64,7 +63,6 @@ Feature: Route cache invalidation resolver: factoryClassName: Neos\Neos\FrontendRouting\DimensionResolution\Resolver\NoopResolverFactory """ - And The documenturipath projection is up to date Scenario: Change uri path segment invalidates route cache When I am on URL "/" @@ -75,7 +73,6 @@ Feature: Route cache invalidation | nodeAggregateId | "sir-david-nodenborough" | | originDimensionSpacePoint | {} | | propertyValues | {"uriPathSegment": "david-nodenborough-updated"} | - And The documenturipath projection is up to date Then No node should match URL "/david-nodenborough" And No node should match URL "/david-nodenborough/earl-document" @@ -89,13 +86,11 @@ Feature: Route cache invalidation | nodeAggregateId | "sir-david-nodenborough" | | originDimensionSpacePoint | {} | | propertyValues | {"uriPathSegment": "david-nodenborough-updated-a"} | - And The documenturipath projection is up to date When the command SetNodeProperties is executed with payload: | Key | Value | | nodeAggregateId | "sir-david-nodenborough" | | originDimensionSpacePoint | {} | | propertyValues | {"uriPathSegment": "david-nodenborough-updated-b"} | - And The documenturipath projection is up to date Then No node should match URL "/david-nodenborough" And No node should match URL "/david-nodenborough/earl-document" @@ -114,7 +109,6 @@ Feature: Route cache invalidation | dimensionSpacePoint | {} | | newParentNodeAggregateId | "shernode-homes" | | newSucceedingSiblingNodeAggregateId | null | - And The documenturipath projection is up to date Then No node should match URL "/david-nodenborough/earl-document" @@ -128,7 +122,6 @@ Feature: Route cache invalidation | dimensionSpacePoint | {} | | newParentNodeAggregateId | "earl-o-documentbourgh" | | newSucceedingSiblingNodeAggregateId | null | - And The documenturipath projection is up to date Then No node should match URL "/nody" @@ -142,7 +135,6 @@ Feature: Route cache invalidation | nodeAggregateId | "sir-david-nodenborough" | | coveredDimensionSpacePoint | {} | | nodeVariantSelectionStrategy | "allVariants" | - And The documenturipath projection is up to date Then No node should match URL "/david-nodenborough" And No node should match URL "/david-nodenborough/earl-document" @@ -158,7 +150,6 @@ Feature: Route cache invalidation | nodeAggregateId | "sir-david-nodenborough" | | coveredDimensionSpacePoint | {} | | nodeVariantSelectionStrategy | "allVariants" | - And The documenturipath projection is up to date Then No node should match URL "/david-nodenborough" And No node should match URL "/david-nodenborough/earl-document" diff --git a/Neos.Neos/Tests/Behavior/Features/FrontendRouting/Shortcuts.feature b/Neos.Neos/Tests/Behavior/Features/FrontendRouting/Shortcuts.feature index 8b315048502..21df312f31c 100644 --- a/Neos.Neos/Tests/Behavior/Features/FrontendRouting/Shortcuts.feature +++ b/Neos.Neos/Tests/Behavior/Features/FrontendRouting/Shortcuts.feature @@ -52,7 +52,6 @@ Feature: Routing behavior of shortcut nodes | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.Neos:Sites" | - And the graph projection is fully up to date # lady-eleonode-rootford # shernode-homes @@ -93,7 +92,6 @@ Feature: Routing behavior of shortcut nodes resolver: factoryClassName: Neos\Neos\FrontendRouting\DimensionResolution\Resolver\NoopResolverFactory """ - And The documenturipath projection is up to date Scenario: Shortcut parent node When I am on URL "/" @@ -118,7 +116,6 @@ Feature: Routing behavior of shortcut nodes | nodeAggregateId | "shortcut-external-url" | | originDimensionSpacePoint | {} | | propertyValues | {"target": "/some/relative/url"} | - And The documenturipath projection is up to date When I am on URL "https://current.host/" Then the node "shortcut-external-url" in content stream "cs-identifier" and dimension "{}" should resolve to URL "/some/relative/url" @@ -128,7 +125,6 @@ Feature: Routing behavior of shortcut nodes | nodeAggregateId | "shortcut-external-url" | | originDimensionSpacePoint | {} | | propertyValues | {"target": "https://www.some-domain.tld:1234/some/url/path?some=query#some-fragment"} | - And The documenturipath projection is up to date When I am on URL "http://current.host/" Then the node "shortcut-external-url" in content stream "cs-identifier" and dimension "{}" should resolve to URL "https://www.some-domain.tld:1234/some/url/path?some=query#some-fragment" @@ -145,7 +141,6 @@ Feature: Routing behavior of shortcut nodes | parentNodeAggregateId | "shortcut-first-child-node" | | initialPropertyValues | {"uriPathSegment": "new-child-node"} | | succeedingSiblingNodeAggregateId | "first-child-node" | - And The documenturipath projection is up to date When I am on URL "/" Then the node "shortcut-first-child-node" in content stream "cs-identifier" and dimension "{}" should resolve to URL "/david-nodenborough/shortcuts/shortcut-first-child/new-child-node" @@ -156,7 +151,6 @@ Feature: Routing behavior of shortcut nodes | dimensionSpacePoint | {} | | newParentNodeAggregateId | "shortcut-first-child-node" | | newSucceedingSiblingNodeAggregateId | "first-child-node" | - And The documenturipath projection is up to date When I am on URL "/" Then the node "shortcut-first-child-node" in content stream "cs-identifier" and dimension "{}" should resolve to URL "/david-nodenborough/shortcuts/shortcut-first-child/nodeward-3" @@ -167,7 +161,6 @@ Feature: Routing behavior of shortcut nodes | dimensionSpacePoint | {} | | newParentNodeAggregateId | null | | newSucceedingSiblingNodeAggregateId | "first-child-node" | - And The documenturipath projection is up to date When I am on URL "/" Then the node "shortcut-first-child-node" in content stream "cs-identifier" and dimension "{}" should resolve to URL "/david-nodenborough/shortcuts/shortcut-first-child/second-child-node" @@ -178,7 +171,6 @@ Feature: Routing behavior of shortcut nodes | dimensionSpacePoint | {} | | newParentNodeAggregateId | "shortcut-first-child-node" | | newSucceedingSiblingNodeAggregateId | "second-child-node" | - And The documenturipath projection is up to date When I am on URL "/" Then the node "shortcut-first-child-node" in content stream "cs-identifier" and dimension "{}" should resolve to URL "/david-nodenborough/shortcuts/shortcut-first-child/first-child-node" @@ -191,14 +183,12 @@ Feature: Routing behavior of shortcut nodes | parentNodeAggregateId | "shortcut-first-child-node" | | initialPropertyValues | {"uriPathSegment": "new-child-node"} | | succeedingSiblingNodeAggregateId | "second-child-node" | - And the graph projection is fully up to date And the command MoveNodeAggregate is executed with payload: | Key | Value | | nodeAggregateId | "nody-mc-newface" | | dimensionSpacePoint | {} | | newParentNodeAggregateId | null | | newSucceedingSiblingNodeAggregateId | null | - And The documenturipath projection is up to date When I am on URL "/" Then the node "shortcut-first-child-node" in content stream "cs-identifier" and dimension "{}" should resolve to URL "/david-nodenborough/shortcuts/shortcut-first-child/first-child-node" @@ -208,7 +198,6 @@ Feature: Routing behavior of shortcut nodes | nodeAggregateId | "sir-david-nodenborough-ii" | | newNodeTypeName | "Neos.Neos:Shortcut" | | strategy | "happypath" | - And The documenturipath projection is up to date When I am on URL "/" Then the node "sir-david-nodenborough-ii" in content stream "cs-identifier" and dimension "{}" should resolve to URL "/david-nodenborough-2/nodeward-3" @@ -218,7 +207,6 @@ Feature: Routing behavior of shortcut nodes | nodeAggregateId | "shortcut-first-child-node" | | newNodeTypeName | "Neos.Neos:Test.Routing.Page" | | strategy | "happypath" | - And The documenturipath projection is up to date When I am on URL "/" Then the node "shortcut-first-child-node" in content stream "cs-identifier" and dimension "{}" should resolve to URL "/david-nodenborough/shortcuts/shortcut-first-child" @@ -228,7 +216,6 @@ Feature: Routing behavior of shortcut nodes | nodeAggregateId | "shortcut-first-child-node" | | originDimensionSpacePoint | {} | | propertyValues | {"targetMode": "parentNode"} | - And The documenturipath projection is up to date When I am on URL "/" Then the node "shortcut-first-child-node" in content stream "cs-identifier" and dimension "{}" should resolve to URL "/david-nodenborough/shortcuts" @@ -238,7 +225,6 @@ Feature: Routing behavior of shortcut nodes | nodeAggregateId | "shortcut-first-child-node" | | originDimensionSpacePoint | {} | | propertyValues | {"targetMode": "selectedTarget", "target": "http://www.neos.io"} | - And The documenturipath projection is up to date When I am on URL "/" Then the node "shortcut-first-child-node" in content stream "cs-identifier" and dimension "{}" should resolve to URL "http://www.neos.io/" @@ -252,7 +238,6 @@ Feature: Routing behavior of shortcut nodes | nodeAggregateId | "shortcut-parent-node" | | originDimensionSpacePoint | {} | | propertyValues | {"targetMode": "firstChildNode"} | - And The documenturipath projection is up to date When I am on URL "/" Then the node "shortcut-parent-node" in content stream "cs-identifier" and dimension "{}" should resolve to URL "/david-nodenborough/shortcuts/shortcut-parent-node/new-child" @@ -262,7 +247,6 @@ Feature: Routing behavior of shortcut nodes | nodeAggregateId | "shortcut-parent-node" | | originDimensionSpacePoint | {} | | propertyValues | {"targetMode": "selectedTarget", "target": "https://neos.io/"} | - And The documenturipath projection is up to date When I am on URL "/" Then the node "shortcut-parent-node" in content stream "cs-identifier" and dimension "{}" should resolve to URL "https://neos.io/" @@ -275,7 +259,6 @@ Feature: Routing behavior of shortcut nodes | parentNodeAggregateId | "shortcuts" | | initialPropertyValues | {"uriPathSegment": "invalid-target-mode", "targetMode": "invalidMode"} | | nodeName | "some-node-name" | - And The documenturipath projection is up to date When I am on URL "/" Then The node "invalid-target-mode" in content stream "cs-identifier" and dimension "{}" should not resolve to an URL @@ -288,7 +271,6 @@ Feature: Routing behavior of shortcut nodes | parentNodeAggregateId | "shortcuts" | | initialPropertyValues | {"uriPathSegment": "invalid-missing-target", "targetMode": "selectedTarget"} | | nodeName | "some-node-name" | - And The documenturipath projection is up to date When I am on URL "/" Then The node "invalid-missing-target" in content stream "cs-identifier" and dimension "{}" should not resolve to an URL @@ -301,7 +283,6 @@ Feature: Routing behavior of shortcut nodes | parentNodeAggregateId | "shortcuts" | | initialPropertyValues | {"uriPathSegment": "invalid-shortcut-first-child", "targetMode": "firstChildNode"} | | nodeName | "some-node-name" | - And The documenturipath projection is up to date When I am on URL "/" Then The node "invalid-shortcut-first-child-node" in content stream "cs-identifier" and dimension "{}" should not resolve to an URL @@ -314,7 +295,6 @@ Feature: Routing behavior of shortcut nodes | parentNodeAggregateId | "shortcuts" | | initialPropertyValues | {"uriPathSegment": "invalid-shortcut-selected-node", "targetMode": "selectedTarget", "target": "node://non-existing-node"} | | nodeName | "some-node-name" | - And The documenturipath projection is up to date When I am on URL "/" Then The node "invalid-shortcut-selected-node" in content stream "cs-identifier" and dimension "{}" should not resolve to an URL @@ -327,7 +307,6 @@ Feature: Routing behavior of shortcut nodes | parentNodeAggregateId | "shortcuts" | | initialPropertyValues | {"uriPathSegment": "invalid-shortcut-selected-node", "targetMode": "selectedTarget", "target": "node://"} | | nodeName | "some-node-name" | - And The documenturipath projection is up to date When I am on URL "/" Then The node "invalid-shortcut-selected-node" in content stream "cs-identifier" and dimension "{}" should not resolve to an URL @@ -337,7 +316,6 @@ Feature: Routing behavior of shortcut nodes | nodeAggregateId | parentNodeAggregateId | nodeTypeName | initialPropertyValues | nodeName | | level-1 | shortcuts | Neos.Neos:Shortcut | {"uriPathSegment": "level1", "targetMode": "selectedTarget", "target": "node://level-2"} | level1 | | level-2 | shortcuts | Neos.Neos:Shortcut | {"uriPathSegment": "level2", "targetMode": "selectedTarget", "target": "node://shortcut-first-child-node"} | level2 | - And The documenturipath projection is up to date When I am on URL "/" Then the node "level-1" in content stream "cs-identifier" and dimension "{}" should resolve to URL "/david-nodenborough/shortcuts/shortcut-first-child/first-child-node" Then the node "level-2" in content stream "cs-identifier" and dimension "{}" should resolve to URL "/david-nodenborough/shortcuts/shortcut-first-child/first-child-node" @@ -348,6 +326,5 @@ Feature: Routing behavior of shortcut nodes | nodeAggregateId | parentNodeAggregateId | nodeTypeName | initialPropertyValues | nodeName | | node-a | shortcuts | Neos.Neos:Shortcut | {"uriPathSegment": "a", "targetMode": "selectedTarget", "target": "node://node-b"} | node-a | | node-b | shortcuts | Neos.Neos:Shortcut | {"uriPathSegment": "b", "targetMode": "selectedTarget", "target": "node://node-a"} | node-b | - And The documenturipath projection is up to date When I am on URL "/" Then The node "node-a" in content stream "cs-identifier" and dimension "{}" should not resolve to an URL diff --git a/Neos.Neos/Tests/Behavior/Features/FrontendRouting/TetheredSiteChildDocuments.feature b/Neos.Neos/Tests/Behavior/Features/FrontendRouting/TetheredSiteChildDocuments.feature index df5b10e9ccc..22cf90d6e2f 100644 --- a/Neos.Neos/Tests/Behavior/Features/FrontendRouting/TetheredSiteChildDocuments.feature +++ b/Neos.Neos/Tests/Behavior/Features/FrontendRouting/TetheredSiteChildDocuments.feature @@ -35,7 +35,6 @@ Feature: Tests for site node child documents. These are special in that they hav | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.Neos:Sites" | - And the graph projection is fully up to date # We explicitly create a site node with a tethered child document without uriPathSegment, so its uriPath is empty, exactly as the site node's And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | parentNodeAggregateId | nodeTypeName | initialPropertyValues | nodeName | @@ -52,7 +51,6 @@ Feature: Tests for site node child documents. These are special in that they hav resolver: factoryClassName: Neos\Neos\FrontendRouting\DimensionResolution\Resolver\NoopResolverFactory """ - And The documenturipath projection is up to date Scenario: Set tethered child uriPathSegment When I remember NodeAggregateId of node "shernode-homes"s child "notFound" as "notFoundId" @@ -60,8 +58,6 @@ Feature: Tests for site node child documents. These are special in that they hav | Key | Value | | nodeAggregateId | "$notFoundId" | | propertyValues | {"uriPathSegment": "not-found"} | - And the graph projection is fully up to date - And The documenturipath projection is up to date And I am on URL "/" Then the matched node should be "shernode-homes" in content stream "cs-identifier" and dimension "{}" And the node "$notFoundId" in content stream "cs-identifier" and dimension "{}" should resolve to URL "/not-found" diff --git a/Neos.Neos/Tests/Behavior/Features/FrontendRouting/UnknownNodeTypes.feature b/Neos.Neos/Tests/Behavior/Features/FrontendRouting/UnknownNodeTypes.feature index 7923dac5f9e..7cc38b3f551 100644 --- a/Neos.Neos/Tests/Behavior/Features/FrontendRouting/UnknownNodeTypes.feature +++ b/Neos.Neos/Tests/Behavior/Features/FrontendRouting/UnknownNodeTypes.feature @@ -29,7 +29,6 @@ Feature: Basic routing functionality (match & resolve nodes with unknown types) | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.Neos:Sites" | - And the graph projection is fully up to date Scenario: When the event NodeAggregateWithNodeWasCreated was published with payload: @@ -55,7 +54,6 @@ Feature: Basic routing functionality (match & resolve nodes with unknown types) | parentNodeAggregateId | "shernode-homes" | | nodeAggregateClassification | "regular" | | initialPropertyValues | {"uriPathSegment": {"type": "string", "value": "non-existing"}} | - And The documenturipath projection is up to date Then I expect the documenturipath table to contain exactly: | uripath | nodeaggregateidpath | nodeaggregateid | parentnodeaggregateid | precedingnodeaggregateid | succeedingnodeaggregateid | nodetypename | | "" | "lady-eleonode-rootford" | "lady-eleonode-rootford" | null | null | null | "Neos.Neos:Sites" | diff --git a/Neos.Neos/Tests/Behavior/Features/Fusion/ContentCase.feature b/Neos.Neos/Tests/Behavior/Features/Fusion/ContentCase.feature index d73a80cf0cf..e9ca0ebbe78 100644 --- a/Neos.Neos/Tests/Behavior/Features/Fusion/ContentCase.feature +++ b/Neos.Neos/Tests/Behavior/Features/Fusion/ContentCase.feature @@ -38,7 +38,6 @@ Feature: Tests for the "Neos.Neos:ContentCase" Fusion prototype | Key | Value | | nodeAggregateId | "root" | | nodeTypeName | "Neos.Neos:Sites" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | parentNodeAggregateId | nodeTypeName | | a | root | Neos.Neos:Site | diff --git a/Neos.Neos/Tests/Behavior/Features/Fusion/ContentCollection.feature b/Neos.Neos/Tests/Behavior/Features/Fusion/ContentCollection.feature index f68a96cf08b..f04d655b439 100644 --- a/Neos.Neos/Tests/Behavior/Features/Fusion/ContentCollection.feature +++ b/Neos.Neos/Tests/Behavior/Features/Fusion/ContentCollection.feature @@ -46,7 +46,6 @@ Feature: Tests for the "Neos.Neos:ContentCollection" Fusion prototype | Key | Value | | nodeAggregateId | "root" | | nodeTypeName | "Neos.Neos:Sites" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | parentNodeAggregateId | nodeTypeName | | a | root | Neos.Neos:Site | @@ -116,7 +115,6 @@ Feature: Tests for the "Neos.Neos:ContentCollection" Fusion prototype | parentNodeAggregateId | "a" | | initialPropertyValues | {} | | tetheredDescendantNodeAggregateIds | { "main": "a1-main"} | - And the graph projection is fully up to date When the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | parentNodeAggregateId | nodeTypeName | | content1 | a1-main | Neos.Neos:Test.ContentType | diff --git a/Neos.Neos/Tests/Behavior/Features/Fusion/ConvertUris.feature b/Neos.Neos/Tests/Behavior/Features/Fusion/ConvertUris.feature index fccf8d719b6..8b7a4666b9b 100644 --- a/Neos.Neos/Tests/Behavior/Features/Fusion/ConvertUris.feature +++ b/Neos.Neos/Tests/Behavior/Features/Fusion/ConvertUris.feature @@ -35,7 +35,6 @@ Feature: Tests for the "Neos.Neos:ConvertUris" Fusion prototype | Key | Value | | nodeAggregateId | "root" | | nodeTypeName | "Neos.Neos:Sites" | - And the graph projection is fully up to date And I am in content stream "cs-identifier" and dimension space point {} And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | parentNodeAggregateId | nodeTypeName |initialPropertyValues | nodeName | diff --git a/Neos.Neos/Tests/Behavior/Features/Fusion/FlowQuery.feature b/Neos.Neos/Tests/Behavior/Features/Fusion/FlowQuery.feature index b7073940274..6b307360c54 100644 --- a/Neos.Neos/Tests/Behavior/Features/Fusion/FlowQuery.feature +++ b/Neos.Neos/Tests/Behavior/Features/Fusion/FlowQuery.feature @@ -51,7 +51,6 @@ Feature: Tests for the "Neos.ContentRepository" Flow Query methods. | Key | Value | | nodeAggregateId | "root" | | nodeTypeName | "Neos.Neos:Sites" | - And the graph projection is fully up to date And I am in content stream "cs-identifier" and dimension space point {} And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | parentNodeAggregateId | nodeTypeName | initialPropertyValues | nodeName | diff --git a/Neos.Neos/Tests/Behavior/Features/Fusion/Menu.feature b/Neos.Neos/Tests/Behavior/Features/Fusion/Menu.feature index d137b1b77ec..86ef666f74f 100644 --- a/Neos.Neos/Tests/Behavior/Features/Fusion/Menu.feature +++ b/Neos.Neos/Tests/Behavior/Features/Fusion/Menu.feature @@ -51,7 +51,6 @@ Feature: Tests for the "Neos.Neos:Menu" and related Fusion prototypes | Key | Value | | nodeAggregateId | "root" | | nodeTypeName | "Neos.Neos:Sites" | - And the graph projection is fully up to date And the following CreateNodeAggregateWithNode commands are executed: | nodeAggregateId | parentNodeAggregateId | nodeTypeName | initialPropertyValues | nodeName | | a | root | Neos.Neos:Site | {"title": "Node a"} | a | diff --git a/Neos.TimeableNodeVisibility/Tests/Behavior/Bootstrap/FeatureContext.php b/Neos.TimeableNodeVisibility/Tests/Behavior/Bootstrap/FeatureContext.php index 66f948b239f..4147c5d274c 100644 --- a/Neos.TimeableNodeVisibility/Tests/Behavior/Bootstrap/FeatureContext.php +++ b/Neos.TimeableNodeVisibility/Tests/Behavior/Bootstrap/FeatureContext.php @@ -38,8 +38,6 @@ public function __construct() { self::bootstrapFlow(); $this->contentRepositoryRegistry = $this->getObject(ContentRepositoryRegistry::class); - - $this->setupCRTestSuiteTrait(); } /** diff --git a/Neos.TimeableNodeVisibility/Tests/Behavior/Features/HandleExceeded.feature b/Neos.TimeableNodeVisibility/Tests/Behavior/Features/HandleExceeded.feature index 845bb8fc66c..cf51fd79279 100644 --- a/Neos.TimeableNodeVisibility/Tests/Behavior/Features/HandleExceeded.feature +++ b/Neos.TimeableNodeVisibility/Tests/Behavior/Features/HandleExceeded.feature @@ -31,14 +31,12 @@ Feature: Simple handling of nodes with exceeded enableAfter and disableAfter dat | Key | Value | | workspaceName | "live" | | newContentStreamId | "cs-identifier" | - And the graph projection is fully up to date And I am in workspace "live" And I am in the active content stream of workspace "live" and dimension space point {} And the command CreateRootNodeAggregateWithNode is executed with payload: | Key | Value | | nodeAggregateId | "lady-eleonode-rootford" | | nodeTypeName | "Neos.Neos:Sites" | - And the graph projection is fully up to date # <===========================|now|===========================> diff --git a/composer.json b/composer.json index b17ad9c3d79..e30391801bd 100644 --- a/composer.json +++ b/composer.json @@ -19,6 +19,8 @@ "psr/clock": "^1", "behat/transliterator": "~1.0", "ramsey/uuid": "^3.0 || ^4.0", + "react/promise": "^3.1", + "react/async": "^v4.2", "league/flysystem": "^3", "webmozart/assert": "^1.11", "neos/flow": "*", From 99cd1e0e0f0bb093a581e7f7344d393c880381b9 Mon Sep 17 00:00:00 2001 From: Bastian Waidelich Date: Fri, 12 Apr 2024 18:42:35 +0200 Subject: [PATCH 02/21] Remove `react/async` dependency as discussed in todays weekly --- .../src/DoctrineDbalContentGraphProjection.php | 7 ++----- .../Domain/Projection/HypergraphProjection.php | 9 ++------- .../Classes/ContentRepository.php | 17 ++++++----------- .../ContentGraph/ContentGraphProjection.php | 9 ++++----- .../ContentStream/ContentStreamProjection.php | 11 +++-------- .../Classes/Projection/ProjectionInterface.php | 11 ++--------- .../Workspace/WorkspaceProjection.php | 6 ++---- Neos.ContentRepository.Core/composer.json | 4 +--- .../Projection/AssetUsageProjection.php | 7 ++----- .../Projection/DocumentUriPathProjection.php | 9 ++------- .../ChangeProjection.php | 9 ++------- 11 files changed, 28 insertions(+), 71 deletions(-) diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php index 2f9b00fe47d..12fce3e8f42 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php @@ -62,7 +62,6 @@ use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; use Neos\EventStore\Model\Event\SequenceNumber; use Neos\EventStore\Model\EventEnvelope; -use React\Promise\PromiseInterface; use function React\Promise\resolve; @@ -161,7 +160,7 @@ public function status(): ProjectionStatus return ProjectionStatus::ok(); } - public function reset(): PromiseInterface + public function reset(): void { $this->truncateDatabaseTables(); @@ -172,7 +171,6 @@ public function reset(): PromiseInterface foreach ($contentGraph->getSubgraphs() as $subgraph) { $subgraph->inMemoryCache->enable(); } - return resolve(null); } private function truncateDatabaseTables(): void @@ -184,7 +182,7 @@ private function truncateDatabaseTables(): void $connection->executeQuery('TRUNCATE table ' . $this->tableNamePrefix . '_dimensionspacepoints'); } - public function apply(EventInterface $event, EventEnvelope $eventEnvelope): PromiseInterface + public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void { match ($event::class) { RootNodeAggregateWithNodeWasCreated::class => $this->whenRootNodeAggregateWithNodeWasCreated($event, $eventEnvelope), @@ -207,7 +205,6 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): Prom SubtreeWasUntagged::class => $this->whenSubtreeWasUntagged($event), default => null, }; - return resolve(null); } public function getCheckpointStorage(): DbalCheckpointStorage diff --git a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/HypergraphProjection.php b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/HypergraphProjection.php index 68d5e6b103c..64560bf61b1 100644 --- a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/HypergraphProjection.php +++ b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/HypergraphProjection.php @@ -52,9 +52,6 @@ use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId; use Neos\EventStore\Model\Event\SequenceNumber; use Neos\EventStore\Model\EventEnvelope; -use React\Promise\PromiseInterface; - -use function React\Promise\resolve; /** * The alternate reality-aware hypergraph projector for the PostgreSQL backend via Doctrine DBAL @@ -156,7 +153,7 @@ private function determineRequiredSqlStatements(): array return DbalSchemaDiff::determineRequiredSqlStatements($connection, $schema); } - public function reset(): PromiseInterface + public function reset(): void { $this->truncateDatabaseTables(); @@ -167,7 +164,6 @@ public function reset(): PromiseInterface //foreach ($contentGraph->getSubgraphs() as $subgraph) { // $subgraph->inMemoryCache->enable(); //} - return resolve(null); } private function truncateDatabaseTables(): void @@ -179,7 +175,7 @@ private function truncateDatabaseTables(): void $connection->executeQuery('TRUNCATE table ' . $this->tableNamePrefix . '_restrictionhyperrelation'); } - public function apply(EventInterface $event, EventEnvelope $eventEnvelope): PromiseInterface + public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void { match ($event::class) { // ContentStreamForking @@ -206,7 +202,6 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): Prom NodePeerVariantWasCreated::class => $this->whenNodePeerVariantWasCreated($event), default => null, }; - return resolve(null); } public function getCheckpointStorage(): DbalCheckpointStorage diff --git a/Neos.ContentRepository.Core/Classes/ContentRepository.php b/Neos.ContentRepository.Core/Classes/ContentRepository.php index 18f0d132b2f..80cf2e01771 100644 --- a/Neos.ContentRepository.Core/Classes/ContentRepository.php +++ b/Neos.ContentRepository.Core/Classes/ContentRepository.php @@ -188,24 +188,19 @@ public function catchUpProjections(): void foreach ($eventStream as $eventEnvelope) { #\Neos\Flow\var_dump('EVENT ' . $eventEnvelope->event->type->value); $event = $this->eventNormalizer->denormalize($eventEnvelope->event); - $futures = []; /** @var array{projection: ProjectionInterface, catchUpHook: CatchUpHookInterface|null} $projectionAndCatchUpHook */ foreach ($projectionsAndCatchUpHooks as $projectionClassName => $projectionAndCatchUpHook) { #$projectionAndCatchUpHook['catchUpHook']?->onBeforeEvent($event, $eventEnvelope); #\Neos\Flow\var_dump('APPLY ' . $eventEnvelope->event->type->value . ' (' . $eventEnvelope->sequenceNumber->value . ') TO ' . $projectionClassName); #$futures[] = function () => $projectionAndCatchUpHook['projection']->apply($event, $eventEnvelope); #$projectionAndCatchUpHook['catchUpHook']?->onAfterEvent($event, $eventEnvelope); - $futures[] = function () use ($projectionAndCatchUpHook, $event, $eventEnvelope) { - $projectionAndCatchUpHook['catchUpHook']?->onBeforeEvent($event, $eventEnvelope); - #\Neos\Flow\var_dump('APPLY ' . $eventEnvelope->event->type->value . ' (' . $eventEnvelope->sequenceNumber->value . ') TO ' . $projectionClassName); - $promise = $projectionAndCatchUpHook['projection']->apply($event, $eventEnvelope); - $projectionAndCatchUpHook['catchUpHook']?->onAfterEvent($event, $eventEnvelope); - return $promise; - }; + $projectionAndCatchUpHook['catchUpHook']?->onBeforeEvent($event, $eventEnvelope); + #\Neos\Flow\var_dump('APPLY ' . $eventEnvelope->event->type->value . ' (' . $eventEnvelope->sequenceNumber->value . ') TO ' . $projectionClassName); + $projectionAndCatchUpHook['projection']->apply($event, $eventEnvelope); + $projectionAndCatchUpHook['catchUpHook']?->onAfterEvent($event, $eventEnvelope); #$projectionAndCatchUpHook['projection']->getCheckpointStorage()->updateAndReleaseLock($eventEnvelope->sequenceNumber); #\Neos\Flow\var_dump('UPDATE CHECKPOINT for ' . $projectionClassName . ' to ' . $eventEnvelope->sequenceNumber->value); } - await(parallel($futures)); } assert($eventEnvelope instanceof EventEnvelope); /** @var array{projection: ProjectionInterface, catchUpHook: CatchUpHookInterface|null} $projectionAndCatchUpHook */ @@ -279,7 +274,7 @@ public function status(): ContentRepositoryStatus public function resetProjectionStates(): void { foreach ($this->projectionsAndCatchUpHooks->projections as $projection) { - await($projection->reset()); + $projection->reset(); } } @@ -289,7 +284,7 @@ public function resetProjectionStates(): void public function resetProjectionState(string $projectionClassName): void { $projection = $this->projectionsAndCatchUpHooks->projections->get($projectionClassName); - await($projection->reset()); + $projection->reset(); } public function getNodeTypeManager(): NodeTypeManager diff --git a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentGraphProjection.php b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentGraphProjection.php index 2ac3923feb9..8391dcb093d 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentGraphProjection.php +++ b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentGraphProjection.php @@ -10,7 +10,6 @@ use Neos\ContentRepository\Core\Projection\ProjectionStatus; use Neos\ContentRepository\Core\Projection\WithMarkStaleInterface; use Neos\EventStore\Model\EventEnvelope; -use React\Promise\PromiseInterface; /** * @implements ProjectionInterface @@ -36,9 +35,9 @@ public function status(): ProjectionStatus return $this->projectionImplementation->status(); } - public function reset(): PromiseInterface + public function reset(): void { - return $this->projectionImplementation->reset(); + $this->projectionImplementation->reset(); } public function getState(): ContentGraphInterface @@ -46,9 +45,9 @@ public function getState(): ContentGraphInterface return $this->projectionImplementation->getState(); } - public function apply(EventInterface $event, EventEnvelope $eventEnvelope): PromiseInterface + public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void { - return $this->projectionImplementation->apply($event, $eventEnvelope); + $this->projectionImplementation->apply($event, $eventEnvelope); } public function getCheckpointStorage(): CheckpointStorageInterface diff --git a/Neos.ContentRepository.Core/Classes/Projection/ContentStream/ContentStreamProjection.php b/Neos.ContentRepository.Core/Classes/Projection/ContentStream/ContentStreamProjection.php index 61fe00ab567..239b6a39403 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/ContentStream/ContentStreamProjection.php +++ b/Neos.ContentRepository.Core/Classes/Projection/ContentStream/ContentStreamProjection.php @@ -50,9 +50,6 @@ use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamState; use Neos\EventStore\Model\Event\SequenceNumber; use Neos\EventStore\Model\EventEnvelope; -use React\Promise\PromiseInterface; - -use function React\Promise\resolve; /** * See {@see ContentStreamFinder} for explanation. @@ -144,19 +141,18 @@ private function determineRequiredSqlStatements(): array return DbalSchemaDiff::determineRequiredSqlStatements($connection, $schema); } - public function reset(): PromiseInterface + public function reset(): void { $this->getDatabaseConnection()->executeStatement('TRUNCATE table ' . $this->tableName); $this->checkpointStorage->acquireLock(); $this->checkpointStorage->updateAndReleaseLock(SequenceNumber::none()); - return resolve(null); } - public function apply(EventInterface $event, EventEnvelope $eventEnvelope): PromiseInterface + public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void { if ($event instanceof EmbedsContentStreamAndNodeAggregateId) { $this->updateContentStreamVersion($event, $eventEnvelope); - return resolve(null); + return; } match ($event::class) { ContentStreamWasCreated::class => $this->whenContentStreamWasCreated($event, $eventEnvelope), @@ -175,7 +171,6 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): Prom DimensionShineThroughWasAdded::class => $this->whenDimensionShineThroughWasAdded($event, $eventEnvelope), default => null, }; - return resolve(null); } public function getCheckpointStorage(): CheckpointStorageInterface diff --git a/Neos.ContentRepository.Core/Classes/Projection/ProjectionInterface.php b/Neos.ContentRepository.Core/Classes/Projection/ProjectionInterface.php index f2c3f1a592f..cf4c7daf432 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/ProjectionInterface.php +++ b/Neos.ContentRepository.Core/Classes/Projection/ProjectionInterface.php @@ -7,7 +7,6 @@ use Neos\ContentRepository\Core\ContentRepository; use Neos\ContentRepository\Core\EventStore\EventInterface; use Neos\EventStore\Model\EventEnvelope; -use React\Promise\PromiseInterface; /** * Common interface for a Content Repository projection. This API is NOT exposed to the outside world, but is @@ -31,10 +30,7 @@ public function setUp(): void; */ public function status(): ProjectionStatus; - /** - * @return PromiseInterface - */ - public function apply(EventInterface $event, EventEnvelope $eventEnvelope): PromiseInterface; + public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void; public function getCheckpointStorage(): CheckpointStorageInterface; @@ -48,8 +44,5 @@ public function getCheckpointStorage(): CheckpointStorageInterface; */ public function getState(): ProjectionStateInterface; - /** - * @return PromiseInterface - */ - public function reset(): PromiseInterface; + public function reset(): void; } diff --git a/Neos.ContentRepository.Core/Classes/Projection/Workspace/WorkspaceProjection.php b/Neos.ContentRepository.Core/Classes/Projection/Workspace/WorkspaceProjection.php index 7ef1c864a36..00cceb71ba9 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/Workspace/WorkspaceProjection.php +++ b/Neos.ContentRepository.Core/Classes/Projection/Workspace/WorkspaceProjection.php @@ -136,15 +136,14 @@ private function determineRequiredSqlStatements(): array return DbalSchemaDiff::determineRequiredSqlStatements($connection, $schema); } - public function reset(): PromiseInterface + public function reset(): void { $this->getDatabaseConnection()->exec('TRUNCATE ' . $this->tableName); $this->checkpointStorage->acquireLock(); $this->checkpointStorage->updateAndReleaseLock(SequenceNumber::none()); - return resolve(null); } - public function apply(EventInterface $event, EventEnvelope $eventEnvelope): PromiseInterface + public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void { match ($event::class) { WorkspaceWasCreated::class => $this->whenWorkspaceWasCreated($event), @@ -161,7 +160,6 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): Prom WorkspaceBaseWorkspaceWasChanged::class => $this->whenWorkspaceBaseWorkspaceWasChanged($event), default => null, }; - return resolve(null); } public function getCheckpointStorage(): DbalCheckpointStorage diff --git a/Neos.ContentRepository.Core/composer.json b/Neos.ContentRepository.Core/composer.json index 1c7f92c949a..56bdba56ad6 100644 --- a/Neos.ContentRepository.Core/composer.json +++ b/Neos.ContentRepository.Core/composer.json @@ -21,9 +21,7 @@ "symfony/serializer": "^6.3", "psr/clock": "^1", "behat/transliterator": "~1.0", - "ramsey/uuid": "^3.0 || ^4.0", - "react/promise": "^3.1", - "react/async": "^v4.2" + "ramsey/uuid": "^3.0 || ^4.0" }, "require-dev": { "roave/security-advisories": "dev-latest", diff --git a/Neos.Neos/Classes/AssetUsage/Projection/AssetUsageProjection.php b/Neos.Neos/Classes/AssetUsage/Projection/AssetUsageProjection.php index c1a6f70ea95..6fa9e65b1ad 100644 --- a/Neos.Neos/Classes/AssetUsage/Projection/AssetUsageProjection.php +++ b/Neos.Neos/Classes/AssetUsage/Projection/AssetUsageProjection.php @@ -35,7 +35,6 @@ use Neos\Neos\AssetUsage\Dto\AssetUsageNodeAddress; use Neos\Utility\Exception\InvalidTypeException; use Neos\Utility\TypeHandling; -use React\Promise\PromiseInterface; use function React\Promise\resolve; @@ -65,12 +64,11 @@ public function __construct( ); } - public function reset(): PromiseInterface + public function reset(): void { $this->repository->reset(); $this->checkpointStorage->acquireLock(); $this->checkpointStorage->updateAndReleaseLock(SequenceNumber::none()); - return resolve(null); } public function whenNodeAggregateWithNodeWasCreated(NodeAggregateWithNodeWasCreated $event, EventEnvelope $eventEnvelope): void @@ -257,7 +255,7 @@ public function status(): ProjectionStatus return ProjectionStatus::ok(); } - public function apply(EventInterface $event, EventEnvelope $eventEnvelope): PromiseInterface + public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void { match ($event::class) { NodeAggregateWithNodeWasCreated::class => $this->whenNodeAggregateWithNodeWasCreated($event, $eventEnvelope), @@ -273,7 +271,6 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): Prom ContentStreamWasRemoved::class => $this->whenContentStreamWasRemoved($event), default => null, }; - return resolve(null); } public function getCheckpointStorage(): DbalCheckpointStorage diff --git a/Neos.Neos/Classes/FrontendRouting/Projection/DocumentUriPathProjection.php b/Neos.Neos/Classes/FrontendRouting/Projection/DocumentUriPathProjection.php index 90413cf21e8..d1022703f28 100644 --- a/Neos.Neos/Classes/FrontendRouting/Projection/DocumentUriPathProjection.php +++ b/Neos.Neos/Classes/FrontendRouting/Projection/DocumentUriPathProjection.php @@ -43,9 +43,6 @@ use Neos\Neos\Domain\Model\SiteNodeName; use Neos\Neos\Domain\Service\NodeTypeNameFactory; use Neos\Neos\FrontendRouting\Exception\NodeNotFoundException; -use React\Promise\PromiseInterface; - -use function React\Promise\resolve; /** * @implements ProjectionInterface @@ -123,13 +120,12 @@ private function determineRequiredSqlStatements(): array } - public function reset(): PromiseInterface + public function reset(): void { $this->truncateDatabaseTables(); $this->checkpointStorage->acquireLock(); $this->checkpointStorage->updateAndReleaseLock(SequenceNumber::none()); $this->stateAccessor = null; - return resolve(null); } private function truncateDatabaseTables(): void @@ -142,7 +138,7 @@ private function truncateDatabaseTables(): void } } - public function apply(EventInterface $event, EventEnvelope $eventEnvelope): PromiseInterface + public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void { match ($event::class) { RootWorkspaceWasCreated::class => $this->whenRootWorkspaceWasCreated($event), @@ -162,7 +158,6 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): Prom DimensionShineThroughWasAdded::class => $this->whenDimensionShineThroughWasAdded($event), default => null, }; - return resolve(null); } public function getCheckpointStorage(): DbalCheckpointStorage diff --git a/Neos.Neos/Classes/PendingChangesProjection/ChangeProjection.php b/Neos.Neos/Classes/PendingChangesProjection/ChangeProjection.php index c833a48f4d6..712fe2b0f89 100644 --- a/Neos.Neos/Classes/PendingChangesProjection/ChangeProjection.php +++ b/Neos.Neos/Classes/PendingChangesProjection/ChangeProjection.php @@ -46,9 +46,6 @@ use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; use Neos\EventStore\Model\Event\SequenceNumber; use Neos\EventStore\Model\EventEnvelope; -use React\Promise\PromiseInterface; - -use function React\Promise\resolve; /** * TODO: this class needs testing and probably a major refactoring! @@ -156,16 +153,15 @@ private function determineRequiredSqlStatements(): array return DbalSchemaDiff::determineRequiredSqlStatements($connection, $schema); } - public function reset(): PromiseInterface + public function reset(): void { $this->getDatabaseConnection()->exec('TRUNCATE ' . $this->tableNamePrefix); $this->getDatabaseConnection()->exec('TRUNCATE ' . $this->tableNamePrefix . '_livecontentstreams'); $this->checkpointStorage->acquireLock(); $this->checkpointStorage->updateAndReleaseLock(SequenceNumber::none()); - return resolve(null); } - public function apply(EventInterface $event, EventEnvelope $eventEnvelope): PromiseInterface + public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void { match ($event::class) { RootWorkspaceWasCreated::class => $this->whenRootWorkspaceWasCreated($event), @@ -182,7 +178,6 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): Prom NodePeerVariantWasCreated::class => $this->whenNodePeerVariantWasCreated($event), default => null, }; - return resolve(null); } public function getCheckpointStorage(): DbalCheckpointStorage From e8a0bddec7ea325daa8eaddffeaa76e2bc66cc34 Mon Sep 17 00:00:00 2001 From: Bastian Waidelich Date: Fri, 12 Apr 2024 19:12:07 +0200 Subject: [PATCH 03/21] Remove `react/async` dependency 2/2 --- .../Classes/Projection/Workspace/WorkspaceProjection.php | 3 --- composer.json | 2 -- 2 files changed, 5 deletions(-) diff --git a/Neos.ContentRepository.Core/Classes/Projection/Workspace/WorkspaceProjection.php b/Neos.ContentRepository.Core/Classes/Projection/Workspace/WorkspaceProjection.php index 00cceb71ba9..ebd57d5ccb0 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/Workspace/WorkspaceProjection.php +++ b/Neos.ContentRepository.Core/Classes/Projection/Workspace/WorkspaceProjection.php @@ -45,9 +45,6 @@ use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName; use Neos\EventStore\Model\Event\SequenceNumber; use Neos\EventStore\Model\EventEnvelope; -use React\Promise\PromiseInterface; - -use function React\Promise\resolve; /** * @internal diff --git a/composer.json b/composer.json index e30391801bd..b17ad9c3d79 100644 --- a/composer.json +++ b/composer.json @@ -19,8 +19,6 @@ "psr/clock": "^1", "behat/transliterator": "~1.0", "ramsey/uuid": "^3.0 || ^4.0", - "react/promise": "^3.1", - "react/async": "^v4.2", "league/flysystem": "^3", "webmozart/assert": "^1.11", "neos/flow": "*", From d2382eec02ac2528f5a4da0e04a0497d77351b5a Mon Sep 17 00:00:00 2001 From: Bastian Waidelich Date: Sat, 13 Apr 2024 12:44:40 +0200 Subject: [PATCH 04/21] Cosmetic fix to satisfy linter --- Neos.ContentRepository.Core/Classes/ContentRepository.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/Neos.ContentRepository.Core/Classes/ContentRepository.php b/Neos.ContentRepository.Core/Classes/ContentRepository.php index 80cf2e01771..2ce096f45d5 100644 --- a/Neos.ContentRepository.Core/Classes/ContentRepository.php +++ b/Neos.ContentRepository.Core/Classes/ContentRepository.php @@ -46,9 +46,6 @@ use Neos\EventStore\Model\EventStream\VirtualStreamName; use Psr\Clock\ClockInterface; -use function React\Async\await; -use function React\Async\parallel; - /** * Main Entry Point to the system. Encapsulates the full event-sourced Content Repository. * From 7dc35fc67425428f2811b3ed0a1aad4fb8e032a3 Mon Sep 17 00:00:00 2001 From: Bastian Waidelich Date: Sat, 13 Apr 2024 12:58:29 +0200 Subject: [PATCH 05/21] Remove unused namespace imports --- .../src/DoctrineDbalContentGraphProjection.php | 2 -- .../Classes/AssetUsage/Projection/AssetUsageProjection.php | 2 -- 2 files changed, 4 deletions(-) diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php index 12fce3e8f42..0dcc133dad0 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php @@ -63,8 +63,6 @@ use Neos\EventStore\Model\Event\SequenceNumber; use Neos\EventStore\Model\EventEnvelope; -use function React\Promise\resolve; - /** * @implements ProjectionInterface * @internal but the graph projection is api diff --git a/Neos.Neos/Classes/AssetUsage/Projection/AssetUsageProjection.php b/Neos.Neos/Classes/AssetUsage/Projection/AssetUsageProjection.php index 6fa9e65b1ad..4e2a1e41a3e 100644 --- a/Neos.Neos/Classes/AssetUsage/Projection/AssetUsageProjection.php +++ b/Neos.Neos/Classes/AssetUsage/Projection/AssetUsageProjection.php @@ -36,8 +36,6 @@ use Neos\Utility\Exception\InvalidTypeException; use Neos\Utility\TypeHandling; -use function React\Promise\resolve; - /** * @implements ProjectionInterface * @internal From 13e1238db7dc6f6e96b4a4ea9b2d5b8ec22647b9 Mon Sep 17 00:00:00 2001 From: Bastian Waidelich Date: Sun, 14 Apr 2024 14:18:11 +0200 Subject: [PATCH 06/21] Replace `CheckpointStorageInterface` and introduce `neos/contentrepository-dbaltools` package --- .../Classes}/DbalSchemaDiff.php | 0 .../Classes}/DbalSchemaFactory.php | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename {Neos.ContentRepository.Core/Classes/Infrastructure => Neos.ContentRepository.DbalTools/Classes}/DbalSchemaDiff.php (100%) rename {Neos.ContentRepository.Core/Classes/Infrastructure => Neos.ContentRepository.DbalTools/Classes}/DbalSchemaFactory.php (100%) diff --git a/Neos.ContentRepository.Core/Classes/Infrastructure/DbalSchemaDiff.php b/Neos.ContentRepository.DbalTools/Classes/DbalSchemaDiff.php similarity index 100% rename from Neos.ContentRepository.Core/Classes/Infrastructure/DbalSchemaDiff.php rename to Neos.ContentRepository.DbalTools/Classes/DbalSchemaDiff.php diff --git a/Neos.ContentRepository.Core/Classes/Infrastructure/DbalSchemaFactory.php b/Neos.ContentRepository.DbalTools/Classes/DbalSchemaFactory.php similarity index 100% rename from Neos.ContentRepository.Core/Classes/Infrastructure/DbalSchemaFactory.php rename to Neos.ContentRepository.DbalTools/Classes/DbalSchemaFactory.php From 4c425cda4d1f01f8cfef42a3806561522f2aeb8f Mon Sep 17 00:00:00 2001 From: Bastian Waidelich Date: Sun, 14 Apr 2024 14:18:11 +0200 Subject: [PATCH 07/21] Replace `CheckpointStorageInterface` and introduce `neos/contentrepository-dbaltools` package --- .../composer.json | 3 +- .../DoctrineDbalContentGraphProjection.php | 48 ++----- .../DoctrineDbalContentGraphSchemaBuilder.php | 6 +- .../composer.json | 2 +- .../Projection/HypergraphProjection.php | 34 ++--- .../SchemaBuilder/HypergraphSchemaBuilder.php | 3 +- .../Classes/ContentRepository.php | 36 ++--- .../Infrastructure/DbalCheckpointStorage.php | 124 ---------------- .../Infrastructure/DbalClientInterface.php | 2 + .../Classes/Projection/CatchUp.php | 134 ------------------ .../Projection/CatchUpHookInterface.php | 8 +- .../Projection/CheckpointStorageInterface.php | 61 -------- .../Projection/CheckpointStorageStatus.php | 53 ------- .../CheckpointStorageStatusType.php | 12 -- .../ContentGraph/ContentGraphProjection.php | 6 +- .../ContentStream/ContentStreamProjection.php | 46 +++--- .../Projection/ProjectionInterface.php | 5 +- .../Workspace/WorkspaceProjection.php | 40 +++--- .../Infrastructure/DbalSchemaDiffTest.php | 2 +- Neos.ContentRepository.Core/composer.json | 10 +- .../Classes/CheckpointHelper.php | 61 ++++++++ .../Classes}/DbalSchemaDiff.php | 2 +- .../Classes}/DbalSchemaFactory.php | 4 +- .../composer.json | 34 +++++ .../Projection/AssetUsageProjection.php | 65 ++++++--- .../Projection/AssetUsageRepository.php | 4 +- .../Projection/DocumentUriPathProjection.php | 35 ++--- .../DocumentUriPathSchemaBuilder.php | 6 +- .../ChangeProjection.php | 41 +++--- Neos.Neos/composer.json | 1 + composer.json | 3 +- 31 files changed, 289 insertions(+), 602 deletions(-) delete mode 100644 Neos.ContentRepository.Core/Classes/Infrastructure/DbalCheckpointStorage.php delete mode 100644 Neos.ContentRepository.Core/Classes/Projection/CatchUp.php delete mode 100644 Neos.ContentRepository.Core/Classes/Projection/CheckpointStorageInterface.php delete mode 100644 Neos.ContentRepository.Core/Classes/Projection/CheckpointStorageStatus.php delete mode 100644 Neos.ContentRepository.Core/Classes/Projection/CheckpointStorageStatusType.php create mode 100644 Neos.ContentRepository.DbalTools/Classes/CheckpointHelper.php rename {Neos.ContentRepository.Core/Classes/Infrastructure => Neos.ContentRepository.DbalTools/Classes}/DbalSchemaDiff.php (97%) rename {Neos.ContentRepository.Core/Classes/Infrastructure => Neos.ContentRepository.DbalTools/Classes}/DbalSchemaFactory.php (98%) create mode 100644 Neos.ContentRepository.DbalTools/composer.json diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/composer.json b/Neos.ContentGraph.DoctrineDbalAdapter/composer.json index 6ef1a4dfca2..f7d1c899c28 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/composer.json +++ b/Neos.ContentGraph.DoctrineDbalAdapter/composer.json @@ -10,8 +10,7 @@ "license": "GPL-3.0+", "require": { "neos/contentrepository-core": "self.version", - "doctrine/dbal": "^2.13", - "doctrine/migrations": "*" + "neos/contentrepository-dbaltools": "*" }, "autoload": { "psr-4": { diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php index 0dcc133dad0..eeda8919d5f 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php @@ -5,6 +5,7 @@ namespace Neos\ContentGraph\DoctrineDbalAdapter; use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Exception\UniqueConstraintViolationException; use Doctrine\DBAL\Schema\AbstractSchemaManager; use Doctrine\DBAL\Types\Types; use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Projection\Feature\NodeMove; @@ -44,12 +45,11 @@ use Neos\ContentRepository\Core\Feature\SubtreeTagging\Dto\SubtreeTags; use Neos\ContentRepository\Core\Feature\SubtreeTagging\Event\SubtreeWasTagged; use Neos\ContentRepository\Core\Feature\SubtreeTagging\Event\SubtreeWasUntagged; -use Neos\ContentRepository\Core\Infrastructure\DbalCheckpointStorage; use Neos\ContentRepository\Core\Infrastructure\DbalClientInterface; -use Neos\ContentRepository\Core\Infrastructure\DbalSchemaDiff; +use Neos\ContentRepository\DbalTools\CheckpointHelper; +use Neos\ContentRepository\DbalTools\DbalSchemaDiff; use Neos\ContentRepository\Core\NodeType\NodeTypeManager; use Neos\ContentRepository\Core\NodeType\NodeTypeName; -use Neos\ContentRepository\Core\Projection\CheckpointStorageStatusType; use Neos\ContentRepository\Core\Projection\ContentGraph\NodeTags; use Neos\ContentRepository\Core\Projection\ContentGraph\Timestamps; use Neos\ContentRepository\Core\Projection\ProjectionInterface; @@ -83,8 +83,6 @@ final class DoctrineDbalContentGraphProjection implements ProjectionInterface, W */ private ?ContentGraph $contentGraph = null; - private DbalCheckpointStorage $checkpointStorage; - public function __construct( private readonly DbalClientInterface $dbalClient, private readonly NodeFactory $nodeFactory, @@ -94,11 +92,6 @@ public function __construct( private readonly string $tableNamePrefix, private readonly DimensionSpacePointsRepository $dimensionSpacePointsRepository ) { - $this->checkpointStorage = new DbalCheckpointStorage( - $this->dbalClient->getConnection(), - $this->tableNamePrefix . '_checkpoint', - self::class - ); } protected function getProjectionContentGraph(): ProjectionContentGraph @@ -116,7 +109,7 @@ public function setUp(): void foreach ($this->determineRequiredSqlStatements() as $statement) { $this->getDatabaseConnection()->executeStatement($statement); } - $this->checkpointStorage->setUp(); + CheckpointHelper::resetCheckpoint($this->getDatabaseConnection(), $this->getTableNamePrefix()); } /** @@ -135,13 +128,7 @@ private function determineRequiredSqlStatements(): array public function status(): ProjectionStatus { - $checkpointStorageStatus = $this->checkpointStorage->status(); - if ($checkpointStorageStatus->type === CheckpointStorageStatusType::ERROR) { - return ProjectionStatus::error($checkpointStorageStatus->details); - } - if ($checkpointStorageStatus->type === CheckpointStorageStatusType::SETUP_REQUIRED) { - return ProjectionStatus::setupRequired($checkpointStorageStatus->details); - } + // TODO check checkpoint status try { $this->getDatabaseConnection()->connect(); } catch (\Throwable $e) { @@ -159,29 +146,22 @@ public function status(): ProjectionStatus } public function reset(): void - { - $this->truncateDatabaseTables(); - - $this->checkpointStorage->acquireLock(); - $this->checkpointStorage->updateAndReleaseLock(SequenceNumber::none()); - - $contentGraph = $this->getState(); - foreach ($contentGraph->getSubgraphs() as $subgraph) { - $subgraph->inMemoryCache->enable(); - } - } - - private function truncateDatabaseTables(): void { $connection = $this->dbalClient->getConnection(); $connection->executeQuery('TRUNCATE table ' . $this->tableNamePrefix . '_node'); $connection->executeQuery('TRUNCATE table ' . $this->tableNamePrefix . '_hierarchyrelation'); $connection->executeQuery('TRUNCATE table ' . $this->tableNamePrefix . '_referencerelation'); $connection->executeQuery('TRUNCATE table ' . $this->tableNamePrefix . '_dimensionspacepoints'); + CheckpointHelper::resetCheckpoint($this->getDatabaseConnection(), $this->getTableNamePrefix()); + $contentGraph = $this->getState(); + foreach ($contentGraph->getSubgraphs() as $subgraph) { + $subgraph->inMemoryCache->enable(); + } } public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void { + $this->getDatabaseConnection()->beginTransaction(); match ($event::class) { RootNodeAggregateWithNodeWasCreated::class => $this->whenRootNodeAggregateWithNodeWasCreated($event, $eventEnvelope), RootNodeAggregateDimensionsWereUpdated::class => $this->whenRootNodeAggregateDimensionsWereUpdated($event), @@ -203,11 +183,13 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void SubtreeWasUntagged::class => $this->whenSubtreeWasUntagged($event), default => null, }; + CheckpointHelper::updateCheckpoint($this->getDatabaseConnection(), $this->getTableNamePrefix(), $eventEnvelope->sequenceNumber); + $this->getDatabaseConnection()->commit(); } - public function getCheckpointStorage(): DbalCheckpointStorage + public function getCheckpoint(): SequenceNumber { - return $this->checkpointStorage; + return CheckpointHelper::getCheckpoint($this->getDatabaseConnection(), $this->getTableNamePrefix()); } public function getState(): ContentGraph diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphSchemaBuilder.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphSchemaBuilder.php index 06cc35ff431..614737df256 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphSchemaBuilder.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphSchemaBuilder.php @@ -8,7 +8,8 @@ use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Types; -use Neos\ContentRepository\Core\Infrastructure\DbalSchemaFactory; +use Neos\ContentRepository\DbalTools\CheckpointHelper; +use Neos\ContentRepository\DbalTools\DbalSchemaFactory; /** * @internal @@ -28,7 +29,8 @@ public function buildSchema(AbstractSchemaManager $schemaManager): Schema $this->createNodeTable(), $this->createHierarchyRelationTable(), $this->createReferenceRelationTable(), - $this->createDimensionSpacePointsTable() + $this->createDimensionSpacePointsTable(), + CheckpointHelper::checkpointTableSchema($this->tableNamePrefix), ]); } diff --git a/Neos.ContentGraph.PostgreSQLAdapter/composer.json b/Neos.ContentGraph.PostgreSQLAdapter/composer.json index d76c1831bd8..a8976fdc257 100644 --- a/Neos.ContentGraph.PostgreSQLAdapter/composer.json +++ b/Neos.ContentGraph.PostgreSQLAdapter/composer.json @@ -11,7 +11,7 @@ "require": { "neos/contentrepository-core": "self.version", "doctrine/dbal": "*", - "doctrine/migrations": "*" + "neos/contentrepository-dbaltools": "*" }, "autoload": { "psr-4": { diff --git a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/HypergraphProjection.php b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/HypergraphProjection.php index 64560bf61b1..4a14652359f 100644 --- a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/HypergraphProjection.php +++ b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/HypergraphProjection.php @@ -43,10 +43,9 @@ use Neos\ContentRepository\Core\Feature\RootNodeCreation\Event\RootNodeAggregateWithNodeWasCreated; use Neos\ContentRepository\Core\Feature\SubtreeTagging\Event\SubtreeWasTagged; use Neos\ContentRepository\Core\Feature\SubtreeTagging\Event\SubtreeWasUntagged; -use Neos\ContentRepository\Core\Infrastructure\DbalCheckpointStorage; -use Neos\ContentRepository\Core\Infrastructure\DbalSchemaDiff; +use Neos\ContentRepository\DbalTools\CheckpointHelper; +use Neos\ContentRepository\DbalTools\DbalSchemaDiff; use Neos\ContentRepository\Core\NodeType\NodeTypeManager; -use Neos\ContentRepository\Core\Projection\CheckpointStorageStatusType; use Neos\ContentRepository\Core\Projection\ProjectionInterface; use Neos\ContentRepository\Core\Projection\ProjectionStatus; use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId; @@ -76,7 +75,6 @@ final class HypergraphProjection implements ProjectionInterface * so that always the same instance is returned */ private ?ContentHypergraph $contentHypergraph = null; - private DbalCheckpointStorage $checkpointStorage; private ProjectionHypergraph $projectionHypergraph; public function __construct( @@ -87,11 +85,6 @@ public function __construct( private readonly string $tableNamePrefix, ) { $this->projectionHypergraph = new ProjectionHypergraph($this->databaseClient, $this->tableNamePrefix); - $this->checkpointStorage = new DbalCheckpointStorage( - $this->databaseClient->getConnection(), - $this->tableNamePrefix . '_checkpoint', - self::class - ); } @@ -109,18 +102,10 @@ public function setUp(): void create index if not exists restriction_affected on ' . $this->tableNamePrefix . '_restrictionhyperrelation using gin (affectednodeaggregateids); '); - $this->checkpointStorage->setUp(); } public function status(): ProjectionStatus { - $checkpointStorageStatus = $this->checkpointStorage->status(); - if ($checkpointStorageStatus->type === CheckpointStorageStatusType::ERROR) { - return ProjectionStatus::error($checkpointStorageStatus->details); - } - if ($checkpointStorageStatus->type === CheckpointStorageStatusType::SETUP_REQUIRED) { - return ProjectionStatus::setupRequired($checkpointStorageStatus->details); - } try { $this->getDatabaseConnection()->connect(); } catch (\Throwable $e) { @@ -134,6 +119,11 @@ public function status(): ProjectionStatus if ($requiredSqlStatements !== []) { return ProjectionStatus::setupRequired(sprintf('The following SQL statement%s required: %s', count($requiredSqlStatements) !== 1 ? 's are' : ' is', implode(chr(10), $requiredSqlStatements))); } + try { + $this->getCheckpoint(); + } catch (\Exception $exception) { + return ProjectionStatus::error($exception->getMessage()); + } return ProjectionStatus::ok(); } @@ -157,8 +147,7 @@ public function reset(): void { $this->truncateDatabaseTables(); - $this->checkpointStorage->acquireLock(); - $this->checkpointStorage->updateAndReleaseLock(SequenceNumber::none()); + CheckpointHelper::resetCheckpoint($this->getDatabaseConnection(), $this->tableNamePrefix); //$contentGraph = $this->getState(); //foreach ($contentGraph->getSubgraphs() as $subgraph) { @@ -177,6 +166,7 @@ private function truncateDatabaseTables(): void public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void { + $this->getDatabaseConnection()->beginTransaction(); match ($event::class) { // ContentStreamForking ContentStreamWasForked::class => $this->whenContentStreamWasForked($event), @@ -202,11 +192,13 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void NodePeerVariantWasCreated::class => $this->whenNodePeerVariantWasCreated($event), default => null, }; + CheckpointHelper::updateCheckpoint($this->getDatabaseConnection(), $this->tableNamePrefix, $eventEnvelope->sequenceNumber); + $this->getDatabaseConnection()->commit(); } - public function getCheckpointStorage(): DbalCheckpointStorage + public function getCheckpoint(): SequenceNumber { - return $this->checkpointStorage; + return CheckpointHelper::getCheckpoint($this->getDatabaseConnection(), $this->tableNamePrefix); } public function getState(): ContentHypergraph diff --git a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/SchemaBuilder/HypergraphSchemaBuilder.php b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/SchemaBuilder/HypergraphSchemaBuilder.php index 40176222de6..99fc31fde76 100644 --- a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/SchemaBuilder/HypergraphSchemaBuilder.php +++ b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/SchemaBuilder/HypergraphSchemaBuilder.php @@ -7,6 +7,7 @@ use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Types; use Neos\ContentGraph\PostgreSQLAdapter\Domain\Projection\HypergraphProjection; +use Neos\ContentRepository\DbalTools\CheckpointHelper; /** * @internal @@ -20,7 +21,7 @@ public function __construct( public function buildSchema(): Schema { - $schema = new Schema(); + $schema = new Schema([CheckpointHelper::checkpointTableSchema($this->tableNamePrefix)]); $this->createNodeTable($schema); $this->createHierarchyHyperrelationTable($schema); diff --git a/Neos.ContentRepository.Core/Classes/ContentRepository.php b/Neos.ContentRepository.Core/Classes/ContentRepository.php index 2ce096f45d5..9f35e6ea7a8 100644 --- a/Neos.ContentRepository.Core/Classes/ContentRepository.php +++ b/Neos.ContentRepository.Core/Classes/ContentRepository.php @@ -26,7 +26,6 @@ use Neos\ContentRepository\Core\EventStore\EventsToPublish; use Neos\ContentRepository\Core\Factory\ContentRepositoryFactory; use Neos\ContentRepository\Core\NodeType\NodeTypeManager; -use Neos\ContentRepository\Core\Projection\CatchUp; use Neos\ContentRepository\Core\Projection\CatchUpHookInterface; use Neos\ContentRepository\Core\Projection\CatchUpOptions; use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphInterface; @@ -45,6 +44,8 @@ use Neos\EventStore\Model\EventEnvelope; use Neos\EventStore\Model\EventStream\VirtualStreamName; use Psr\Clock\ClockInterface; +use Symfony\Component\Lock\LockFactory; +use Symfony\Component\Lock\Store\SemaphoreStore; /** * Main Entry Point to the system. Encapsulates the full event-sourced Content Repository. @@ -160,13 +161,17 @@ public function projectionState(string $projectionStateClassName): ProjectionSta public function catchUpProjections(): void { + $store = new SemaphoreStore(); + $factory = new LockFactory($store); + $lock = $factory->createLock('catchup'); + $lock->acquire(true); #print_r(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS)); $lowestAppliedSequenceNumber = null; - /** @var array, catchUpHook: CatchUpHookInterface|null}> $projectionsAndCatchUpHooks */ + /** @var array, sequenceNumber: SequenceNumber, catchUpHook: CatchUpHookInterface|null}> $projectionsAndCatchUpHooks */ $projectionsAndCatchUpHooks = []; foreach ($this->projectionsAndCatchUpHooks->projections as $projectionClassName => $projection) { - $projectionSequenceNumber = $projection->getCheckpointStorage()->acquireLock(); + $projectionSequenceNumber = $projection->getCheckpoint(); #\Neos\Flow\var_dump('ACQUIRE LOCK FOR ' . $projectionClassName . ': ' . $projectionSequenceNumber->value); if ($lowestAppliedSequenceNumber === null || $projectionSequenceNumber->value < $lowestAppliedSequenceNumber->value) { $lowestAppliedSequenceNumber = $projectionSequenceNumber; @@ -174,6 +179,7 @@ public function catchUpProjections(): void $catchUpHookFactory = $this->projectionsAndCatchUpHooks->getCatchUpHookFactoryForProjection($projection); $projectionsAndCatchUpHooks[$projectionClassName] = [ 'projection' => $projection, + 'sequenceNumber' => $projectionSequenceNumber, 'catchUpHook' => $catchUpHookFactory?->build($this), ]; $projectionsAndCatchUpHooks[$projectionClassName]['catchUpHook']?->onBeforeCatchUp(); @@ -185,8 +191,11 @@ public function catchUpProjections(): void foreach ($eventStream as $eventEnvelope) { #\Neos\Flow\var_dump('EVENT ' . $eventEnvelope->event->type->value); $event = $this->eventNormalizer->denormalize($eventEnvelope->event); - /** @var array{projection: ProjectionInterface, catchUpHook: CatchUpHookInterface|null} $projectionAndCatchUpHook */ + /** @var array{projection: ProjectionInterface, sequenceNumber: SequenceNumber, catchUpHook: CatchUpHookInterface|null} $projectionAndCatchUpHook */ foreach ($projectionsAndCatchUpHooks as $projectionClassName => $projectionAndCatchUpHook) { + if ($projectionAndCatchUpHook['sequenceNumber']->value >= $eventEnvelope->sequenceNumber->value) { + continue; + } #$projectionAndCatchUpHook['catchUpHook']?->onBeforeEvent($event, $eventEnvelope); #\Neos\Flow\var_dump('APPLY ' . $eventEnvelope->event->type->value . ' (' . $eventEnvelope->sequenceNumber->value . ') TO ' . $projectionClassName); #$futures[] = function () => $projectionAndCatchUpHook['projection']->apply($event, $eventEnvelope); @@ -200,14 +209,15 @@ public function catchUpProjections(): void } } assert($eventEnvelope instanceof EventEnvelope); - /** @var array{projection: ProjectionInterface, catchUpHook: CatchUpHookInterface|null} $projectionAndCatchUpHook */ + /** @var array{projection: ProjectionInterface, sequenceNumber: SequenceNumber, catchUpHook: CatchUpHookInterface|null} $projectionAndCatchUpHook */ foreach ($projectionsAndCatchUpHooks as $projectionClassName => $projectionAndCatchUpHook) { $projectionAndCatchUpHook['catchUpHook']?->onBeforeBatchCompleted(); - $projectionAndCatchUpHook['projection']->getCheckpointStorage()->updateAndReleaseLock($eventEnvelope->sequenceNumber); + #$projectionAndCatchUpHook['projection']->getCheckpointStorage()->updateAndReleaseLock($eventEnvelope->sequenceNumber); #\Neos\Flow\var_dump('UPDATE SQN FOR ' . $projectionClassName . ': ' . $eventEnvelope->sequenceNumber->value); #\Neos\Flow\var_dump('UPDATE CHECKPOINT for ' . $projectionClassName . ' to ' . $eventEnvelope->sequenceNumber->value); $projectionAndCatchUpHook['catchUpHook']?->onAfterCatchUp(); } + $lock->release(); } /** @@ -220,30 +230,22 @@ public function catchUpProjection(string $projectionClassName, CatchUpOptions $o $catchUpHookFactory = $this->projectionsAndCatchUpHooks->getCatchUpHookFactoryForProjection($projection); $catchUpHook = $catchUpHookFactory?->build($this); - // TODO allow custom stream name per projection $streamName = VirtualStreamName::all(); $eventStream = $this->eventStore->load($streamName); if ($options->maximumSequenceNumber !== null) { $eventStream = $eventStream->withMaximumSequenceNumber($options->maximumSequenceNumber); } - - $eventApplier = function (EventEnvelope $eventEnvelope) use ($projection, $catchUpHook, $options) { + foreach ($eventStream as $eventEnvelope) { $event = $this->eventNormalizer->denormalize($eventEnvelope->event); if ($options->progressCallback !== null) { ($options->progressCallback)($event, $eventEnvelope); } $catchUpHook?->onBeforeEvent($event, $eventEnvelope); $projection->apply($event, $eventEnvelope); + // TODO this should happen in the inner transaction + $catchUpHook?->onBeforeBatchCompleted(); $catchUpHook?->onAfterEvent($event, $eventEnvelope); - }; - - $catchUp = CatchUp::create($eventApplier, $projection->getCheckpointStorage()); - - if ($catchUpHook !== null) { - $catchUpHook->onBeforeCatchUp(); - $catchUp = $catchUp->withOnBeforeBatchCompleted(fn() => $catchUpHook->onBeforeBatchCompleted()); } - $catchUp->run($eventStream); $catchUpHook?->onAfterCatchUp(); } diff --git a/Neos.ContentRepository.Core/Classes/Infrastructure/DbalCheckpointStorage.php b/Neos.ContentRepository.Core/Classes/Infrastructure/DbalCheckpointStorage.php deleted file mode 100644 index b9d124b5aef..00000000000 --- a/Neos.ContentRepository.Core/Classes/Infrastructure/DbalCheckpointStorage.php +++ /dev/null @@ -1,124 +0,0 @@ -connection->getDatabasePlatform(); - if (!($platform instanceof MySqlPlatform || $platform instanceof PostgreSqlPlatform)) { - throw new \InvalidArgumentException(sprintf('The %s only supports the platforms %s and %s currently. Given: %s', $this::class, MySqlPlatform::class, PostgreSqlPlatform::class, get_debug_type($platform)), 1660556004); - } - if (strlen($this->subscriberId) > 255) { - throw new \InvalidArgumentException('The subscriberId must not exceed 255 characters', 1705673456); - } - } - - public function setUp(): void - { - foreach ($this->determineRequiredSqlStatements() as $statement) { - $this->connection->executeStatement($statement); - } - try { - $this->connection->insert($this->tableName, ['subscriberid' => $this->subscriberId, 'appliedsequencenumber' => 0]); - } catch (UniqueConstraintViolationException $e) { - // table and row already exists, ignore - } - } - - public function status(): CheckpointStorageStatus - { - try { - $this->connection->connect(); - } catch (\Throwable $e) { - return CheckpointStorageStatus::error(sprintf('Failed to connect to database for subscriber "%s": %s', $this->subscriberId, $e->getMessage())); - } - try { - $requiredSqlStatements = $this->determineRequiredSqlStatements(); - } catch (\Throwable $e) { - return CheckpointStorageStatus::error(sprintf('Failed to compare database schema for subscriber "%s": %s', $this->subscriberId, $e->getMessage())); - } - if ($requiredSqlStatements !== []) { - return CheckpointStorageStatus::setupRequired(sprintf('The following SQL statement%s required for subscriber "%s": %s', count($requiredSqlStatements) !== 1 ? 's are' : ' is', $this->subscriberId, implode(chr(10), $requiredSqlStatements))); - } - try { - $appliedSequenceNumber = $this->connection->fetchOne('SELECT appliedsequencenumber FROM ' . $this->tableName . ' WHERE subscriberid = :subscriberId', ['subscriberId' => $this->subscriberId]); - } catch (\Throwable $e) { - return CheckpointStorageStatus::error(sprintf('Failed to determine initial applied sequence number for subscriber "%s": %s', $this->subscriberId, $e->getMessage())); - } - if ($appliedSequenceNumber === false) { - return CheckpointStorageStatus::setupRequired(sprintf('Initial initial applied sequence number not set for subscriber "%s"', $this->subscriberId)); - } - return CheckpointStorageStatus::ok(); - } - - public function acquireLock(): SequenceNumber - { - return $this->getHighestAppliedSequenceNumber(); - } - - public function updateAndReleaseLock(SequenceNumber $sequenceNumber): void - { - $this->connection->update($this->tableName, ['appliedsequencenumber' => $sequenceNumber->value], ['subscriberid' => $this->subscriberId]); - } - - public function getHighestAppliedSequenceNumber(): SequenceNumber - { - $highestAppliedSequenceNumber = $this->connection->fetchOne('SELECT appliedsequencenumber FROM ' . $this->connection->quoteIdentifier($this->tableName) . ' WHERE subscriberid = :subscriberId ', [ - 'subscriberId' => $this->subscriberId - ]); - if (!is_numeric($highestAppliedSequenceNumber)) { - throw new \RuntimeException(sprintf('Failed to fetch highest applied sequence number for subscriber "%s". Please run %s::setUp()', $this->subscriberId, $this::class), 1652279427); - } - return SequenceNumber::fromInteger((int)$highestAppliedSequenceNumber); - } - - // -------------- - - /** - * @return array - */ - private function determineRequiredSqlStatements(): array - { - $schemaManager = $this->connection->getSchemaManager(); - if (!$schemaManager instanceof AbstractSchemaManager) { - throw new \RuntimeException('Failed to retrieve Schema Manager', 1705681161); - } - $tableSchema = new Table( - $this->tableName, - [ - (new Column('subscriberid', Type::getType(Types::STRING)))->setLength(255), - (new Column('appliedsequencenumber', Type::getType(Types::INTEGER))) - ] - ); - $tableSchema->setPrimaryKey(['subscriberid']); - $schema = DbalSchemaFactory::createSchemaWithTables($schemaManager, [$tableSchema]); - return DbalSchemaDiff::determineRequiredSqlStatements($this->connection, $schema); - } -} diff --git a/Neos.ContentRepository.Core/Classes/Infrastructure/DbalClientInterface.php b/Neos.ContentRepository.Core/Classes/Infrastructure/DbalClientInterface.php index 93e1aff18f3..8db7a998b6f 100644 --- a/Neos.ContentRepository.Core/Classes/Infrastructure/DbalClientInterface.php +++ b/Neos.ContentRepository.Core/Classes/Infrastructure/DbalClientInterface.php @@ -9,6 +9,8 @@ /** * This is what the ES CR uses to access a database. It needs to be filled from the external world * + * TODO remove this interface + * * @api */ interface DbalClientInterface diff --git a/Neos.ContentRepository.Core/Classes/Projection/CatchUp.php b/Neos.ContentRepository.Core/Classes/Projection/CatchUp.php deleted file mode 100644 index b997978bfe7..00000000000 --- a/Neos.ContentRepository.Core/Classes/Projection/CatchUp.php +++ /dev/null @@ -1,134 +0,0 @@ -batchSize < 1) { - throw new \InvalidArgumentException(sprintf('batch size must be a positive integer, given: %d', $this->batchSize), 1705672467); - } - } - - /** - * @param \Closure(EventEnvelope): void $eventHandler The callback that is invoked for every {@see EventEnvelope} that is processed - * @param CheckpointStorageInterface $checkpointStorage The checkpoint storage that saves the last processed {@see SequenceNumber} - */ - public static function create(\Closure $eventHandler, CheckpointStorageInterface $checkpointStorage): self - { - return new self($eventHandler, $checkpointStorage, 1, null); - } - - /** - * After how many events should the (database) transaction be committed? - * - * @param int $batchSize Number of events to process before the checkpoint is written - */ - public function withBatchSize(int $batchSize): self - { - if ($batchSize === $this->batchSize) { - return $this; - } - return new self($this->eventHandler, $this->checkpointStorage, $batchSize, $this->onBeforeBatchCompletedHook); - } - - /** - * This hook is called directly before the sequence number is persisted back in CheckpointStorage. - * Use this to trigger any operation which need to happen BEFORE the sequence number update is made - * visible to the outside. - * - * Overrides all previously registered onBeforeBatchCompleted hooks. - * - * @param \Closure(): void $callback the hook being called before the batch is completed - */ - public function withOnBeforeBatchCompleted(\Closure $callback): self - { - return new self($this->eventHandler, $this->checkpointStorage, $this->batchSize, $callback); - } - - /** - * Iterate over the $eventStream, invoke the specified event handler closure for every {@see EventEnvelope} and update - * the last processed sequence number in the {@see CheckpointStorageInterface} - * - * @param EventStreamInterface $eventStream The event stream to process - * @return SequenceNumber The last processed {@see SequenceNumber} - * @throws \Throwable Exceptions that are thrown during callback handling are re-thrown - */ - public function run(EventStreamInterface $eventStream): SequenceNumber - { - $highestAppliedSequenceNumber = $this->checkpointStorage->acquireLock(); - $iteration = 0; - try { - foreach ($eventStream->withMinimumSequenceNumber($highestAppliedSequenceNumber->next()) as $eventEnvelope) { - if ($eventEnvelope->sequenceNumber->value <= $highestAppliedSequenceNumber->value) { - continue; - } - try { - ($this->eventHandler)($eventEnvelope); - } catch (\Exception $e) { - throw new \RuntimeException(sprintf('Exception while catching up to sequence number %d', $eventEnvelope->sequenceNumber->value), 1710707311, $e); - } - $iteration++; - if ($this->batchSize === 1 || $iteration % $this->batchSize === 0) { - if ($this->onBeforeBatchCompletedHook) { - ($this->onBeforeBatchCompletedHook)(); - } - $this->checkpointStorage->updateAndReleaseLock($eventEnvelope->sequenceNumber); - $highestAppliedSequenceNumber = $this->checkpointStorage->acquireLock(); - } else { - $highestAppliedSequenceNumber = $eventEnvelope->sequenceNumber; - } - } - } finally { - try { - if ($this->onBeforeBatchCompletedHook) { - ($this->onBeforeBatchCompletedHook)(); - } - } finally { - $this->checkpointStorage->updateAndReleaseLock($highestAppliedSequenceNumber); - } - } - return $highestAppliedSequenceNumber; - } -} diff --git a/Neos.ContentRepository.Core/Classes/Projection/CatchUpHookInterface.php b/Neos.ContentRepository.Core/Classes/Projection/CatchUpHookInterface.php index 374e1165564..5d04bbc7ad8 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/CatchUpHookInterface.php +++ b/Neos.ContentRepository.Core/Classes/Projection/CatchUpHookInterface.php @@ -2,6 +2,7 @@ namespace Neos\ContentRepository\Core\Projection; +use Neos\ContentRepository\Core\ContentRepository; use Neos\ContentRepository\Core\EventStore\EventInterface; use Neos\EventStore\Model\EventEnvelope; @@ -16,8 +17,7 @@ interface CatchUpHookInterface { /** - * This hook is called at the beginning of {@see ProjectionInterface::catchUpProjection()}; - * BEFORE the Database Lock is acquired (by {@see CheckpointStorageInterface::acquireLock()}). + * This hook is called at the beginning of {@see ContentRepository::catchUpProjection()}; * * @return void */ @@ -36,8 +36,8 @@ public function onBeforeEvent(EventInterface $eventInstance, EventEnvelope $even public function onAfterEvent(EventInterface $eventInstance, EventEnvelope $eventEnvelope): void; /** - * This hook is called directly before the database lock is RELEASED - * in {@see CheckpointStorageInterface::updateAndReleaseLock()}. + * This hook is called directly before the catchup is done + * in {@see ContentRepository::catchUpProjection()}. * * It can happen that this method is called multiple times, even without * having seen Events in the meantime. diff --git a/Neos.ContentRepository.Core/Classes/Projection/CheckpointStorageInterface.php b/Neos.ContentRepository.Core/Classes/Projection/CheckpointStorageInterface.php deleted file mode 100644 index 43dc37f8ab7..00000000000 --- a/Neos.ContentRepository.Core/Classes/Projection/CheckpointStorageInterface.php +++ /dev/null @@ -1,61 +0,0 @@ -type, $details); - } -} diff --git a/Neos.ContentRepository.Core/Classes/Projection/CheckpointStorageStatusType.php b/Neos.ContentRepository.Core/Classes/Projection/CheckpointStorageStatusType.php deleted file mode 100644 index 3e138d4348d..00000000000 --- a/Neos.ContentRepository.Core/Classes/Projection/CheckpointStorageStatusType.php +++ /dev/null @@ -1,12 +0,0 @@ -projectionImplementation->apply($event, $eventEnvelope); } - public function getCheckpointStorage(): CheckpointStorageInterface + public function getCheckpoint(): SequenceNumber { - return $this->projectionImplementation->getCheckpointStorage(); + return $this->projectionImplementation->getCheckpoint(); } public function markStale(): void diff --git a/Neos.ContentRepository.Core/Classes/Projection/ContentStream/ContentStreamProjection.php b/Neos.ContentRepository.Core/Classes/Projection/ContentStream/ContentStreamProjection.php index 239b6a39403..8b990f42368 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/ContentStream/ContentStreamProjection.php +++ b/Neos.ContentRepository.Core/Classes/Projection/ContentStream/ContentStreamProjection.php @@ -37,17 +37,15 @@ use Neos\ContentRepository\Core\Feature\WorkspacePublication\Event\WorkspaceWasPublished; use Neos\ContentRepository\Core\Feature\WorkspaceRebase\Event\WorkspaceRebaseFailed; use Neos\ContentRepository\Core\Feature\WorkspaceRebase\Event\WorkspaceWasRebased; -use Neos\ContentRepository\Core\Infrastructure\DbalCheckpointStorage; use Neos\ContentRepository\Core\Infrastructure\DbalClientInterface; -use Neos\ContentRepository\Core\Infrastructure\DbalSchemaDiff; -use Neos\ContentRepository\Core\Infrastructure\DbalSchemaFactory; -use Neos\ContentRepository\Core\Projection\CheckpointStorageInterface; -use Neos\ContentRepository\Core\Projection\CheckpointStorageStatusType; use Neos\ContentRepository\Core\Projection\ProjectionInterface; use Neos\ContentRepository\Core\Projection\ProjectionStateInterface; use Neos\ContentRepository\Core\Projection\ProjectionStatus; use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamState; +use Neos\ContentRepository\DbalTools\CheckpointHelper; +use Neos\ContentRepository\DbalTools\DbalSchemaDiff; +use Neos\ContentRepository\DbalTools\DbalSchemaFactory; use Neos\EventStore\Model\Event\SequenceNumber; use Neos\EventStore\Model\EventEnvelope; @@ -64,42 +62,24 @@ class ContentStreamProjection implements ProjectionInterface * so that always the same instance is returned */ private ?ContentStreamFinder $contentStreamFinder = null; - private DbalCheckpointStorage $checkpointStorage; public function __construct( private readonly DbalClientInterface $dbalClient, private readonly string $tableName ) { - $this->checkpointStorage = new DbalCheckpointStorage( - $this->dbalClient->getConnection(), - $this->tableName . '_checkpoint', - self::class - ); } public function setUp(): void { $statements = $this->determineRequiredSqlStatements(); - // MIGRATIONS - if ($this->getDatabaseConnection()->getSchemaManager()->tablesExist([$this->tableName])) { - // added 2023-04-01 - $statements[] = sprintf("UPDATE %s SET state='FORKED' WHERE state='REBASING'; ", $this->tableName); - } foreach ($statements as $statement) { $this->getDatabaseConnection()->executeStatement($statement); } - $this->checkpointStorage->setUp(); + CheckpointHelper::resetCheckpoint($this->getDatabaseConnection(), $this->tableName); } public function status(): ProjectionStatus { - $checkpointStorageStatus = $this->checkpointStorage->status(); - if ($checkpointStorageStatus->type === CheckpointStorageStatusType::ERROR) { - return ProjectionStatus::error($checkpointStorageStatus->details); - } - if ($checkpointStorageStatus->type === CheckpointStorageStatusType::SETUP_REQUIRED) { - return ProjectionStatus::setupRequired($checkpointStorageStatus->details); - } try { $this->getDatabaseConnection()->connect(); } catch (\Throwable $e) { @@ -113,6 +93,11 @@ public function status(): ProjectionStatus if ($requiredSqlStatements !== []) { return ProjectionStatus::setupRequired(sprintf('The following SQL statement%s required: %s', count($requiredSqlStatements) !== 1 ? 's are' : ' is', implode(chr(10), $requiredSqlStatements))); } + try { + $this->getCheckpoint(); + } catch (\Exception $exception) { + return ProjectionStatus::error($exception->getMessage()); + } return ProjectionStatus::ok(); } @@ -135,7 +120,8 @@ private function determineRequiredSqlStatements(): array // Should become a DB ENUM (unclear how to configure with DBAL) or int (latter needs adaption to code) (new Column('state', Type::getType(Types::BINARY)))->setLength(20)->setNotnull(true), (new Column('removed', Type::getType(Types::BOOLEAN)))->setDefault(false)->setNotnull(false) - ])) + ])), + CheckpointHelper::checkpointTableSchema($this->tableName) ]); return DbalSchemaDiff::determineRequiredSqlStatements($connection, $schema); @@ -144,12 +130,12 @@ private function determineRequiredSqlStatements(): array public function reset(): void { $this->getDatabaseConnection()->executeStatement('TRUNCATE table ' . $this->tableName); - $this->checkpointStorage->acquireLock(); - $this->checkpointStorage->updateAndReleaseLock(SequenceNumber::none()); + CheckpointHelper::resetCheckpoint($this->getDatabaseConnection(), $this->tableName); } public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void { + $this->getDatabaseConnection()->beginTransaction(); if ($event instanceof EmbedsContentStreamAndNodeAggregateId) { $this->updateContentStreamVersion($event, $eventEnvelope); return; @@ -171,11 +157,13 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void DimensionShineThroughWasAdded::class => $this->whenDimensionShineThroughWasAdded($event, $eventEnvelope), default => null, }; + CheckpointHelper::updateCheckpoint($this->getDatabaseConnection(), $this->tableName, $eventEnvelope->sequenceNumber); + $this->getDatabaseConnection()->commit(); } - public function getCheckpointStorage(): CheckpointStorageInterface + public function getCheckpoint(): SequenceNumber { - return $this->checkpointStorage; + return CheckpointHelper::getCheckpoint($this->getDatabaseConnection(), $this->tableName); } public function getState(): ProjectionStateInterface diff --git a/Neos.ContentRepository.Core/Classes/Projection/ProjectionInterface.php b/Neos.ContentRepository.Core/Classes/Projection/ProjectionInterface.php index cf4c7daf432..0d674c1d79f 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/ProjectionInterface.php +++ b/Neos.ContentRepository.Core/Classes/Projection/ProjectionInterface.php @@ -6,6 +6,7 @@ use Neos\ContentRepository\Core\ContentRepository; use Neos\ContentRepository\Core\EventStore\EventInterface; +use Neos\EventStore\Model\Event\SequenceNumber; use Neos\EventStore\Model\EventEnvelope; /** @@ -21,7 +22,7 @@ interface ProjectionInterface { /** - * Set up the projection state (create databases, call {@see CheckpointStorageInterface::setUp()}). + * Set up the projection state (create databases). */ public function setUp(): void; @@ -32,7 +33,7 @@ public function status(): ProjectionStatus; public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void; - public function getCheckpointStorage(): CheckpointStorageInterface; + public function getCheckpoint(): SequenceNumber; /** * NOTE: The ProjectionStateInterface returned must be ALWAYS THE SAME INSTANCE. diff --git a/Neos.ContentRepository.Core/Classes/Projection/Workspace/WorkspaceProjection.php b/Neos.ContentRepository.Core/Classes/Projection/Workspace/WorkspaceProjection.php index ebd57d5ccb0..c2d984e35c7 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/Workspace/WorkspaceProjection.php +++ b/Neos.ContentRepository.Core/Classes/Projection/Workspace/WorkspaceProjection.php @@ -33,16 +33,15 @@ use Neos\ContentRepository\Core\Feature\WorkspacePublication\Event\WorkspaceWasPublished; use Neos\ContentRepository\Core\Feature\WorkspaceRebase\Event\WorkspaceRebaseFailed; use Neos\ContentRepository\Core\Feature\WorkspaceRebase\Event\WorkspaceWasRebased; -use Neos\ContentRepository\Core\Infrastructure\DbalCheckpointStorage; use Neos\ContentRepository\Core\Infrastructure\DbalClientInterface; -use Neos\ContentRepository\Core\Infrastructure\DbalSchemaDiff; -use Neos\ContentRepository\Core\Infrastructure\DbalSchemaFactory; -use Neos\ContentRepository\Core\Projection\CheckpointStorageStatusType; use Neos\ContentRepository\Core\Projection\ProjectionInterface; use Neos\ContentRepository\Core\Projection\ProjectionStatus; use Neos\ContentRepository\Core\Projection\WithMarkStaleInterface; use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName; +use Neos\ContentRepository\DbalTools\CheckpointHelper; +use Neos\ContentRepository\DbalTools\DbalSchemaDiff; +use Neos\ContentRepository\DbalTools\DbalSchemaFactory; use Neos\EventStore\Model\Event\SequenceNumber; use Neos\EventStore\Model\EventEnvelope; @@ -59,18 +58,12 @@ class WorkspaceProjection implements ProjectionInterface, WithMarkStaleInterface * so that always the same instance is returned */ private ?WorkspaceFinder $workspaceFinder = null; - private DbalCheckpointStorage $checkpointStorage; private WorkspaceRuntimeCache $workspaceRuntimeCache; public function __construct( private readonly DbalClientInterface $dbalClient, private readonly string $tableName, ) { - $this->checkpointStorage = new DbalCheckpointStorage( - $this->dbalClient->getConnection(), - $this->tableName . '_checkpoint', - self::class - ); $this->workspaceRuntimeCache = new WorkspaceRuntimeCache(); } @@ -79,18 +72,11 @@ public function setUp(): void foreach ($this->determineRequiredSqlStatements() as $statement) { $this->getDatabaseConnection()->executeStatement($statement); } - $this->checkpointStorage->setUp(); + CheckpointHelper::resetCheckpoint($this->getDatabaseConnection(), $this->tableName); } public function status(): ProjectionStatus { - $checkpointStorageStatus = $this->checkpointStorage->status(); - if ($checkpointStorageStatus->type === CheckpointStorageStatusType::ERROR) { - return ProjectionStatus::error($checkpointStorageStatus->details); - } - if ($checkpointStorageStatus->type === CheckpointStorageStatusType::SETUP_REQUIRED) { - return ProjectionStatus::setupRequired($checkpointStorageStatus->details); - } try { $this->getDatabaseConnection()->connect(); } catch (\Throwable $e) { @@ -104,6 +90,11 @@ public function status(): ProjectionStatus if ($requiredSqlStatements !== []) { return ProjectionStatus::setupRequired(sprintf('The following SQL statement%s required: %s', count($requiredSqlStatements) !== 1 ? 's are' : ' is', implode(chr(10), $requiredSqlStatements))); } + try { + $this->getCheckpoint(); + } catch (\Exception $exception) { + return ProjectionStatus::error($exception->getMessage()); + } return ProjectionStatus::ok(); } @@ -128,20 +119,21 @@ private function determineRequiredSqlStatements(): array (new Column('status', Type::getType(Types::BINARY)))->setLength(20)->setNotnull(false) ]); $workspaceTable->setPrimaryKey(['workspacename']); + $checkpointTable = CheckpointHelper::checkpointTableSchema($this->tableName); - $schema = DbalSchemaFactory::createSchemaWithTables($schemaManager, [$workspaceTable]); + $schema = DbalSchemaFactory::createSchemaWithTables($schemaManager, [$workspaceTable, $checkpointTable]); return DbalSchemaDiff::determineRequiredSqlStatements($connection, $schema); } public function reset(): void { $this->getDatabaseConnection()->exec('TRUNCATE ' . $this->tableName); - $this->checkpointStorage->acquireLock(); - $this->checkpointStorage->updateAndReleaseLock(SequenceNumber::none()); + CheckpointHelper::resetCheckpoint($this->getDatabaseConnection(), $this->tableName); } public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void { + $this->getDatabaseConnection()->beginTransaction(); match ($event::class) { WorkspaceWasCreated::class => $this->whenWorkspaceWasCreated($event), WorkspaceWasRenamed::class => $this->whenWorkspaceWasRenamed($event), @@ -157,11 +149,13 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void WorkspaceBaseWorkspaceWasChanged::class => $this->whenWorkspaceBaseWorkspaceWasChanged($event), default => null, }; + CheckpointHelper::updateCheckpoint($this->getDatabaseConnection(), $this->tableName, $eventEnvelope->sequenceNumber); + $this->getDatabaseConnection()->commit(); } - public function getCheckpointStorage(): DbalCheckpointStorage + public function getCheckpoint(): SequenceNumber { - return $this->checkpointStorage; + return CheckpointHelper::getCheckpoint($this->getDatabaseConnection(), $this->tableName); } public function getState(): WorkspaceFinder diff --git a/Neos.ContentRepository.Core/Tests/Unit/Infrastructure/DbalSchemaDiffTest.php b/Neos.ContentRepository.Core/Tests/Unit/Infrastructure/DbalSchemaDiffTest.php index 7914d76355d..f919bb1c27c 100644 --- a/Neos.ContentRepository.Core/Tests/Unit/Infrastructure/DbalSchemaDiffTest.php +++ b/Neos.ContentRepository.Core/Tests/Unit/Infrastructure/DbalSchemaDiffTest.php @@ -9,7 +9,7 @@ use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Types; -use Neos\ContentRepository\Core\Infrastructure\DbalSchemaDiff; +use Neos\ContentRepository\DbalTools\DbalSchemaDiff; use PHPUnit\Framework\TestCase; class DbalSchemaDiffTest extends TestCase diff --git a/Neos.ContentRepository.Core/composer.json b/Neos.ContentRepository.Core/composer.json index 56bdba56ad6..4a7d56426ca 100644 --- a/Neos.ContentRepository.Core/composer.json +++ b/Neos.ContentRepository.Core/composer.json @@ -11,17 +11,17 @@ "GPL-3.0-or-later" ], "require": { - "neos/eventstore": "^1", - "neos/eventstore-doctrineadapter": "^1 || ^2", "php": "^8.2", + "neos/eventstore": "^1", "neos/error-messages": "*", "neos/utility-objecthandling": "*", "neos/utility-arrays": "*", - "doctrine/dbal": "^2.13", "symfony/serializer": "^6.3", "psr/clock": "^1", - "behat/transliterator": "~1.0", - "ramsey/uuid": "^3.0 || ^4.0" + "behat/transliterator": "^1", + "ramsey/uuid": "^3 || ^4", + "symfony/lock": "^6", + "neos/contentrepository-dbaltools": "*" }, "require-dev": { "roave/security-advisories": "dev-latest", diff --git a/Neos.ContentRepository.DbalTools/Classes/CheckpointHelper.php b/Neos.ContentRepository.DbalTools/Classes/CheckpointHelper.php new file mode 100644 index 00000000000..a6841a6f6e8 --- /dev/null +++ b/Neos.ContentRepository.DbalTools/Classes/CheckpointHelper.php @@ -0,0 +1,61 @@ +setCustomSchemaOption('check', 'CHECK (id = 0)'), + (new Column('appliedsequencenumber', Type::getType(Types::INTEGER))), + ])) + ->setPrimaryKey(['id']); + } + + public static function resetCheckpoint(Connection $connection, string $tableNamePrefix): void + { + $connection->executeStatement('INSERT INTO ' . $connection->quoteIdentifier($tableNamePrefix . self::CHECKPOINT_TABLE_NAME_SUFFIX) . ' (id, appliedsequencenumber) VALUES (0, 0) ON DUPLICATE KEY UPDATE appliedsequencenumber = 0'); + } + + public static function updateCheckpoint(Connection $connection, string $tableNamePrefix, SequenceNumber $sequenceNumber): void + { + $connection->executeStatement('UPDATE ' . $connection->quoteIdentifier($tableNamePrefix . self::CHECKPOINT_TABLE_NAME_SUFFIX) . ' SET appliedsequencenumber = :sequenceNumber WHERE id = 0', ['sequenceNumber' => $sequenceNumber->value]); + } + + public static function getCheckpoint(Connection $connection, string $tableNamePrefix): SequenceNumber + { + $highestAppliedSequenceNumber = $connection->fetchOne('SELECT appliedsequencenumber FROM ' . $connection->quoteIdentifier($tableNamePrefix . self::CHECKPOINT_TABLE_NAME_SUFFIX) . ' LIMIT 1 '); + if (!is_numeric($highestAppliedSequenceNumber)) { + throw new \RuntimeException('Failed to fetch highest applied sequence number', 1712942681); + } + return SequenceNumber::fromInteger((int)$highestAppliedSequenceNumber); + } + +} diff --git a/Neos.ContentRepository.Core/Classes/Infrastructure/DbalSchemaDiff.php b/Neos.ContentRepository.DbalTools/Classes/DbalSchemaDiff.php similarity index 97% rename from Neos.ContentRepository.Core/Classes/Infrastructure/DbalSchemaDiff.php rename to Neos.ContentRepository.DbalTools/Classes/DbalSchemaDiff.php index 1af625d9def..3202bc4067a 100644 --- a/Neos.ContentRepository.Core/Classes/Infrastructure/DbalSchemaDiff.php +++ b/Neos.ContentRepository.DbalTools/Classes/DbalSchemaDiff.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Neos\ContentRepository\Core\Infrastructure; +namespace Neos\ContentRepository\DbalTools; use Doctrine\DBAL\Connection; use Doctrine\DBAL\Exception; diff --git a/Neos.ContentRepository.Core/Classes/Infrastructure/DbalSchemaFactory.php b/Neos.ContentRepository.DbalTools/Classes/DbalSchemaFactory.php similarity index 98% rename from Neos.ContentRepository.Core/Classes/Infrastructure/DbalSchemaFactory.php rename to Neos.ContentRepository.DbalTools/Classes/DbalSchemaFactory.php index 8f2d455f009..cefa41373de 100644 --- a/Neos.ContentRepository.Core/Classes/Infrastructure/DbalSchemaFactory.php +++ b/Neos.ContentRepository.DbalTools/Classes/DbalSchemaFactory.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Neos\ContentRepository\Core\Infrastructure; +namespace Neos\ContentRepository\DbalTools; use Doctrine\DBAL\Schema\AbstractSchemaManager; use Doctrine\DBAL\Schema\Column; @@ -115,7 +115,7 @@ public static function columnForNodeTypeName(string $columnName): Column ->setCustomSchemaOption('collation', 'ascii_general_ci'); } - /** + /** * @param AbstractSchemaManager $schemaManager * @param Table[] $tables * @return Schema diff --git a/Neos.ContentRepository.DbalTools/composer.json b/Neos.ContentRepository.DbalTools/composer.json new file mode 100644 index 00000000000..702e11124fe --- /dev/null +++ b/Neos.ContentRepository.DbalTools/composer.json @@ -0,0 +1,34 @@ +{ + "name": "neos/contentrepository-dbaltools", + "type": "library", + "description": "Collection of Doctrine DBAL related tools for the neos/contentrepository-core", + "support": { + "source": "https://github.com/neos/contentrepository-dbaltools.git", + "forum": "https://discuss.neos.io/", + "docs": "https://docs.neos.io/" + }, + "license": [ + "GPL-3.0-or-later" + ], + "require": { + "php": "^8.2", + "doctrine/dbal": "^2 || ^3", + "neos/contentrepository-core": "*" + }, + "require-dev": { + "roave/security-advisories": "dev-latest", + "phpstan/phpstan": "^1.5", + "squizlabs/php_codesniffer": "^3.6", + "phpunit/phpunit": "^9.0" + }, + "autoload": { + "psr-4": { + "Neos\\ContentRepository\\DbalTools\\": "Classes" + } + }, + "autoload-dev": { + "psr-4": { + "Neos\\ContentRepository\\DbalTools\\Tests\\": "Tests" + } + } +} diff --git a/Neos.Neos/Classes/AssetUsage/Projection/AssetUsageProjection.php b/Neos.Neos/Classes/AssetUsage/Projection/AssetUsageProjection.php index 4e2a1e41a3e..9579dbb3af0 100644 --- a/Neos.Neos/Classes/AssetUsage/Projection/AssetUsageProjection.php +++ b/Neos.Neos/Classes/AssetUsage/Projection/AssetUsageProjection.php @@ -5,6 +5,7 @@ namespace Neos\Neos\AssetUsage\Projection; use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Schema\AbstractSchemaManager; use Doctrine\ORM\Exception\ORMException; use Neos\ContentRepository\Core\EventStore\EventInterface; use Neos\ContentRepository\Core\Feature\ContentStreamForking\Event\ContentStreamWasForked; @@ -19,11 +20,12 @@ use Neos\ContentRepository\Core\Feature\WorkspacePublication\Event\WorkspaceWasPartiallyPublished; use Neos\ContentRepository\Core\Feature\WorkspacePublication\Event\WorkspaceWasPublished; use Neos\ContentRepository\Core\Feature\WorkspaceRebase\Event\WorkspaceWasRebased; -use Neos\ContentRepository\Core\Infrastructure\DbalCheckpointStorage; -use Neos\ContentRepository\Core\Projection\CheckpointStorageStatusType; use Neos\ContentRepository\Core\Projection\ProjectionInterface; use Neos\ContentRepository\Core\Projection\ProjectionStatus; use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId; +use Neos\ContentRepository\DbalTools\CheckpointHelper; +use Neos\ContentRepository\DbalTools\DbalSchemaDiff; +use Neos\ContentRepository\DbalTools\DbalSchemaFactory; use Neos\EventStore\Model\Event\SequenceNumber; use Neos\EventStore\Model\EventEnvelope; use Neos\Media\Domain\Model\AssetInterface; @@ -44,29 +46,22 @@ final class AssetUsageProjection implements ProjectionInterface { private ?AssetUsageFinder $stateAccessor = null; private AssetUsageRepository $repository; - private DbalCheckpointStorage $checkpointStorage; /** @var array */ private array $originalAssetIdMappingRuntimeCache = []; public function __construct( private readonly AssetRepository $assetRepository, ContentRepositoryId $contentRepositoryId, - Connection $dbal, + private readonly Connection $dbal, AssetUsageRepositoryFactory $assetUsageRepositoryFactory, ) { $this->repository = $assetUsageRepositoryFactory->build($contentRepositoryId); - $this->checkpointStorage = new DbalCheckpointStorage( - $dbal, - $this->repository->getTableNamePrefix() . '_checkpoint', - self::class - ); } public function reset(): void { $this->repository->reset(); - $this->checkpointStorage->acquireLock(); - $this->checkpointStorage->updateAndReleaseLock(SequenceNumber::none()); + CheckpointHelper::resetCheckpoint($this->dbal, $this->repository->getTableNamePrefix()); } public function whenNodeAggregateWithNodeWasCreated(NodeAggregateWithNodeWasCreated $event, EventEnvelope $eventEnvelope): void @@ -230,18 +225,14 @@ private function extractAssetIds(string $type, mixed $value): array public function setUp(): void { $this->repository->setUp(); - $this->checkpointStorage->setUp(); + foreach ($this->determineRequiredSqlStatements() as $statement) { + $this->dbal->executeStatement($statement); + } + CheckpointHelper::resetCheckpoint($this->dbal, $this->repository->getTableNamePrefix()); } public function status(): ProjectionStatus { - $checkpointStorageStatus = $this->checkpointStorage->status(); - if ($checkpointStorageStatus->type === CheckpointStorageStatusType::ERROR) { - return ProjectionStatus::error($checkpointStorageStatus->details); - } - if ($checkpointStorageStatus->type === CheckpointStorageStatusType::SETUP_REQUIRED) { - return ProjectionStatus::setupRequired($checkpointStorageStatus->details); - } try { $falseOrDetailsString = $this->repository->isSetupRequired(); if (is_string($falseOrDetailsString)) { @@ -250,11 +241,25 @@ public function status(): ProjectionStatus } catch (\Throwable $e) { return ProjectionStatus::error(sprintf('Failed to determine required SQL statements: %s', $e->getMessage())); } + try { + $requiredSqlStatements = $this->determineRequiredSqlStatements(); + } catch (\Throwable $e) { + return ProjectionStatus::error(sprintf('Failed to determine required SQL statements: %s', $e->getMessage())); + } + if ($requiredSqlStatements !== []) { + return ProjectionStatus::setupRequired(sprintf('The following SQL statement%s required: %s', count($requiredSqlStatements) !== 1 ? 's are' : ' is', implode(chr(10), $requiredSqlStatements))); + } + try { + $this->getCheckpoint(); + } catch (\Exception $exception) { + return ProjectionStatus::error($exception->getMessage()); + } return ProjectionStatus::ok(); } public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void { + $this->dbal->beginTransaction(); match ($event::class) { NodeAggregateWithNodeWasCreated::class => $this->whenNodeAggregateWithNodeWasCreated($event, $eventEnvelope), NodePropertiesWereSet::class => $this->whenNodePropertiesWereSet($event, $eventEnvelope), @@ -269,11 +274,13 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void ContentStreamWasRemoved::class => $this->whenContentStreamWasRemoved($event), default => null, }; + CheckpointHelper::updateCheckpoint($this->dbal, $this->repository->getTableNamePrefix(), $eventEnvelope->sequenceNumber); + $this->dbal->commit(); } - public function getCheckpointStorage(): DbalCheckpointStorage + public function getCheckpoint(): SequenceNumber { - return $this->checkpointStorage; + return CheckpointHelper::getCheckpoint($this->dbal, $this->repository->getTableNamePrefix()); } public function getState(): AssetUsageFinder @@ -284,6 +291,22 @@ public function getState(): AssetUsageFinder return $this->stateAccessor; } + /** + * @return array + */ + private function determineRequiredSqlStatements(): array + { + $schemaManager = $this->dbal->getSchemaManager(); + if (!$schemaManager instanceof AbstractSchemaManager) { + throw new \RuntimeException('Failed to retrieve Schema Manager', 1625653914); + } + $checkpointTable = CheckpointHelper::checkpointTableSchema($this->repository->getTableNamePrefix()); + + $schema = DbalSchemaFactory::createSchemaWithTables($schemaManager, [$checkpointTable]); + return DbalSchemaDiff::determineRequiredSqlStatements($this->dbal, $schema); + } + + private function findOriginalAssetId(string $assetId): ?string { if (!array_key_exists($assetId, $this->originalAssetIdMappingRuntimeCache)) { diff --git a/Neos.Neos/Classes/AssetUsage/Projection/AssetUsageRepository.php b/Neos.Neos/Classes/AssetUsage/Projection/AssetUsageRepository.php index 3de07925cc1..b83a0ebf447 100644 --- a/Neos.Neos/Classes/AssetUsage/Projection/AssetUsageRepository.php +++ b/Neos.Neos/Classes/AssetUsage/Projection/AssetUsageRepository.php @@ -17,8 +17,8 @@ use Doctrine\DBAL\Types\Types; use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePointSet; use Neos\ContentRepository\Core\DimensionSpace\OriginDimensionSpacePoint; -use Neos\ContentRepository\Core\Infrastructure\DbalSchemaDiff; -use Neos\ContentRepository\Core\Infrastructure\DbalSchemaFactory; +use Neos\ContentRepository\DbalTools\DbalSchemaDiff; +use Neos\ContentRepository\DbalTools\DbalSchemaFactory; use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId; use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; use Neos\Neos\AssetUsage\Dto\AssetIdAndOriginalAssetId; diff --git a/Neos.Neos/Classes/FrontendRouting/Projection/DocumentUriPathProjection.php b/Neos.Neos/Classes/FrontendRouting/Projection/DocumentUriPathProjection.php index d1022703f28..cf53b310675 100644 --- a/Neos.Neos/Classes/FrontendRouting/Projection/DocumentUriPathProjection.php +++ b/Neos.Neos/Classes/FrontendRouting/Projection/DocumentUriPathProjection.php @@ -29,15 +29,14 @@ use Neos\ContentRepository\Core\Feature\SubtreeTagging\Event\SubtreeWasTagged; use Neos\ContentRepository\Core\Feature\SubtreeTagging\Event\SubtreeWasUntagged; use Neos\ContentRepository\Core\Feature\WorkspaceCreation\Event\RootWorkspaceWasCreated; -use Neos\ContentRepository\Core\Infrastructure\DbalCheckpointStorage; -use Neos\ContentRepository\Core\Infrastructure\DbalSchemaDiff; use Neos\ContentRepository\Core\NodeType\NodeTypeManager; use Neos\ContentRepository\Core\NodeType\NodeTypeName; -use Neos\ContentRepository\Core\Projection\CheckpointStorageStatusType; use Neos\ContentRepository\Core\Projection\ProjectionInterface; use Neos\ContentRepository\Core\Projection\ProjectionStatus; use Neos\ContentRepository\Core\Projection\WithMarkStaleInterface; use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId; +use Neos\ContentRepository\DbalTools\CheckpointHelper; +use Neos\ContentRepository\DbalTools\DbalSchemaDiff; use Neos\EventStore\Model\Event\SequenceNumber; use Neos\EventStore\Model\EventEnvelope; use Neos\Neos\Domain\Model\SiteNodeName; @@ -53,7 +52,6 @@ final class DocumentUriPathProjection implements ProjectionInterface, WithMarkSt 'shortcutTarget' => Types::JSON, ]; - private DbalCheckpointStorage $checkpointStorage; private ?DocumentUriPathFinder $stateAccessor = null; /** @@ -66,11 +64,6 @@ public function __construct( private readonly Connection $dbal, private readonly string $tableNamePrefix, ) { - $this->checkpointStorage = new DbalCheckpointStorage( - $this->dbal, - $this->tableNamePrefix . '_checkpoint', - self::class - ); } public function setUp(): void @@ -78,18 +71,11 @@ public function setUp(): void foreach ($this->determineRequiredSqlStatements() as $statement) { $this->dbal->executeStatement($statement); } - $this->checkpointStorage->setUp(); + CheckpointHelper::resetCheckpoint($this->dbal, $this->tableNamePrefix); } public function status(): ProjectionStatus { - $checkpointStorageStatus = $this->checkpointStorage->status(); - if ($checkpointStorageStatus->type === CheckpointStorageStatusType::ERROR) { - return ProjectionStatus::error($checkpointStorageStatus->details); - } - if ($checkpointStorageStatus->type === CheckpointStorageStatusType::SETUP_REQUIRED) { - return ProjectionStatus::setupRequired($checkpointStorageStatus->details); - } try { $this->dbal->connect(); } catch (\Throwable $e) { @@ -103,6 +89,11 @@ public function status(): ProjectionStatus if ($requiredSqlStatements !== []) { return ProjectionStatus::setupRequired(sprintf('The following SQL statement%s required: %s', count($requiredSqlStatements) !== 1 ? 's are' : ' is', implode(chr(10), $requiredSqlStatements))); } + try { + $this->getCheckpoint(); + } catch (\Exception $exception) { + return ProjectionStatus::error($exception->getMessage()); + } return ProjectionStatus::ok(); } @@ -123,8 +114,7 @@ private function determineRequiredSqlStatements(): array public function reset(): void { $this->truncateDatabaseTables(); - $this->checkpointStorage->acquireLock(); - $this->checkpointStorage->updateAndReleaseLock(SequenceNumber::none()); + CheckpointHelper::resetCheckpoint($this->dbal, $this->tableNamePrefix); $this->stateAccessor = null; } @@ -140,6 +130,7 @@ private function truncateDatabaseTables(): void public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void { + $this->dbal->beginTransaction(); match ($event::class) { RootWorkspaceWasCreated::class => $this->whenRootWorkspaceWasCreated($event), RootNodeAggregateWithNodeWasCreated::class => $this->whenRootNodeAggregateWithNodeWasCreated($event), @@ -158,11 +149,13 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void DimensionShineThroughWasAdded::class => $this->whenDimensionShineThroughWasAdded($event), default => null, }; + CheckpointHelper::updateCheckpoint($this->dbal, $this->tableNamePrefix, $eventEnvelope->sequenceNumber); + $this->dbal->commit(); } - public function getCheckpointStorage(): DbalCheckpointStorage + public function getCheckpoint(): SequenceNumber { - return $this->checkpointStorage; + return CheckpointHelper::getCheckpoint($this->dbal, $this->tableNamePrefix); } public function getState(): DocumentUriPathFinder diff --git a/Neos.Neos/Classes/FrontendRouting/Projection/DocumentUriPathSchemaBuilder.php b/Neos.Neos/Classes/FrontendRouting/Projection/DocumentUriPathSchemaBuilder.php index aa074353049..eb59fa3d085 100644 --- a/Neos.Neos/Classes/FrontendRouting/Projection/DocumentUriPathSchemaBuilder.php +++ b/Neos.Neos/Classes/FrontendRouting/Projection/DocumentUriPathSchemaBuilder.php @@ -8,7 +8,8 @@ use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Types; -use Neos\ContentRepository\Core\Infrastructure\DbalSchemaFactory; +use Neos\ContentRepository\DbalTools\CheckpointHelper; +use Neos\ContentRepository\DbalTools\DbalSchemaFactory; class DocumentUriPathSchemaBuilder { @@ -23,7 +24,8 @@ public function buildSchema(AbstractSchemaManager $schemaManager): Schema { $schema = DbalSchemaFactory::createSchemaWithTables($schemaManager, [ $this->createUriTable(), - $this->createLiveContentStreamsTable() + $this->createLiveContentStreamsTable(), + CheckpointHelper::checkpointTableSchema($this->tableNamePrefix), ]); return $schema; diff --git a/Neos.Neos/Classes/PendingChangesProjection/ChangeProjection.php b/Neos.Neos/Classes/PendingChangesProjection/ChangeProjection.php index 712fe2b0f89..71b2817e84e 100644 --- a/Neos.Neos/Classes/PendingChangesProjection/ChangeProjection.php +++ b/Neos.Neos/Classes/PendingChangesProjection/ChangeProjection.php @@ -35,15 +35,14 @@ use Neos\ContentRepository\Core\Feature\SubtreeTagging\Event\SubtreeWasTagged; use Neos\ContentRepository\Core\Feature\SubtreeTagging\Event\SubtreeWasUntagged; use Neos\ContentRepository\Core\Feature\WorkspaceCreation\Event\RootWorkspaceWasCreated; -use Neos\ContentRepository\Core\Infrastructure\DbalCheckpointStorage; use Neos\ContentRepository\Core\Infrastructure\DbalClientInterface; -use Neos\ContentRepository\Core\Infrastructure\DbalSchemaDiff; -use Neos\ContentRepository\Core\Infrastructure\DbalSchemaFactory; -use Neos\ContentRepository\Core\Projection\CheckpointStorageStatusType; use Neos\ContentRepository\Core\Projection\ProjectionInterface; use Neos\ContentRepository\Core\Projection\ProjectionStatus; use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId; use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; +use Neos\ContentRepository\DbalTools\CheckpointHelper; +use Neos\ContentRepository\DbalTools\DbalSchemaDiff; +use Neos\ContentRepository\DbalTools\DbalSchemaFactory; use Neos\EventStore\Model\Event\SequenceNumber; use Neos\EventStore\Model\EventEnvelope; @@ -66,17 +65,11 @@ class ChangeProjection implements ProjectionInterface * @var array|null */ private ?array $liveContentStreamIdsRuntimeCache = null; - private DbalCheckpointStorage $checkpointStorage; public function __construct( private readonly DbalClientInterface $dbalClient, private readonly string $tableNamePrefix, ) { - $this->checkpointStorage = new DbalCheckpointStorage( - $this->dbalClient->getConnection(), - $this->tableNamePrefix . '_checkpoint', - self::class - ); } @@ -85,18 +78,11 @@ public function setUp(): void foreach ($this->determineRequiredSqlStatements() as $statement) { $this->getDatabaseConnection()->executeStatement($statement); } - $this->checkpointStorage->setUp(); + CheckpointHelper::resetCheckpoint($this->getDatabaseConnection(), $this->tableNamePrefix); } public function status(): ProjectionStatus { - $checkpointStorageStatus = $this->checkpointStorage->status(); - if ($checkpointStorageStatus->type === CheckpointStorageStatusType::ERROR) { - return ProjectionStatus::error($checkpointStorageStatus->details); - } - if ($checkpointStorageStatus->type === CheckpointStorageStatusType::SETUP_REQUIRED) { - return ProjectionStatus::setupRequired($checkpointStorageStatus->details); - } try { $this->getDatabaseConnection()->connect(); } catch (\Throwable $e) { @@ -110,6 +96,11 @@ public function status(): ProjectionStatus if ($requiredSqlStatements !== []) { return ProjectionStatus::setupRequired(sprintf('The following SQL statement%s required: %s', count($requiredSqlStatements) !== 1 ? 's are' : ' is', implode(chr(10), $requiredSqlStatements))); } + try { + $this->getCheckpoint(); + } catch (\Exception $exception) { + return ProjectionStatus::error($exception->getMessage()); + } return ProjectionStatus::ok(); } @@ -149,7 +140,9 @@ private function determineRequiredSqlStatements(): array ]); $liveContentStreamsTable->setPrimaryKey(['contentstreamid']); - $schema = DbalSchemaFactory::createSchemaWithTables($schemaManager, [$changeTable, $liveContentStreamsTable]); + $checkpointTable = CheckpointHelper::checkpointTableSchema($this->tableNamePrefix); + + $schema = DbalSchemaFactory::createSchemaWithTables($schemaManager, [$changeTable, $liveContentStreamsTable, $checkpointTable]); return DbalSchemaDiff::determineRequiredSqlStatements($connection, $schema); } @@ -157,12 +150,12 @@ public function reset(): void { $this->getDatabaseConnection()->exec('TRUNCATE ' . $this->tableNamePrefix); $this->getDatabaseConnection()->exec('TRUNCATE ' . $this->tableNamePrefix . '_livecontentstreams'); - $this->checkpointStorage->acquireLock(); - $this->checkpointStorage->updateAndReleaseLock(SequenceNumber::none()); + CheckpointHelper::resetCheckpoint($this->getDatabaseConnection(), $this->tableNamePrefix); } public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void { + $this->getDatabaseConnection()->beginTransaction(); match ($event::class) { RootWorkspaceWasCreated::class => $this->whenRootWorkspaceWasCreated($event), NodeAggregateWasMoved::class => $this->whenNodeAggregateWasMoved($event), @@ -178,11 +171,13 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void NodePeerVariantWasCreated::class => $this->whenNodePeerVariantWasCreated($event), default => null, }; + CheckpointHelper::updateCheckpoint($this->getDatabaseConnection(), $this->tableNamePrefix, $eventEnvelope->sequenceNumber); + $this->getDatabaseConnection()->commit(); } - public function getCheckpointStorage(): DbalCheckpointStorage + public function getCheckpoint(): SequenceNumber { - return $this->checkpointStorage; + return CheckpointHelper::getCheckpoint($this->getDatabaseConnection(), $this->tableNamePrefix); } public function getState(): ChangeFinder diff --git a/Neos.Neos/composer.json b/Neos.Neos/composer.json index 0f61b1d8764..996a3c0657d 100644 --- a/Neos.Neos/composer.json +++ b/Neos.Neos/composer.json @@ -17,6 +17,7 @@ "neos/media-browser": "self.version", "neos/party": "~7.0.3", "neos/contentrepository-core": "self.version", + "neos/contentrepository-dbaltools": "*", "neos/contentrepositoryregistry": "self.version", "neos/contentrepository-nodeaccess": "self.version", "neos/contentrepository-export": "self.version", diff --git a/composer.json b/composer.json index b17ad9c3d79..a4231726504 100644 --- a/composer.json +++ b/composer.json @@ -58,6 +58,7 @@ "neos/contentgraph-postgresqladapter": "self.version", "neos/contentrepository-behavioraltests": "self.version", "neos/contentrepository-core": "self.version", + "neos/contentrepository-dbaltools": "self.version", "neos/contentrepository-export": "self.version", "neos/contentrepository-legacynodemigration": "self.version", "neos/contentrepository-nodeaccess": "self.version", @@ -127,7 +128,6 @@ "@test:behat-cli -c Neos.ContentRepository.LegacyNodeMigration/Tests/Behavior/behat.yml.dist", "@test:behat-cli -c Neos.ContentRepository.Export/Tests/Behavior/behat.yml.dist", "@test:behat-cli -c Neos.TimeableNodeVisibility/Tests/Behavior/behat.yml.dist", - "../../flow doctrine:migrate --quiet; ../../flow cr:setup", "@test:behat-cli -c Neos.Neos/Tests/Behavior/behat.yml" ], "test:behavioral:sync": [ @@ -140,7 +140,6 @@ "@test:behat-cli -vvv --stop-on-failure -c Neos.ContentRepository.LegacyNodeMigration/Tests/Behavior/behat.yml.dist", "@test:behat-cli -vvv --stop-on-failure -c Neos.ContentRepository.Export/Tests/Behavior/behat.yml.dist", "@test:behat-cli -vvv --stop-on-failure -c Neos.TimeableNodeVisibility/Tests/Behavior/behat.yml.dist", - "../../flow doctrine:migrate --quiet; ../../flow cr:setup", "@test:behat-cli -vvv --stop-on-failure -c Neos.Neos/Tests/Behavior/behat.yml" ], "test:behavioral:stop-on-failure:sync": [ From ad57a91b911bb6a5566b89b337f0cfc58832a376 Mon Sep 17 00:00:00 2001 From: Bastian Waidelich Date: Mon, 15 Apr 2024 12:14:31 +0200 Subject: [PATCH 08/21] Remove `DbalClientInterface` and implementations ...and use `Doctrine\DBAL\Connection` directly --- ...ectionIntegrityViolationDetectionTrait.php | 24 ++--- .../DoctrineDbalContentGraphProjection.php | 92 +++++++++---------- ...trineDbalContentGraphProjectionFactory.php | 10 +- ...tegrityViolationDetectionRunnerFactory.php | 6 +- .../ProjectionIntegrityViolationDetector.php | 44 +++++---- .../src/Domain/Repository/ContentGraph.php | 7 +- .../src/Domain/Repository/ContentSubgraph.php | 9 +- .../Repository/ProjectionContentGraph.php | 43 +++++---- .../Projection/HypergraphProjection.php | 41 ++++----- .../Projection/ProjectionHypergraph.php | 46 ++++------ .../Domain/Repository/ContentHypergraph.php | 35 +++---- .../Repository/ContentSubhypergraph.php | 26 +++--- .../src/HypergraphProjectionFactory.php | 6 +- .../PostgresDbalClientInterface.php | 25 ----- .../Command/PerformanceMeasurementService.php | 4 +- .../PerformanceMeasurementServiceFactory.php | 4 +- .../Behavior/Bootstrap/FeatureContext.php | 4 +- .../Infrastructure/DbalClientInterface.php | 19 ---- .../ContentStream/ContentStreamFinder.php | 21 ++--- .../ContentStream/ContentStreamProjection.php | 50 +++++----- .../ContentStreamProjectionFactory.php | 6 +- .../Projection/Workspace/WorkspaceFinder.php | 22 ++--- .../Workspace/WorkspaceProjection.php | 55 +++++------ .../Workspace/WorkspaceProjectionFactory.php | 6 +- .../Classes/DoctrineDbalClient.php | 66 ------------- .../Configuration/Caches.yaml | 5 - .../Configuration/Objects.yaml | 5 +- .../Configuration/Settings.yaml | 3 +- .../composer.json | 5 - .../Classes/PostgresDbalClient.php | 64 ------------- .../Configuration/Caches.yaml | 5 - .../Configuration/Objects.yaml | 2 +- .../Configuration/Settings.yaml | 9 ++ .../composer.json | 5 - .../Configuration/Caches.yaml | 5 - .../Configuration/Objects.yaml | 4 +- .../Configuration/Settings.yaml | 3 +- .../PendingChangesProjection/ChangeFinder.php | 15 +-- .../ChangeProjection.php | 54 +++++------ .../ChangeProjectionFactory.php | 6 +- composer.json | 3 + 41 files changed, 303 insertions(+), 561 deletions(-) delete mode 100644 Neos.ContentGraph.PostgreSQLAdapter/src/Infrastructure/PostgresDbalClientInterface.php delete mode 100644 Neos.ContentRepository.Core/Classes/Infrastructure/DbalClientInterface.php delete mode 100644 Neos.ContentRepositoryRegistry.DoctrineDbalClient/Classes/DoctrineDbalClient.php delete mode 100644 Neos.ContentRepositoryRegistry.DoctrineDbalClient/Configuration/Caches.yaml delete mode 100644 Neos.ContentRepositoryRegistry.PostgresDbalClient/Classes/PostgresDbalClient.php delete mode 100644 Neos.ContentRepositoryRegistry.PostgresDbalClient/Configuration/Caches.yaml create mode 100644 Neos.ContentRepositoryRegistry.PostgresDbalClient/Configuration/Settings.yaml delete mode 100644 Neos.ContentRepositoryRegistry/Configuration/Caches.yaml diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Bootstrap/ProjectionIntegrityViolationDetectionTrait.php b/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Bootstrap/ProjectionIntegrityViolationDetectionTrait.php index cb43d749e47..cb06cc09e62 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Bootstrap/ProjectionIntegrityViolationDetectionTrait.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Bootstrap/ProjectionIntegrityViolationDetectionTrait.php @@ -15,6 +15,7 @@ namespace Neos\ContentGraph\DoctrineDbalAdapter\Tests\Behavior\Features\Bootstrap; use Behat\Gherkin\Node\TableNode; +use Doctrine\DBAL\Connection; use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Exception\InvalidArgumentException; use Neos\ContentGraph\DoctrineDbalAdapter\DoctrineDbalContentGraphProjectionFactory; @@ -26,7 +27,6 @@ use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId; use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; use Neos\ContentRepository\TestSuite\Behavior\Features\Bootstrap\CRTestSuiteRuntimeVariables; -use Neos\ContentRepositoryRegistry\DoctrineDbalClient\DoctrineDbalClient; use Neos\Error\Messages\Error; use Neos\Error\Messages\Result; use PHPUnit\Framework\Assert; @@ -40,7 +40,7 @@ trait ProjectionIntegrityViolationDetectionTrait { use CRTestSuiteRuntimeVariables; - private DoctrineDbalClient $dbalClient; + private Connection $dbal; protected Result $lastIntegrityViolationDetectionResult; @@ -61,7 +61,7 @@ protected function getTableNamePrefix(): string public function setupDbalGraphAdapterIntegrityViolationTrait() { - $this->dbalClient = $this->getObject(DoctrineDbalClient::class); + $this->dbal = $this->getObject(Connection::class); } /** @@ -79,7 +79,7 @@ public function iRemoveTheFollowingSubtreeTag(TableNode $payloadTable): void if (!$subtreeTags->contain($subtreeTagToRemove)) { throw new \RuntimeException(sprintf('Failed to remove subtree tag "%s" because that tag is not set', $subtreeTagToRemove->value), 1708618267); } - $this->dbalClient->getConnection()->update( + $this->dbal->update( $this->getTableNamePrefix() . '_hierarchyrelation', [ 'subtreetags' => json_encode($subtreeTags->without($subtreeTagToRemove), JSON_THROW_ON_ERROR | JSON_FORCE_OBJECT), @@ -96,7 +96,7 @@ public function iAddTheFollowingHierarchyRelation(TableNode $payloadTable): void { $dataset = $this->transformPayloadTableToDataset($payloadTable); $record = $this->transformDatasetToHierarchyRelationRecord($dataset); - $this->dbalClient->getConnection()->insert( + $this->dbal->insert( $this->getTableNamePrefix() . '_hierarchyrelation', $record ); @@ -113,7 +113,7 @@ public function iChangeTheFollowingHierarchyRelationsDimensionSpacePointHash(Tab $record = $this->transformDatasetToHierarchyRelationRecord($dataset); unset($record['position']); - $this->dbalClient->getConnection()->update( + $this->dbal->update( $this->getTableNamePrefix() . '_hierarchyrelation', [ 'dimensionspacepointhash' => $dataset['newDimensionSpacePointHash'] @@ -133,7 +133,7 @@ public function iChangeTheFollowingHierarchyRelationsEdgeName(TableNode $payload $record = $this->transformDatasetToHierarchyRelationRecord($dataset); unset($record['position']); - $this->dbalClient->getConnection()->update( + $this->dbal->update( $this->getTableNamePrefix() . '_hierarchyrelation', [ 'name' => $dataset['newName'] @@ -157,7 +157,7 @@ public function iSetTheFollowingPosition(TableNode $payloadTable): void 'childnodeanchor' => $this->findRelationAnchorPointByDataset($dataset) ]; - $this->dbalClient->getConnection()->update( + $this->dbal->update( $this->getTableNamePrefix() . '_hierarchyrelation', [ 'position' => $dataset['newPosition'] @@ -175,7 +175,7 @@ public function iDetachTheFollowingReferenceRelationFromItsSource(TableNode $pay { $dataset = $this->transformPayloadTableToDataset($payloadTable); - $this->dbalClient->getConnection()->update( + $this->dbal->update( $this->getTableNamePrefix() . '_referencerelation', [ 'nodeanchorpoint' => 7777777 @@ -193,7 +193,7 @@ public function iSetTheFollowingReferencePosition(TableNode $payloadTable): void { $dataset = $this->transformPayloadTableToDataset($payloadTable); - $this->dbalClient->getConnection()->update( + $this->dbal->update( $this->getTableNamePrefix() . '_referencerelation', [ 'position' => $dataset['newPosition'] @@ -263,7 +263,7 @@ private function findHierarchyRelationByIds( DimensionSpacePoint $dimensionSpacePoint, NodeAggregateId $nodeAggregateId ): array { - $nodeRecord = $this->dbalClient->getConnection()->executeQuery( + $nodeRecord = $this->dbal->executeQuery( 'SELECT h.* FROM ' . $this->getTableNamePrefix() . '_node n INNER JOIN ' . $this->getTableNamePrefix() . '_hierarchyrelation h @@ -299,7 +299,7 @@ private function transformPayloadTableToDataset(TableNode $payloadTable): array */ public function iRunIntegrityViolationDetection(): void { - $projectionIntegrityViolationDetectionRunner = $this->getContentRepositoryService(new DoctrineDbalProjectionIntegrityViolationDetectionRunnerFactory($this->dbalClient)); + $projectionIntegrityViolationDetectionRunner = $this->getContentRepositoryService(new DoctrineDbalProjectionIntegrityViolationDetectionRunnerFactory($this->dbal)); $this->lastIntegrityViolationDetectionResult = $projectionIntegrityViolationDetectionRunner->run(); } diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php index eeda8919d5f..d3262df4f6b 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php @@ -5,7 +5,6 @@ namespace Neos\ContentGraph\DoctrineDbalAdapter; use Doctrine\DBAL\Connection; -use Doctrine\DBAL\Exception\UniqueConstraintViolationException; use Doctrine\DBAL\Schema\AbstractSchemaManager; use Doctrine\DBAL\Types\Types; use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Projection\Feature\NodeMove; @@ -45,9 +44,6 @@ use Neos\ContentRepository\Core\Feature\SubtreeTagging\Dto\SubtreeTags; use Neos\ContentRepository\Core\Feature\SubtreeTagging\Event\SubtreeWasTagged; use Neos\ContentRepository\Core\Feature\SubtreeTagging\Event\SubtreeWasUntagged; -use Neos\ContentRepository\Core\Infrastructure\DbalClientInterface; -use Neos\ContentRepository\DbalTools\CheckpointHelper; -use Neos\ContentRepository\DbalTools\DbalSchemaDiff; use Neos\ContentRepository\Core\NodeType\NodeTypeManager; use Neos\ContentRepository\Core\NodeType\NodeTypeName; use Neos\ContentRepository\Core\Projection\ContentGraph\NodeTags; @@ -60,6 +56,8 @@ use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId; use Neos\ContentRepository\Core\SharedModel\Node\NodeName; use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; +use Neos\ContentRepository\DbalTools\CheckpointHelper; +use Neos\ContentRepository\DbalTools\DbalSchemaDiff; use Neos\EventStore\Model\Event\SequenceNumber; use Neos\EventStore\Model\EventEnvelope; @@ -84,7 +82,7 @@ final class DoctrineDbalContentGraphProjection implements ProjectionInterface, W private ?ContentGraph $contentGraph = null; public function __construct( - private readonly DbalClientInterface $dbalClient, + private readonly Connection $dbal, private readonly NodeFactory $nodeFactory, private readonly ContentRepositoryId $contentRepositoryId, private readonly NodeTypeManager $nodeTypeManager, @@ -107,9 +105,9 @@ protected function getTableNamePrefix(): string public function setUp(): void { foreach ($this->determineRequiredSqlStatements() as $statement) { - $this->getDatabaseConnection()->executeStatement($statement); + $this->dbal->executeStatement($statement); } - CheckpointHelper::resetCheckpoint($this->getDatabaseConnection(), $this->getTableNamePrefix()); + CheckpointHelper::resetCheckpoint($this->dbal, $this->getTableNamePrefix()); } /** @@ -117,20 +115,18 @@ public function setUp(): void */ private function determineRequiredSqlStatements(): array { - $connection = $this->dbalClient->getConnection(); - $schemaManager = $connection->getSchemaManager(); + $schemaManager = $this->dbal->getSchemaManager(); if (!$schemaManager instanceof AbstractSchemaManager) { throw new \RuntimeException('Failed to retrieve Schema Manager', 1625653914); } $schema = (new DoctrineDbalContentGraphSchemaBuilder($this->tableNamePrefix))->buildSchema($schemaManager); - return DbalSchemaDiff::determineRequiredSqlStatements($connection, $schema); + return DbalSchemaDiff::determineRequiredSqlStatements($this->dbal, $schema); } public function status(): ProjectionStatus { - // TODO check checkpoint status try { - $this->getDatabaseConnection()->connect(); + $this->dbal->connect(); } catch (\Throwable $e) { return ProjectionStatus::error(sprintf('Failed to connect to database: %s', $e->getMessage())); } @@ -142,17 +138,21 @@ public function status(): ProjectionStatus if ($requiredSqlStatements !== []) { return ProjectionStatus::setupRequired(sprintf('The following SQL statement%s required: %s', count($requiredSqlStatements) !== 1 ? 's are' : ' is', implode(chr(10), $requiredSqlStatements))); } + try { + $this->getCheckpoint(); + } catch (\Exception $exception) { + return ProjectionStatus::error($exception->getMessage()); + } return ProjectionStatus::ok(); } public function reset(): void { - $connection = $this->dbalClient->getConnection(); - $connection->executeQuery('TRUNCATE table ' . $this->tableNamePrefix . '_node'); - $connection->executeQuery('TRUNCATE table ' . $this->tableNamePrefix . '_hierarchyrelation'); - $connection->executeQuery('TRUNCATE table ' . $this->tableNamePrefix . '_referencerelation'); - $connection->executeQuery('TRUNCATE table ' . $this->tableNamePrefix . '_dimensionspacepoints'); - CheckpointHelper::resetCheckpoint($this->getDatabaseConnection(), $this->getTableNamePrefix()); + $this->dbal->executeQuery('TRUNCATE table ' . $this->tableNamePrefix . '_node'); + $this->dbal->executeQuery('TRUNCATE table ' . $this->tableNamePrefix . '_hierarchyrelation'); + $this->dbal->executeQuery('TRUNCATE table ' . $this->tableNamePrefix . '_referencerelation'); + $this->dbal->executeQuery('TRUNCATE table ' . $this->tableNamePrefix . '_dimensionspacepoints'); + CheckpointHelper::resetCheckpoint($this->dbal, $this->getTableNamePrefix()); $contentGraph = $this->getState(); foreach ($contentGraph->getSubgraphs() as $subgraph) { $subgraph->inMemoryCache->enable(); @@ -161,7 +161,7 @@ public function reset(): void public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void { - $this->getDatabaseConnection()->beginTransaction(); + $this->dbal->beginTransaction(); match ($event::class) { RootNodeAggregateWithNodeWasCreated::class => $this->whenRootNodeAggregateWithNodeWasCreated($event, $eventEnvelope), RootNodeAggregateDimensionsWereUpdated::class => $this->whenRootNodeAggregateDimensionsWereUpdated($event), @@ -183,20 +183,20 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void SubtreeWasUntagged::class => $this->whenSubtreeWasUntagged($event), default => null, }; - CheckpointHelper::updateCheckpoint($this->getDatabaseConnection(), $this->getTableNamePrefix(), $eventEnvelope->sequenceNumber); - $this->getDatabaseConnection()->commit(); + CheckpointHelper::updateCheckpoint($this->dbal, $this->getTableNamePrefix(), $eventEnvelope->sequenceNumber); + $this->dbal->commit(); } public function getCheckpoint(): SequenceNumber { - return CheckpointHelper::getCheckpoint($this->getDatabaseConnection(), $this->getTableNamePrefix()); + return CheckpointHelper::getCheckpoint($this->dbal, $this->getTableNamePrefix()); } public function getState(): ContentGraph { if (!$this->contentGraph) { $this->contentGraph = new ContentGraph( - $this->dbalClient, + $this->dbal, $this->nodeFactory, $this->contentRepositoryId, $this->nodeTypeManager, @@ -221,7 +221,7 @@ private function whenRootNodeAggregateWithNodeWasCreated(RootNodeAggregateWithNo { $originDimensionSpacePoint = OriginDimensionSpacePoint::createWithoutDimensions(); $node = NodeRecord::createNewInDatabase( - $this->getDatabaseConnection(), + $this->dbal, $this->tableNamePrefix, $event->nodeAggregateId, $originDimensionSpacePoint->coordinates, @@ -265,7 +265,7 @@ private function whenRootNodeAggregateDimensionsWereUpdated(RootNodeAggregateDim } // delete all hierarchy edges of the root node - $this->getDatabaseConnection()->executeUpdate(' + $this->dbal->executeUpdate(' DELETE FROM ' . $this->tableNamePrefix . '_hierarchyrelation WHERE parentnodeanchor = :parentNodeAnchor @@ -310,7 +310,7 @@ private function whenNodeAggregateWithNodeWasCreated(NodeAggregateWithNodeWasCre */ private function whenNodeAggregateNameWasChanged(NodeAggregateNameWasChanged $event, EventEnvelope $eventEnvelope): void { - $this->getDatabaseConnection()->executeStatement(' + $this->dbal->executeStatement(' UPDATE ' . $this->tableNamePrefix . '_hierarchyrelation h INNER JOIN ' . $this->tableNamePrefix . '_node n on h.childnodeanchor = n.relationanchorpoint @@ -350,7 +350,7 @@ private function createNodeWithHierarchy( EventEnvelope $eventEnvelope, ): void { $node = NodeRecord::createNewInDatabase( - $this->getDatabaseConnection(), + $this->dbal, $this->tableNamePrefix, $nodeAggregateId, $originDimensionSpacePoint->jsonSerialize(), @@ -443,7 +443,7 @@ private function connectHierarchy( $inheritedSubtreeTags, ); - $hierarchyRelation->addToDatabase($this->getDatabaseConnection(), $this->tableNamePrefix); + $hierarchyRelation->addToDatabase($this->dbal, $this->tableNamePrefix); } } @@ -530,7 +530,7 @@ private function getRelationPositionAfterRecalculation( $position = $offset; $offset += self::RELATION_DEFAULT_OFFSET; } - $relation->assignNewPosition($offset, $this->getDatabaseConnection(), $this->tableNamePrefix); + $relation->assignNewPosition($offset, $this->dbal, $this->tableNamePrefix); } return $position; @@ -544,7 +544,7 @@ private function whenContentStreamWasForked(ContentStreamWasForked $event): void // // 1) Copy HIERARCHY RELATIONS (this is the MAIN OPERATION here) // - $this->getDatabaseConnection()->executeUpdate(' + $this->dbal->executeUpdate(' INSERT INTO ' . $this->tableNamePrefix . '_hierarchyrelation ( parentnodeanchor, childnodeanchor, @@ -576,7 +576,7 @@ private function whenContentStreamWasForked(ContentStreamWasForked $event): void private function whenContentStreamWasRemoved(ContentStreamWasRemoved $event): void { // Drop hierarchy relations - $this->getDatabaseConnection()->executeUpdate(' + $this->dbal->executeUpdate(' DELETE FROM ' . $this->tableNamePrefix . '_hierarchyrelation WHERE contentstreamid = :contentStreamId @@ -585,7 +585,7 @@ private function whenContentStreamWasRemoved(ContentStreamWasRemoved $event): vo ]); // Drop non-referenced nodes (which do not have a hierarchy relation anymore) - $this->getDatabaseConnection()->executeUpdate(' + $this->dbal->executeUpdate(' DELETE FROM ' . $this->tableNamePrefix . '_node WHERE NOT EXISTS ( @@ -596,7 +596,7 @@ private function whenContentStreamWasRemoved(ContentStreamWasRemoved $event): vo '); // Drop non-referenced reference relations (i.e. because the referenced nodes are gone by now) - $this->getDatabaseConnection()->executeUpdate(' + $this->dbal->executeUpdate(' DELETE FROM ' . $this->tableNamePrefix . '_referencerelation WHERE NOT EXISTS ( @@ -683,7 +683,7 @@ function (NodeRecord $node) use ($eventEnvelope) { ); // remove old - $this->getDatabaseConnection()->delete($this->tableNamePrefix . '_referencerelation', [ + $this->dbal->delete($this->tableNamePrefix . '_referencerelation', [ 'nodeanchorpoint' => $nodeAnchorPoint?->value, 'name' => $event->referenceName->value ]); @@ -692,7 +692,7 @@ function (NodeRecord $node) use ($eventEnvelope) { $position = 0; /** @var SerializedNodeReference $reference */ foreach ($event->references as $reference) { - $this->getDatabaseConnection()->insert($this->tableNamePrefix . '_referencerelation', [ + $this->dbal->insert($this->tableNamePrefix . '_referencerelation', [ 'name' => $event->referenceName->value, 'position' => $position, 'nodeanchorpoint' => $nodeAnchorPoint?->value, @@ -735,7 +735,7 @@ protected function copyHierarchyRelationToDimensionSpacePoint( ), $inheritedSubtreeTags, ); - $copy->addToDatabase($this->getDatabaseConnection(), $this->tableNamePrefix); + $copy->addToDatabase($this->dbal, $this->tableNamePrefix); return $copy; } @@ -749,7 +749,7 @@ protected function copyNodeToDimensionSpacePoint( EventEnvelope $eventEnvelope, ): NodeRecord { return NodeRecord::createNewInDatabase( - $this->getDatabaseConnection(), + $this->dbal, $this->tableNamePrefix, $sourceNode->nodeAggregateId, $originDimensionSpacePoint->coordinates, @@ -800,13 +800,13 @@ private function updateNodeRecordWithCopyOnWrite( // 1) fetch node, adjust properties, assign new Relation Anchor Point /** @var NodeRecord $originalNode The anchor point appears in a content stream, so there must be a node */ $originalNode = $this->projectionContentGraph->getNodeByAnchorPoint($anchorPoint); - $copiedNode = NodeRecord::createCopyFromNodeRecord($this->getDatabaseConnection(), $this->tableNamePrefix, $originalNode); + $copiedNode = NodeRecord::createCopyFromNodeRecord($this->dbal, $this->tableNamePrefix, $originalNode); $result = $operations($copiedNode); - $copiedNode->updateToDatabase($this->getDatabaseConnection(), $this->tableNamePrefix); + $copiedNode->updateToDatabase($this->dbal, $this->tableNamePrefix); // 2) reconnect all edges belonging to this content stream to the new "copied node". // IMPORTANT: We need to reconnect BOTH the incoming and outgoing edges. - $this->getDatabaseConnection()->executeStatement( + $this->dbal->executeStatement( ' UPDATE ' . $this->tableNamePrefix . '_hierarchyrelation h SET @@ -841,7 +841,7 @@ private function updateNodeRecordWithCopyOnWrite( } $result = $operations($node); - $node->updateToDatabase($this->getDatabaseConnection(), $this->tableNamePrefix); + $node->updateToDatabase($this->dbal, $this->tableNamePrefix); } return $result; } @@ -851,7 +851,7 @@ private function copyReferenceRelations( NodeRelationAnchorPoint $sourceRelationAnchorPoint, NodeRelationAnchorPoint $destinationRelationAnchorPoint ): void { - $this->getDatabaseConnection()->executeStatement(' + $this->dbal->executeStatement(' INSERT INTO ' . $this->tableNamePrefix . '_referencerelation ( nodeanchorpoint, name, @@ -880,7 +880,7 @@ private function whenDimensionSpacePointWasMoved(DimensionSpacePointWasMoved $ev // hierarchy relations for this query. Then, we update the Hierarchy Relations. // 1) originDimensionSpacePoint on Node - $rel = $this->getDatabaseConnection()->executeQuery( + $rel = $this->dbal->executeQuery( 'SELECT n.relationanchorpoint, n.origindimensionspacepointhash FROM ' . $this->tableNamePrefix . '_node n INNER JOIN ' . $this->tableNamePrefix . '_hierarchyrelation h @@ -910,7 +910,7 @@ function (NodeRecord $nodeRecord) use ($event) { } // 2) hierarchy relations - $this->getDatabaseConnection()->executeStatement( + $this->dbal->executeStatement( ' UPDATE ' . $this->tableNamePrefix . '_hierarchyrelation h SET @@ -932,7 +932,7 @@ private function whenDimensionShineThroughWasAdded(DimensionShineThroughWasAdded $this->dimensionSpacePointsRepository->insertDimensionSpacePoint($event->target); // 1) hierarchy relations - $this->getDatabaseConnection()->executeStatement( + $this->dbal->executeStatement( ' INSERT INTO ' . $this->tableNamePrefix . '_hierarchyrelation ( parentnodeanchor, @@ -965,7 +965,7 @@ private function whenDimensionShineThroughWasAdded(DimensionShineThroughWasAdded private function getDatabaseConnection(): Connection { - return $this->dbalClient->getConnection(); + return $this->dbal; } private static function initiatingDateTime(EventEnvelope $eventEnvelope): \DateTimeImmutable diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjectionFactory.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjectionFactory.php index 64891e2cc33..f667e99918d 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjectionFactory.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjectionFactory.php @@ -4,11 +4,11 @@ namespace Neos\ContentGraph\DoctrineDbalAdapter; +use Doctrine\DBAL\Connection; use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\DimensionSpacePointsRepository; use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\NodeFactory; use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\ProjectionContentGraph; use Neos\ContentRepository\Core\Factory\ProjectionFactoryDependencies; -use Neos\ContentRepository\Core\Infrastructure\DbalClientInterface; use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphProjection; use Neos\ContentRepository\Core\Projection\ProjectionFactoryInterface; use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId; @@ -23,7 +23,7 @@ final class DoctrineDbalContentGraphProjectionFactory implements ProjectionFactoryInterface { public function __construct( - private readonly DbalClientInterface $dbalClient + private readonly Connection $dbal, ) { } @@ -41,11 +41,11 @@ public function build( $projectionFactoryDependencies->contentRepositoryId ); - $dimensionSpacePointsRepository = new DimensionSpacePointsRepository($this->dbalClient->getConnection(), $tableNamePrefix); + $dimensionSpacePointsRepository = new DimensionSpacePointsRepository($this->dbal, $tableNamePrefix); return new ContentGraphProjection( new DoctrineDbalContentGraphProjection( - $this->dbalClient, + $this->dbal, new NodeFactory( $projectionFactoryDependencies->contentRepositoryId, $projectionFactoryDependencies->nodeTypeManager, @@ -55,7 +55,7 @@ public function build( $projectionFactoryDependencies->contentRepositoryId, $projectionFactoryDependencies->nodeTypeManager, new ProjectionContentGraph( - $this->dbalClient, + $this->dbal, $tableNamePrefix ), $tableNamePrefix, diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalProjectionIntegrityViolationDetectionRunnerFactory.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalProjectionIntegrityViolationDetectionRunnerFactory.php index 2808fdf6301..12cfbb567ee 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalProjectionIntegrityViolationDetectionRunnerFactory.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalProjectionIntegrityViolationDetectionRunnerFactory.php @@ -2,10 +2,10 @@ namespace Neos\ContentGraph\DoctrineDbalAdapter; +use Doctrine\DBAL\Connection; use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Projection\ProjectionIntegrityViolationDetector; use Neos\ContentRepository\Core\Factory\ContentRepositoryServiceFactoryDependencies; use Neos\ContentRepository\Core\Factory\ContentRepositoryServiceFactoryInterface; -use Neos\ContentRepository\Core\Infrastructure\DbalClientInterface; use Neos\ContentRepository\Core\Projection\ContentGraph\ProjectionIntegrityViolationDetectionRunner; /** @@ -15,7 +15,7 @@ class DoctrineDbalProjectionIntegrityViolationDetectionRunnerFactory implements ContentRepositoryServiceFactoryInterface { public function __construct( - private readonly DbalClientInterface $dbalClient + private readonly Connection $dbal, ) { } @@ -24,7 +24,7 @@ public function build( ): ProjectionIntegrityViolationDetectionRunner { return new ProjectionIntegrityViolationDetectionRunner( new ProjectionIntegrityViolationDetector( - $this->dbalClient, + $this->dbal, DoctrineDbalContentGraphProjectionFactory::graphProjectionTableNamePrefix( $serviceFactoryDependencies->contentRepositoryId ) diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/ProjectionIntegrityViolationDetector.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/ProjectionIntegrityViolationDetector.php index adb394fb6cd..df507e52cf4 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/ProjectionIntegrityViolationDetector.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/ProjectionIntegrityViolationDetector.php @@ -14,9 +14,9 @@ namespace Neos\ContentGraph\DoctrineDbalAdapter\Domain\Projection; +use Doctrine\DBAL\Connection; use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePoint; use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePointSet; -use Neos\ContentRepository\Core\Infrastructure\DbalClientInterface; use Neos\ContentRepository\Core\Projection\ContentGraph\ProjectionIntegrityViolationDetectorInterface; use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateClassification; use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId; @@ -32,7 +32,7 @@ final class ProjectionIntegrityViolationDetector implements ProjectionIntegrityViolationDetectorInterface { public function __construct( - private readonly DbalClientInterface $client, + private readonly Connection $dbal, private readonly string $tableNamePrefix ) { } @@ -44,7 +44,7 @@ public function hierarchyIntegrityIsProvided(): Result { $result = new Result(); - $disconnectedHierarchyRelationRecords = $this->client->getConnection()->executeQuery( + $disconnectedHierarchyRelationRecords = $this->dbal->executeQuery( 'SELECT h.* FROM ' . $this->tableNamePrefix . '_hierarchyrelation h LEFT JOIN ' . $this->tableNamePrefix . '_node p ON h.parentnodeanchor = p.relationanchorpoint LEFT JOIN ' . $this->tableNamePrefix . '_node c ON h.childnodeanchor = c.relationanchorpoint @@ -66,7 +66,7 @@ public function hierarchyIntegrityIsProvided(): Result )); } - $invalidlyHashedHierarchyRelationRecords = $this->client->getConnection()->executeQuery( + $invalidlyHashedHierarchyRelationRecords = $this->dbal->executeQuery( 'SELECT * FROM ' . $this->tableNamePrefix . '_hierarchyrelation h LEFT JOIN ' . $this->tableNamePrefix . '_dimensionspacepoints dsp ON dsp.hash = h.dimensionspacepointhash HAVING dsp.dimensionspacepoint IS NULL' )->fetchAllAssociative(); @@ -79,7 +79,7 @@ public function hierarchyIntegrityIsProvided(): Result )); } - $hierarchyRelationRecordsAppearingMultipleTimes = $this->client->getConnection()->executeQuery( + $hierarchyRelationRecordsAppearingMultipleTimes = $this->dbal->executeQuery( 'SELECT COUNT(*) as uniquenessCounter, h.* FROM ' . $this->tableNamePrefix . '_hierarchyrelation h LEFT JOIN ' . $this->tableNamePrefix . '_node p ON h.parentnodeanchor = p.relationanchorpoint LEFT JOIN ' . $this->tableNamePrefix . '_node c ON h.childnodeanchor = c.relationanchorpoint @@ -111,7 +111,7 @@ public function siblingsAreDistinctlySorted(): Result { $result = new Result(); - $ambiguouslySortedHierarchyRelationRecords = $this->client->getConnection()->executeQuery( + $ambiguouslySortedHierarchyRelationRecords = $this->dbal->executeQuery( 'SELECT *, COUNT(position) FROM ' . $this->tableNamePrefix . '_hierarchyrelation GROUP BY position, parentnodeanchor, contentstreamid, dimensionspacepointhash @@ -125,7 +125,7 @@ public function siblingsAreDistinctlySorted(): Result $dimensionSpacePoints = $this->findProjectedDimensionSpacePoints(); foreach ($ambiguouslySortedHierarchyRelationRecords as $hierarchyRelationRecord) { - $ambiguouslySortedNodeRecords = $this->client->getConnection()->executeQuery( + $ambiguouslySortedNodeRecords = $this->dbal->executeQuery( 'SELECT nodeaggregateid FROM ' . $this->tableNamePrefix . '_node WHERE relationanchorpoint = :relationAnchorPoint', @@ -153,7 +153,7 @@ public function siblingsAreDistinctlySorted(): Result public function tetheredNodesAreNamed(): Result { $result = new Result(); - $unnamedTetheredNodeRecords = $this->client->getConnection()->executeQuery( + $unnamedTetheredNodeRecords = $this->dbal->executeQuery( 'SELECT n.nodeaggregateid, h.contentstreamid FROM ' . $this->tableNamePrefix . '_node n INNER JOIN ' . $this->tableNamePrefix . '_hierarchyrelation h @@ -188,7 +188,7 @@ public function subtreeTagsAreInherited(): Result // NOTE: // This part determines if a parent hierarchy relation contains subtree tags that are not existing in the child relation. // This could probably be solved with JSON_ARRAY_INTERSECT(JSON_KEYS(ph.subtreetags), JSON_KEYS(h.subtreetags) but unfortunately that's only available with MariaDB 11.2+ according to https://mariadb.com/kb/en/json_array_intersect/ - $hierarchyRelationsWithMissingSubtreeTags = $this->client->getConnection()->executeQuery( + $hierarchyRelationsWithMissingSubtreeTags = $this->dbal->executeQuery( 'SELECT ph.name FROM @@ -221,7 +221,7 @@ public function referenceIntegrityIsProvided(): Result { $result = new Result(); - $referenceRelationRecordsDetachedFromSource = $this->client->getConnection()->executeQuery( + $referenceRelationRecordsDetachedFromSource = $this->dbal->executeQuery( 'SELECT * FROM ' . $this->tableNamePrefix . '_referencerelation WHERE nodeanchorpoint NOT IN ( SELECT relationanchorpoint FROM ' . $this->tableNamePrefix . '_node @@ -236,7 +236,7 @@ public function referenceIntegrityIsProvided(): Result )); } - $referenceRelationRecordsWithInvalidTarget = $this->client->getConnection()->executeQuery( + $referenceRelationRecordsWithInvalidTarget = $this->dbal->executeQuery( 'SELECT sh.contentstreamid AS contentstreamId, s.nodeaggregateid AS sourceNodeAggregateId, r.destinationnodeaggregateid AS destinationNodeAggregateId @@ -286,7 +286,7 @@ public function allNodesAreConnectedToARootNodePerSubgraph(): Result foreach ($this->findProjectedContentStreamIds() as $contentStreamId) { foreach ($this->findProjectedDimensionSpacePoints() as $dimensionSpacePoint) { - $nodeAggregateIdsInCycles = $this->client->getConnection()->executeQuery( + $nodeAggregateIdsInCycles = $this->dbal->executeQuery( 'WITH RECURSIVE subgraph AS ( SELECT h.childnodeanchor @@ -362,7 +362,7 @@ public function nodeAggregateIdsAreUniquePerSubgraph(): Result $result = new Result(); foreach ($this->findProjectedContentStreamIds() as $contentStreamId) { foreach ($this->findProjectedDimensionSpacePoints() as $dimensionSpacePoint) { - $ambiguousNodeAggregateRecords = $this->client->getConnection()->executeQuery( + $ambiguousNodeAggregateRecords = $this->dbal->executeQuery( 'SELECT n.nodeaggregateid, COUNT(n.relationanchorpoint) FROM ' . $this->tableNamePrefix . '_node n INNER JOIN ' . $this->tableNamePrefix . '_hierarchyrelation h @@ -399,7 +399,7 @@ public function allNodesHaveAtMostOneParentPerSubgraph(): Result $result = new Result(); foreach ($this->findProjectedContentStreamIds() as $contentStreamId) { foreach ($this->findProjectedDimensionSpacePoints() as $dimensionSpacePoint) { - $nodeRecordsWithMultipleParents = $this->client->getConnection()->executeQuery( + $nodeRecordsWithMultipleParents = $this->dbal->executeQuery( 'SELECT c.nodeaggregateid FROM ' . $this->tableNamePrefix . '_node c INNER JOIN ' . $this->tableNamePrefix . '_hierarchyrelation h @@ -440,7 +440,7 @@ public function nodeAggregatesAreConsistentlyTypedPerContentStream(): Result $contentStreamId ) as $nodeAggregateId ) { - $nodeAggregateRecords = $this->client->getConnection()->executeQuery( + $nodeAggregateRecords = $this->dbal->executeQuery( 'SELECT DISTINCT n.nodetypename FROM ' . $this->tableNamePrefix . '_node n INNER JOIN ' . $this->tableNamePrefix . '_hierarchyrelation h ON h.childnodeanchor = n.relationanchorpoint @@ -483,7 +483,7 @@ public function nodeAggregatesAreConsistentlyClassifiedPerContentStream(): Resul $contentStreamId ) as $nodeAggregateId ) { - $nodeAggregateRecords = $this->client->getConnection()->executeQuery( + $nodeAggregateRecords = $this->dbal->executeQuery( 'SELECT DISTINCT n.classification FROM ' . $this->tableNamePrefix . '_node n INNER JOIN ' . $this->tableNamePrefix . '_hierarchyrelation h ON h.childnodeanchor = n.relationanchorpoint @@ -521,7 +521,7 @@ public function childNodeCoverageIsASubsetOfParentNodeCoverage(): Result { $result = new Result(); foreach ($this->findProjectedContentStreamIds() as $contentStreamId) { - $excessivelyCoveringNodeRecords = $this->client->getConnection()->executeQuery( + $excessivelyCoveringNodeRecords = $this->dbal->executeQuery( 'SELECT n.nodeaggregateid, c.dimensionspacepointhash FROM ' . $this->tableNamePrefix . '_hierarchyrelation c INNER JOIN ' . $this->tableNamePrefix . '_node n @@ -558,7 +558,7 @@ public function allNodesCoverTheirOrigin(): Result { $result = new Result(); foreach ($this->findProjectedContentStreamIds() as $contentStreamId) { - $nodeRecordsWithMissingOriginCoverage = $this->client->getConnection()->executeQuery( + $nodeRecordsWithMissingOriginCoverage = $this->dbal->executeQuery( 'SELECT nodeaggregateid, origindimensionspacepointhash FROM ' . $this->tableNamePrefix . '_node n INNER JOIN ' . $this->tableNamePrefix . '_hierarchyrelation h @@ -602,9 +602,7 @@ public function allNodesCoverTheirOrigin(): Result */ protected function findProjectedContentStreamIds(): iterable { - $connection = $this->client->getConnection(); - - $rows = $connection->executeQuery( + $rows = $this->dbal->executeQuery( 'SELECT DISTINCT contentstreamid FROM ' . $this->tableNamePrefix . '_hierarchyrelation' )->fetchAllAssociative(); @@ -620,7 +618,7 @@ protected function findProjectedContentStreamIds(): iterable */ protected function findProjectedDimensionSpacePoints(): DimensionSpacePointSet { - $records = $this->client->getConnection()->executeQuery( + $records = $this->dbal->executeQuery( 'SELECT dimensionspacepoint FROM ' . $this->tableNamePrefix . '_dimensionspacepoints' )->fetchAllAssociative(); @@ -638,7 +636,7 @@ protected function findProjectedDimensionSpacePoints(): DimensionSpacePointSet protected function findProjectedNodeAggregateIdsInContentStream( ContentStreamId $contentStreamId ): array { - $records = $this->client->getConnection()->executeQuery( + $records = $this->dbal->executeQuery( 'SELECT DISTINCT nodeaggregateid FROM ' . $this->tableNamePrefix . '_node' )->fetchAllAssociative(); diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ContentGraph.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ContentGraph.php index 1df35d06fa3..151493b9d88 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ContentGraph.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ContentGraph.php @@ -24,7 +24,6 @@ use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePoint; use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePointSet; use Neos\ContentRepository\Core\DimensionSpace\OriginDimensionSpacePoint; -use Neos\ContentRepository\Core\Infrastructure\DbalClientInterface; use Neos\ContentRepository\Core\NodeType\NodeTypeManager; use Neos\ContentRepository\Core\NodeType\NodeTypeName; use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphInterface; @@ -70,7 +69,7 @@ final class ContentGraph implements ContentGraphInterface private array $subgraphs = []; public function __construct( - private readonly DbalClientInterface $client, + private readonly Connection $dbal, private readonly NodeFactory $nodeFactory, private readonly ContentRepositoryId $contentRepositoryId, private readonly NodeTypeManager $nodeTypeManager, @@ -91,7 +90,7 @@ final public function getSubgraph( $contentStreamId, $dimensionSpacePoint, $visibilityConstraints, - $this->client, + $this->dbal, $this->nodeFactory, $this->nodeTypeManager, $this->tableNamePrefix @@ -395,7 +394,7 @@ private function buildChildNodeAggregateQuery(NodeAggregateId $parentNodeAggrega private function createQueryBuilder(): QueryBuilder { - return $this->client->getConnection()->createQueryBuilder(); + return $this->dbal->createQueryBuilder(); } /** diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ContentSubgraph.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ContentSubgraph.php index c1a278822d7..2210f9c6ca5 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ContentSubgraph.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ContentSubgraph.php @@ -21,7 +21,6 @@ use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\Query\QueryBuilder; use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePoint; -use Neos\ContentRepository\Core\Infrastructure\DbalClientInterface; use Neos\ContentRepository\Core\NodeType\NodeTypeManager; use Neos\ContentRepository\Core\NodeType\NodeTypeName; use Neos\ContentRepository\Core\Projection\ContentGraph\AbsoluteNodePath; @@ -108,7 +107,7 @@ public function __construct( private readonly ContentStreamId $contentStreamId, private readonly DimensionSpacePoint $dimensionSpacePoint, private readonly VisibilityConstraints $visibilityConstraints, - private readonly DbalClientInterface $client, + private readonly Connection $dbal, private readonly NodeFactory $nodeFactory, private readonly NodeTypeManager $nodeTypeManager, private readonly string $tableNamePrefix @@ -485,7 +484,7 @@ private function findNodeByPathFromStartingNode(NodePath $path, Node $startingNo private function createQueryBuilder(): QueryBuilder { - return $this->client->getConnection()->createQueryBuilder(); + return $this->dbal->createQueryBuilder(); } private function createUniqueParameterName(): string @@ -907,7 +906,7 @@ private function fetchCteResults(QueryBuilder $queryBuilderInitial, QueryBuilder $parameters = array_merge($queryBuilderInitial->getParameters(), $queryBuilderRecursive->getParameters(), $queryBuilderCte->getParameters()); $parameterTypes = array_merge($queryBuilderInitial->getParameterTypes(), $queryBuilderRecursive->getParameterTypes(), $queryBuilderCte->getParameterTypes()); try { - return $this->client->getConnection()->fetchAllAssociative($query, $parameters, $parameterTypes); + return $this->dbal->fetchAllAssociative($query, $parameters, $parameterTypes); } catch (DbalException $e) { throw new \RuntimeException(sprintf('Failed to fetch CTE result: %s', $e->getMessage()), 1678358108, $e); } @@ -919,7 +918,7 @@ private function fetchCteCountResult(QueryBuilder $queryBuilderInitial, QueryBui $parameters = array_merge($queryBuilderInitial->getParameters(), $queryBuilderRecursive->getParameters(), $queryBuilderCte->getParameters()); $parameterTypes = array_merge($queryBuilderInitial->getParameterTypes(), $queryBuilderRecursive->getParameterTypes(), $queryBuilderCte->getParameterTypes()); try { - return (int)$this->client->getConnection()->fetchOne($query, $parameters, $parameterTypes); + return (int)$this->dbal->fetchOne($query, $parameters, $parameterTypes); } catch (DbalException $e) { throw new \RuntimeException(sprintf('Failed to fetch CTE count result: %s', $e->getMessage()), 1679047841, $e); } diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ProjectionContentGraph.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ProjectionContentGraph.php index 02e6b63e5b9..af55d407613 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ProjectionContentGraph.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ProjectionContentGraph.php @@ -24,7 +24,6 @@ use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePoint; use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePointSet; use Neos\ContentRepository\Core\DimensionSpace\OriginDimensionSpacePoint; -use Neos\ContentRepository\Core\Infrastructure\DbalClientInterface; use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId; use Neos\ContentRepository\Core\SharedModel\Node\NodeName; use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; @@ -40,7 +39,7 @@ class ProjectionContentGraph { public function __construct( - private readonly DbalClientInterface $client, + private readonly Connection $dbal, private readonly string $tableNamePrefix ) { } @@ -70,7 +69,7 @@ public function findParentNode( ? $coveredDimensionSpacePoint->hash : $originDimensionSpacePoint->hash ]; - $nodeRow = $this->getDatabaseConnection()->executeQuery( + $nodeRow = $this->dbal->executeQuery( 'SELECT p.*, ph.contentstreamid, ph.name, ph.subtreetags, dsp.dimensionspacepoint AS origindimensionspacepoint FROM ' . $this->tableNamePrefix . '_node p INNER JOIN ' . $this->tableNamePrefix . '_hierarchyrelation ph ON ph.childnodeanchor = p.relationanchorpoint INNER JOIN ' . $this->tableNamePrefix . '_hierarchyrelation ch ON ch.parentnodeanchor = p.relationanchorpoint @@ -101,7 +100,7 @@ public function findNodeInAggregate( NodeAggregateId $nodeAggregateId, DimensionSpacePoint $coveredDimensionSpacePoint ): ?NodeRecord { - $nodeRow = $this->getDatabaseConnection()->executeQuery( + $nodeRow = $this->dbal->executeQuery( 'SELECT n.*, h.name, h.subtreetags, dsp.dimensionspacepoint AS origindimensionspacepoint FROM ' . $this->tableNamePrefix . '_node n INNER JOIN ' . $this->tableNamePrefix . '_hierarchyrelation h ON h.childnodeanchor = n.relationanchorpoint INNER JOIN ' . $this->tableNamePrefix . '_dimensionspacepoints dsp ON n.origindimensionspacepointhash = dsp.hash @@ -130,7 +129,7 @@ public function findNodeByIds( NodeAggregateId $nodeAggregateId, OriginDimensionSpacePoint $originDimensionSpacePoint ): ?NodeRecord { - $nodeRow = $this->getDatabaseConnection()->executeQuery( + $nodeRow = $this->dbal->executeQuery( 'SELECT n.*, h.name, h.subtreetags, dsp.dimensionspacepoint AS origindimensionspacepoint FROM ' . $this->tableNamePrefix . '_node n INNER JOIN ' . $this->tableNamePrefix . '_hierarchyrelation h ON h.childnodeanchor = n.relationanchorpoint INNER JOIN ' . $this->tableNamePrefix . '_dimensionspacepoints dsp ON n.origindimensionspacepointhash = dsp.hash @@ -159,7 +158,7 @@ public function getAnchorPointForNodeAndOriginDimensionSpacePointAndContentStrea OriginDimensionSpacePoint $originDimensionSpacePoint, ContentStreamId $contentStreamId ): ?NodeRelationAnchorPoint { - $rows = $this->getDatabaseConnection()->executeQuery( + $rows = $this->dbal->executeQuery( 'SELECT DISTINCT n.relationanchorpoint FROM ' . $this->tableNamePrefix . '_node n INNER JOIN ' . $this->tableNamePrefix . '_hierarchyrelation h ON h.childnodeanchor = n.relationanchorpoint WHERE n.nodeaggregateid = :nodeAggregateId @@ -194,7 +193,7 @@ public function getAnchorPointsForNodeAggregateInContentStream( NodeAggregateId $nodeAggregateId, ContentStreamId $contentStreamId ): iterable { - $rows = $this->getDatabaseConnection()->executeQuery( + $rows = $this->dbal->executeQuery( 'SELECT DISTINCT n.relationanchorpoint FROM ' . $this->tableNamePrefix . '_node n INNER JOIN ' . $this->tableNamePrefix . '_hierarchyrelation h ON h.childnodeanchor = n.relationanchorpoint WHERE n.nodeaggregateid = :nodeAggregateId @@ -218,7 +217,7 @@ public function getAnchorPointsForNodeAggregateInContentStream( */ public function getNodeByAnchorPoint(NodeRelationAnchorPoint $nodeRelationAnchorPoint): ?NodeRecord { - $nodeRow = $this->getDatabaseConnection()->executeQuery( + $nodeRow = $this->dbal->executeQuery( 'SELECT n.*, dsp.dimensionspacepoint AS origindimensionspacepoint FROM ' . $this->tableNamePrefix . '_node n INNER JOIN ' . $this->tableNamePrefix . '_dimensionspacepoints dsp ON n.origindimensionspacepointhash = dsp.hash WHERE n.relationanchorpoint = :relationAnchorPoint', @@ -254,7 +253,7 @@ public function determineHierarchyRelationPosition( } if ($succeedingSiblingAnchorPoint) { /** @var array $succeedingSiblingRelation */ - $succeedingSiblingRelation = $this->getDatabaseConnection()->executeQuery( + $succeedingSiblingRelation = $this->dbal->executeQuery( 'SELECT h.* FROM ' . $this->tableNamePrefix . '_hierarchyrelation h WHERE h.childnodeanchor = :succeedingSiblingAnchorPoint AND h.contentstreamid = :contentStreamId @@ -269,7 +268,7 @@ public function determineHierarchyRelationPosition( $succeedingSiblingPosition = (int)$succeedingSiblingRelation['position']; $parentAnchorPoint = NodeRelationAnchorPoint::fromInteger($succeedingSiblingRelation['parentnodeanchor']); - $precedingSiblingData = $this->getDatabaseConnection()->executeQuery( + $precedingSiblingData = $this->dbal->executeQuery( 'SELECT MAX(h.position) AS position FROM ' . $this->tableNamePrefix . '_hierarchyrelation h WHERE h.parentnodeanchor = :anchorPoint AND h.contentstreamid = :contentStreamId @@ -295,7 +294,7 @@ public function determineHierarchyRelationPosition( } else { if (!$parentAnchorPoint) { /** @var array $childHierarchyRelationData */ - $childHierarchyRelationData = $this->getDatabaseConnection()->executeQuery( + $childHierarchyRelationData = $this->dbal->executeQuery( 'SELECT h.parentnodeanchor FROM ' . $this->tableNamePrefix . '_hierarchyrelation h WHERE h.childnodeanchor = :childAnchorPoint AND h.contentstreamid = :contentStreamId @@ -310,7 +309,7 @@ public function determineHierarchyRelationPosition( $childHierarchyRelationData['parentnodeanchor'] ); } - $rightmostSucceedingSiblingRelationData = $this->getDatabaseConnection()->executeQuery( + $rightmostSucceedingSiblingRelationData = $this->dbal->executeQuery( 'SELECT MAX(h.position) AS position FROM ' . $this->tableNamePrefix . '_hierarchyrelation h WHERE h.parentnodeanchor = :parentAnchorPoint AND h.contentstreamid = :contentStreamId @@ -347,7 +346,7 @@ public function getOutgoingHierarchyRelationsForNodeAndSubgraph( ): array { $relations = []; foreach ( - $this->getDatabaseConnection()->executeQuery( + $this->dbal->executeQuery( 'SELECT h.* FROM ' . $this->tableNamePrefix . '_hierarchyrelation h WHERE h.parentnodeanchor = :parentAnchorPoint AND h.contentstreamid = :contentStreamId @@ -379,7 +378,7 @@ public function getIngoingHierarchyRelationsForNodeAndSubgraph( ): array { $relations = []; foreach ( - $this->getDatabaseConnection()->executeQuery( + $this->dbal->executeQuery( 'SELECT h.* FROM ' . $this->tableNamePrefix . '_hierarchyrelation h WHERE h.childnodeanchor = :childAnchorPoint AND h.contentstreamid = :contentStreamId @@ -426,7 +425,7 @@ public function findIngoingHierarchyRelationsForNode( $types['dimensionSpacePointHashes'] = Connection::PARAM_STR_ARRAY; } foreach ( - $this->getDatabaseConnection()->executeQuery($query, $parameters, $types) + $this->dbal->executeQuery($query, $parameters, $types) ->fetchAllAssociative() as $relationData ) { $relations[$relationData['dimensionspacepointhash']] = $this->mapRawDataToHierarchyRelation($relationData); @@ -464,7 +463,7 @@ public function findOutgoingHierarchyRelationsForNode( $types['dimensionSpacePointHashes'] = Connection::PARAM_STR_ARRAY; } foreach ( - $this->getDatabaseConnection()->executeQuery($query, $parameters, $types) + $this->dbal->executeQuery($query, $parameters, $types) ->fetchAllAssociative() as $relationData ) { $relations[$relationData['dimensionspacepointhash']] = $this->mapRawDataToHierarchyRelation($relationData); @@ -487,7 +486,7 @@ public function findOutgoingHierarchyRelationsForNodeAggregate( ): array { $relations = []; foreach ( - $this->getDatabaseConnection()->executeQuery( + $this->dbal->executeQuery( 'SELECT h.* FROM ' . $this->tableNamePrefix . '_hierarchyrelation h INNER JOIN ' . $this->tableNamePrefix . '_node n ON h.parentnodeanchor = n.relationanchorpoint WHERE n.nodeaggregateid = :nodeAggregateId @@ -541,7 +540,7 @@ public function findIngoingHierarchyRelationsForNodeAggregate( } foreach ( - $this->getDatabaseConnection()->executeQuery($query, $parameters, $types) + $this->dbal->executeQuery($query, $parameters, $types) ->fetchAllAssociative() as $relationData ) { $relations[] = $this->mapRawDataToHierarchyRelation($relationData); @@ -559,7 +558,7 @@ public function getAllContentStreamIdsAnchorPointIsContainedIn( ): array { $contentStreamIds = []; foreach ( - $this->getDatabaseConnection()->executeQuery( + $this->dbal->executeQuery( 'SELECT DISTINCT h.contentstreamid FROM ' . $this->tableNamePrefix . '_hierarchyrelation h WHERE h.childnodeanchor = :nodeRelationAnchorPoint', @@ -588,7 +587,7 @@ public function findDescendantNodeAggregateIds( NodeAggregateId $entryNodeAggregateId, DimensionSpacePointSet $affectedDimensionSpacePoints ): array { - $rows = $this->getDatabaseConnection()->executeQuery( + $rows = $this->dbal->executeQuery( ' -- ProjectionContentGraph::findDescendantNodeAggregateIds @@ -652,7 +651,7 @@ public function findDescendantNodeAggregateIds( */ protected function mapRawDataToHierarchyRelation(array $rawData): HierarchyRelation { - $dimensionspacepointRaw = $this->client->getConnection()->fetchOne('SELECT dimensionspacepoint FROM ' . $this->tableNamePrefix . '_dimensionspacepoints WHERE hash = :hash', ['hash' => $rawData['dimensionspacepointhash']]); + $dimensionspacepointRaw = $this->dbal->fetchOne('SELECT dimensionspacepoint FROM ' . $this->tableNamePrefix . '_dimensionspacepoints WHERE hash = :hash', ['hash' => $rawData['dimensionspacepointhash']]); return new HierarchyRelation( NodeRelationAnchorPoint::fromInteger((int)$rawData['parentnodeanchor']), @@ -671,6 +670,6 @@ protected function mapRawDataToHierarchyRelation(array $rawData): HierarchyRelat */ protected function getDatabaseConnection(): Connection { - return $this->client->getConnection(); + return $this->dbal; } } diff --git a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/HypergraphProjection.php b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/HypergraphProjection.php index 4a14652359f..bd498de6da6 100644 --- a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/HypergraphProjection.php +++ b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/HypergraphProjection.php @@ -28,7 +28,6 @@ use Neos\ContentGraph\PostgreSQLAdapter\Domain\Projection\SchemaBuilder\HypergraphSchemaBuilder; use Neos\ContentGraph\PostgreSQLAdapter\Domain\Repository\ContentHypergraph; use Neos\ContentGraph\PostgreSQLAdapter\Domain\Repository\NodeFactory; -use Neos\ContentGraph\PostgreSQLAdapter\Infrastructure\PostgresDbalClientInterface; use Neos\ContentRepository\Core\EventStore\EventInterface; use Neos\ContentRepository\Core\Feature\ContentStreamForking\Event\ContentStreamWasForked; use Neos\ContentRepository\Core\Feature\NodeCreation\Event\NodeAggregateWithNodeWasCreated; @@ -78,22 +77,22 @@ final class HypergraphProjection implements ProjectionInterface private ProjectionHypergraph $projectionHypergraph; public function __construct( - private readonly PostgresDbalClientInterface $databaseClient, + private readonly Connection $dbal, private readonly NodeFactory $nodeFactory, private readonly ContentRepositoryId $contentRepositoryId, private readonly NodeTypeManager $nodeTypeManager, private readonly string $tableNamePrefix, ) { - $this->projectionHypergraph = new ProjectionHypergraph($this->databaseClient, $this->tableNamePrefix); + $this->projectionHypergraph = new ProjectionHypergraph($this->dbal, $this->tableNamePrefix); } public function setUp(): void { foreach ($this->determineRequiredSqlStatements() as $statement) { - $this->getDatabaseConnection()->executeStatement($statement); + $this->dbal->executeStatement($statement); } - $this->getDatabaseConnection()->executeStatement(' + $this->dbal->executeStatement(' CREATE INDEX IF NOT EXISTS node_properties ON ' . $this->tableNamePrefix . '_node USING GIN(properties); create index if not exists hierarchy_children @@ -107,7 +106,7 @@ public function setUp(): void public function status(): ProjectionStatus { try { - $this->getDatabaseConnection()->connect(); + $this->dbal->connect(); } catch (\Throwable $e) { return ProjectionStatus::error(sprintf('Failed to connect to database: %s', $e->getMessage())); } @@ -132,22 +131,21 @@ public function status(): ProjectionStatus */ private function determineRequiredSqlStatements(): array { - $connection = $this->databaseClient->getConnection(); - HypergraphSchemaBuilder::registerTypes($connection->getDatabasePlatform()); - $schemaManager = $connection->getSchemaManager(); + HypergraphSchemaBuilder::registerTypes($this->dbal->getDatabasePlatform()); + $schemaManager = $this->dbal->getSchemaManager(); if (!$schemaManager instanceof AbstractSchemaManager) { throw new \RuntimeException('Failed to retrieve Schema Manager', 1625653914); } $schema = (new HypergraphSchemaBuilder($this->tableNamePrefix))->buildSchema(); - return DbalSchemaDiff::determineRequiredSqlStatements($connection, $schema); + return DbalSchemaDiff::determineRequiredSqlStatements($this->dbal, $schema); } public function reset(): void { $this->truncateDatabaseTables(); - CheckpointHelper::resetCheckpoint($this->getDatabaseConnection(), $this->tableNamePrefix); + CheckpointHelper::resetCheckpoint($this->dbal, $this->tableNamePrefix); //$contentGraph = $this->getState(); //foreach ($contentGraph->getSubgraphs() as $subgraph) { @@ -157,16 +155,15 @@ public function reset(): void private function truncateDatabaseTables(): void { - $connection = $this->databaseClient->getConnection(); - $connection->executeQuery('TRUNCATE table ' . $this->tableNamePrefix . '_node'); - $connection->executeQuery('TRUNCATE table ' . $this->tableNamePrefix . '_hierarchyhyperrelation'); - $connection->executeQuery('TRUNCATE table ' . $this->tableNamePrefix . '_referencerelation'); - $connection->executeQuery('TRUNCATE table ' . $this->tableNamePrefix . '_restrictionhyperrelation'); + $this->dbal->executeQuery('TRUNCATE table ' . $this->tableNamePrefix . '_node'); + $this->dbal->executeQuery('TRUNCATE table ' . $this->tableNamePrefix . '_hierarchyhyperrelation'); + $this->dbal->executeQuery('TRUNCATE table ' . $this->tableNamePrefix . '_referencerelation'); + $this->dbal->executeQuery('TRUNCATE table ' . $this->tableNamePrefix . '_restrictionhyperrelation'); } public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void { - $this->getDatabaseConnection()->beginTransaction(); + $this->dbal->beginTransaction(); match ($event::class) { // ContentStreamForking ContentStreamWasForked::class => $this->whenContentStreamWasForked($event), @@ -192,20 +189,20 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void NodePeerVariantWasCreated::class => $this->whenNodePeerVariantWasCreated($event), default => null, }; - CheckpointHelper::updateCheckpoint($this->getDatabaseConnection(), $this->tableNamePrefix, $eventEnvelope->sequenceNumber); - $this->getDatabaseConnection()->commit(); + CheckpointHelper::updateCheckpoint($this->dbal, $this->tableNamePrefix, $eventEnvelope->sequenceNumber); + $this->dbal->commit(); } public function getCheckpoint(): SequenceNumber { - return CheckpointHelper::getCheckpoint($this->getDatabaseConnection(), $this->tableNamePrefix); + return CheckpointHelper::getCheckpoint($this->dbal, $this->tableNamePrefix); } public function getState(): ContentHypergraph { if (!$this->contentHypergraph) { $this->contentHypergraph = new ContentHypergraph( - $this->databaseClient, + $this->dbal, $this->nodeFactory, $this->contentRepositoryId, $this->nodeTypeManager, @@ -222,6 +219,6 @@ protected function getProjectionHypergraph(): ProjectionHypergraph protected function getDatabaseConnection(): Connection { - return $this->databaseClient->getConnection(); + return $this->dbal; } } diff --git a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/ProjectionHypergraph.php b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/ProjectionHypergraph.php index 07359ca5709..9be0b94d7d4 100644 --- a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/ProjectionHypergraph.php +++ b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/ProjectionHypergraph.php @@ -17,7 +17,6 @@ use Doctrine\DBAL\Connection; use Doctrine\DBAL\Exception as DBALException; use Neos\ContentGraph\PostgreSQLAdapter\Domain\Projection\Query\ProjectionHypergraphQuery; -use Neos\ContentGraph\PostgreSQLAdapter\Infrastructure\PostgresDbalClientInterface; use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePoint; use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePointSet; use Neos\ContentRepository\Core\DimensionSpace\OriginDimensionSpacePoint; @@ -32,7 +31,7 @@ final class ProjectionHypergraph { public function __construct( - private readonly PostgresDbalClientInterface $databaseClient, + private readonly Connection $dbal, private readonly string $tableNamePrefix ) { } @@ -55,7 +54,7 @@ public function findNodeRecordByRelationAnchorPoint( 'relationAnchorPoint' => $relationAnchorPoint->value ]; - $result = $this->getDatabaseConnection()->executeQuery($query, $parameters)->fetchAssociative(); + $result = $this->dbal->executeQuery($query, $parameters)->fetchAssociative(); return $result ? NodeRecord::fromDatabaseRow($result) : null; } @@ -71,7 +70,7 @@ public function findNodeRecordByCoverage( $query = ProjectionHypergraphQuery::create($contentStreamId, $this->tableNamePrefix); $query = $query->withDimensionSpacePoint($dimensionSpacePoint) ->withNodeAggregateId($nodeAggregateId); - $result = $query->execute($this->getDatabaseConnection())->fetchAssociative(); + $result = $query->execute($this->dbal)->fetchAssociative(); return $result ? NodeRecord::fromDatabaseRow($result) : null; } @@ -88,7 +87,7 @@ public function findNodeRecordByOrigin( $query = $query->withOriginDimensionSpacePoint($originDimensionSpacePoint); $query = $query->withNodeAggregateId($nodeAggregateId); - $result = $query->execute($this->getDatabaseConnection())->fetchAssociative(); + $result = $query->execute($this->dbal)->fetchAssociative(); return $result ? NodeRecord::fromDatabaseRow($result) : null; } @@ -118,7 +117,7 @@ public function findParentNodeRecordByOrigin( 'childNodeAggregateId' => $childNodeAggregateId->value ]; - $result = $this->getDatabaseConnection() + $result = $this->dbal ->executeQuery($query, $parameters) ->fetchAssociative(); @@ -171,7 +170,7 @@ public function findParentNodeRecordByCoverage( 'childNodeAggregateId' => $childNodeAggregateId->value ]; - $result = $this->getDatabaseConnection() + $result = $this->dbal ->executeQuery($query, $parameters) ->fetchAssociative(); @@ -189,7 +188,7 @@ public function findNodeRecordsForNodeAggregate( $query = ProjectionHypergraphQuery::create($contentStreamId, $this->tableNamePrefix); $query = $query->withNodeAggregateId($nodeAggregateId); - $result = $query->execute($this->getDatabaseConnection())->fetchAllAssociative(); + $result = $query->execute($this->dbal)->fetchAllAssociative(); return array_map(function ($row) { return NodeRecord::fromDatabaseRow($row); @@ -224,7 +223,7 @@ public function findIngoingHierarchyHyperrelationRecords( } $hierarchyHyperrelations = []; - foreach ($this->getDatabaseConnection()->executeQuery($query, $parameters, $types) as $row) { + foreach ($this->dbal->executeQuery($query, $parameters, $types) as $row) { $hierarchyHyperrelations[] = HierarchyHyperrelationRecord::fromDatabaseRow($row); } @@ -259,7 +258,7 @@ public function findOutgoingHierarchyHyperrelationRecords( $types['affectedDimensionSpacePointHashes'] = Connection::PARAM_STR_ARRAY; $hierarchyHyperrelations = []; - foreach ($this->getDatabaseConnection()->executeQuery($query, $parameters, $types) as $row) { + foreach ($this->dbal->executeQuery($query, $parameters, $types) as $row) { $hierarchyHyperrelations[] = HierarchyHyperrelationRecord::fromDatabaseRow($row); } @@ -283,7 +282,7 @@ public function findOutgoingReferenceHyperrelationRecords( ]; $referenceHyperrelations = []; - foreach ($this->getDatabaseConnection()->executeQuery($query, $parameters) as $row) { + foreach ($this->dbal->executeQuery($query, $parameters) as $row) { $referenceHyperrelations[] = ReferenceRelationRecord::fromDatabaseRow($row); } @@ -312,7 +311,7 @@ public function findHierarchyHyperrelationRecordByParentNodeAnchor( 'parentNodeAnchor' => $parentNodeAnchor->value ]; - $result = $this->getDatabaseConnection()->executeQuery($query, $parameters)->fetchAssociative(); + $result = $this->dbal->executeQuery($query, $parameters)->fetchAssociative(); return $result ? HierarchyHyperrelationRecord::fromDatabaseRow($result) : null; } @@ -339,7 +338,7 @@ public function findHierarchyHyperrelationRecordByChildNodeAnchor( 'childNodeAnchor' => $childNodeAnchor->value ]; - $result = $this->getDatabaseConnection()->executeQuery($query, $parameters)->fetchAssociative(); + $result = $this->dbal->executeQuery($query, $parameters)->fetchAssociative(); return $result ? HierarchyHyperrelationRecord::fromDatabaseRow($result) : null; } @@ -362,7 +361,7 @@ public function findHierarchyHyperrelationRecordsByChildNodeAnchor( ]; $hierarchyRelationRecords = []; - $result = $this->getDatabaseConnection()->executeQuery($query, $parameters)->fetchAllAssociative(); + $result = $this->dbal->executeQuery($query, $parameters)->fetchAllAssociative(); foreach ($result as $row) { $hierarchyRelationRecords[] = HierarchyHyperrelationRecord::fromDatabaseRow($row); } @@ -393,7 +392,7 @@ public function findChildHierarchyHyperrelationRecord( 'dimensionSpacePointHash' => $dimensionSpacePoint->hash ]; - $result = $this->getDatabaseConnection()->executeQuery($query, $parameters)->fetchAssociative(); + $result = $this->dbal->executeQuery($query, $parameters)->fetchAssociative(); return $result ? HierarchyHyperrelationRecord::fromDatabaseRow($result) : null; } @@ -421,7 +420,7 @@ public function findCoverageByNodeRelationAnchorPoint( ]; $dimensionSpacePoints = []; - foreach ($this->getDatabaseConnection()->executeQuery($query, $parameters)->fetchAllAssociative() as $row) { + foreach ($this->dbal->executeQuery($query, $parameters)->fetchAllAssociative() as $row) { $dimensionSpacePoints[] = DimensionSpacePoint::fromJsonString($row['dimensionspacepoint']); } @@ -451,7 +450,7 @@ public function findCoverageByNodeAggregateId( ]; $dimensionSpacePoints = []; - foreach ($this->getDatabaseConnection()->executeQuery($query, $parameters)->fetchAllAssociative() as $row) { + foreach ($this->dbal->executeQuery($query, $parameters)->fetchAllAssociative() as $row) { $dimensionSpacePoints[] = DimensionSpacePoint::fromJsonString($row['dimensionspacepoint']); } @@ -489,7 +488,7 @@ public function findOutgoingRestrictionRelations( $restrictionRelationRecords = []; foreach ( - $this->getDatabaseConnection()->executeQuery($query, $parameters, $types) + $this->dbal->executeQuery($query, $parameters, $types) ->fetchAllAssociative() as $row ) { $restrictionRelationRecords[] = RestrictionHyperrelationRecord::fromDatabaseRow($row); @@ -522,7 +521,7 @@ public function findIngoingRestrictionRelations( ]; $restrictionRelations = []; - $rows = $this->getDatabaseConnection()->executeQuery($query, $parameters)->fetchAllAssociative(); + $rows = $this->dbal->executeQuery($query, $parameters)->fetchAllAssociative(); foreach ($rows as $row) { $restrictionRelations[] = RestrictionHyperrelationRecord::fromDatabaseRow($row); } @@ -589,7 +588,7 @@ public function findDescendantNodeAggregateIds( 'affectedDimensionSpacePointHashes' => Connection::PARAM_STR_ARRAY ]; - $rows = $this->getDatabaseConnection()->executeQuery($query, $parameters, $types) + $rows = $this->dbal->executeQuery($query, $parameters, $types) ->fetchAllAssociative(); $nodeAggregateIdsByDimensionSpacePoint = []; foreach ($rows as $row) { @@ -614,11 +613,6 @@ public function countContentStreamCoverage(NodeRelationAnchorPoint $anchorPoint) 'anchorPoint' => $anchorPoint->value ]; - return (int)$this->getDatabaseConnection()->executeQuery($query, $parameters)->rowCount(); - } - - protected function getDatabaseConnection(): Connection - { - return $this->databaseClient->getConnection(); + return (int)$this->dbal->executeQuery($query, $parameters)->rowCount(); } } diff --git a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Repository/ContentHypergraph.php b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Repository/ContentHypergraph.php index 49f9b7af5be..3ba4ae9367f 100644 --- a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Repository/ContentHypergraph.php +++ b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Repository/ContentHypergraph.php @@ -14,11 +14,11 @@ namespace Neos\ContentGraph\PostgreSQLAdapter\Domain\Repository; +use Doctrine\DBAL\Connection; use Doctrine\DBAL\Connection as DatabaseConnection; use Neos\ContentGraph\PostgreSQLAdapter\Domain\Repository\Query\HypergraphChildQuery; use Neos\ContentGraph\PostgreSQLAdapter\Domain\Repository\Query\HypergraphParentQuery; use Neos\ContentGraph\PostgreSQLAdapter\Domain\Repository\Query\HypergraphQuery; -use Neos\ContentGraph\PostgreSQLAdapter\Infrastructure\PostgresDbalClientInterface; use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePoint; use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePointSet; use Neos\ContentRepository\Core\DimensionSpace\OriginDimensionSpacePoint; @@ -45,24 +45,18 @@ */ final class ContentHypergraph implements ContentGraphInterface { - private PostgresDbalClientInterface $databaseClient; - - private NodeFactory $nodeFactory; - /** * @var array|ContentSubhypergraph[] */ private array $subhypergraphs; public function __construct( - PostgresDbalClientInterface $databaseClient, - NodeFactory $nodeFactory, + private readonly Connection $dbal, + private readonly NodeFactory $nodeFactory, private readonly ContentRepositoryId $contentRepositoryId, private readonly NodeTypeManager $nodeTypeManager, private readonly string $tableNamePrefix ) { - $this->databaseClient = $databaseClient; - $this->nodeFactory = $nodeFactory; } public function getSubgraph( @@ -77,7 +71,7 @@ public function getSubgraph( $contentStreamId, $dimensionSpacePoint, $visibilityConstraints, - $this->databaseClient, + $this->dbal, $this->nodeFactory, $this->nodeTypeManager, $this->tableNamePrefix @@ -141,7 +135,7 @@ public function findNodeAggregateById( $query = HypergraphQuery::create($contentStreamId, $this->tableNamePrefix, true); $query = $query->withNodeAggregateId($nodeAggregateId); - $nodeRows = $query->execute($this->getDatabaseConnection())->fetchAllAssociative(); + $nodeRows = $query->execute($this->dbal)->fetchAllAssociative(); return $this->nodeFactory->mapNodeRowsToNodeAggregate( $nodeRows, @@ -177,7 +171,7 @@ public function findParentNodeAggregateByChildOriginDimensionSpacePoint( 'childOriginDimensionSpacePointHash' => $childOriginDimensionSpacePoint->hash ]; - $nodeRows = $this->getDatabaseConnection()->executeQuery( + $nodeRows = $this->dbal->executeQuery( $query, $parameters )->fetchAllAssociative(); @@ -198,7 +192,7 @@ public function findParentNodeAggregates( $query = HypergraphParentQuery::create($contentStreamId, $this->tableNamePrefix); $query = $query->withChildNodeAggregateId($childNodeAggregateId); - $nodeRows = $query->execute($this->getDatabaseConnection())->fetchAllAssociative(); + $nodeRows = $query->execute($this->dbal)->fetchAllAssociative(); return $this->nodeFactory->mapNodeRowsToNodeAggregates( $nodeRows, @@ -219,7 +213,7 @@ public function findChildNodeAggregates( $this->tableNamePrefix ); - $nodeRows = $query->execute($this->getDatabaseConnection())->fetchAllAssociative(); + $nodeRows = $query->execute($this->dbal)->fetchAllAssociative(); return $this->nodeFactory->mapNodeRowsToNodeAggregates( $nodeRows, @@ -242,7 +236,7 @@ public function findChildNodeAggregatesByName( ); $query = $query->withChildNodeName($name); - $nodeRows = $query->execute($this->getDatabaseConnection())->fetchAllAssociative(); + $nodeRows = $query->execute($this->dbal)->fetchAllAssociative(); return $this->nodeFactory->mapNodeRowsToNodeAggregates( $nodeRows, @@ -264,7 +258,7 @@ public function findTetheredChildNodeAggregates( ); $query = $query->withOnlyTethered(); - $nodeRows = $query->execute($this->getDatabaseConnection())->fetchAllAssociative(); + $nodeRows = $query->execute($this->dbal)->fetchAllAssociative(); return $this->nodeFactory->mapNodeRowsToNodeAggregates($nodeRows, VisibilityConstraints::withoutRestrictions()); } @@ -287,7 +281,7 @@ public function getDimensionSpacePointsOccupiedByChildNodeName( ->withDimensionSpacePoints($dimensionSpacePointsToCheck); $occupiedDimensionSpacePoints = []; - foreach ($query->execute($this->getDatabaseConnection())->fetchAllAssociative() as $row) { + foreach ($query->execute($this->dbal)->fetchAllAssociative() as $row) { $occupiedDimensionSpacePoints[$row['dimensionspacepointhash']] = DimensionSpacePoint::fromJsonString($row['dimensionspacepoint']); } @@ -303,7 +297,7 @@ public function countNodes(): int { $query = 'SELECT COUNT(*) FROM ' . $this->tableNamePrefix . '_node'; - return $this->getDatabaseConnection()->executeQuery($query)->fetchOne(); + return $this->dbal->executeQuery($query)->fetchOne(); } /** @@ -313,9 +307,4 @@ public function findUsedNodeTypeNames(): iterable { return []; } - - private function getDatabaseConnection(): DatabaseConnection - { - return $this->databaseClient->getConnection(); - } } diff --git a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Repository/ContentSubhypergraph.php b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Repository/ContentSubhypergraph.php index 95d96cbf077..df2e0a7887e 100644 --- a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Repository/ContentSubhypergraph.php +++ b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Repository/ContentSubhypergraph.php @@ -14,6 +14,7 @@ namespace Neos\ContentGraph\PostgreSQLAdapter\Domain\Repository; +use Doctrine\DBAL\Connection; use Doctrine\DBAL\Connection as DatabaseConnection; use Neos\ContentGraph\PostgreSQLAdapter\Domain\Repository\Query\HypergraphChildQuery; use Neos\ContentGraph\PostgreSQLAdapter\Domain\Repository\Query\HypergraphParentQuery; @@ -22,7 +23,6 @@ use Neos\ContentGraph\PostgreSQLAdapter\Domain\Repository\Query\HypergraphSiblingQuery; use Neos\ContentGraph\PostgreSQLAdapter\Domain\Repository\Query\HypergraphSiblingQueryMode; use Neos\ContentGraph\PostgreSQLAdapter\Domain\Repository\Query\QueryUtility; -use Neos\ContentGraph\PostgreSQLAdapter\Infrastructure\PostgresDbalClientInterface; use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePoint; use Neos\ContentRepository\Core\NodeType\NodeTypeManager; use Neos\ContentRepository\Core\NodeType\NodeTypeName; @@ -78,7 +78,7 @@ public function __construct( private ContentStreamId $contentStreamId, private DimensionSpacePoint $dimensionSpacePoint, private VisibilityConstraints $visibilityConstraints, - private PostgresDbalClientInterface $databaseClient, + private Connection $dbal, private NodeFactory $nodeFactory, private NodeTypeManager $nodeTypeManager, private string $tableNamePrefix @@ -102,7 +102,7 @@ public function findNodeById(NodeAggregateId $nodeAggregateId): ?Node ->withNodeAggregateId($nodeAggregateId) ->withRestriction($this->visibilityConstraints); - $nodeRow = $query->execute($this->getDatabaseConnection())->fetchAssociative(); + $nodeRow = $query->execute($this->dbal)->fetchAssociative(); return $nodeRow ? $this->nodeFactory->mapNodeRowToNode( $nodeRow, @@ -119,7 +119,7 @@ public function findRootNodeByType(NodeTypeName $nodeTypeName): ?Node ->withClassification(NodeAggregateClassification::CLASSIFICATION_ROOT) ->withRestriction($this->visibilityConstraints); - $nodeRow = $query->execute($this->getDatabaseConnection())->fetchAssociative(); + $nodeRow = $query->execute($this->dbal)->fetchAssociative(); return $nodeRow ? $this->nodeFactory->mapNodeRowToNode( $nodeRow, @@ -152,7 +152,7 @@ public function findChildNodes( ->withOffset($filter->pagination->offset); } - $childNodeRows = $query->execute($this->getDatabaseConnection())->fetchAllAssociative(); + $childNodeRows = $query->execute($this->dbal)->fetchAllAssociative(); return $this->nodeFactory->mapNodeRowsToNodes( $childNodeRows, @@ -189,7 +189,7 @@ public function findReferences( $orderings[] = 'r.position'; $query = $query->orderedBy($orderings); - $referenceRows = $query->execute($this->getDatabaseConnection())->fetchAllAssociative(); + $referenceRows = $query->execute($this->dbal)->fetchAllAssociative(); return $this->nodeFactory->mapReferenceRowsToReferences( $referenceRows, @@ -239,7 +239,7 @@ public function findBackReferences( ->withOffset($filter->pagination->offset); } - $referenceRows = $query->execute($this->getDatabaseConnection())->fetchAllAssociative(); + $referenceRows = $query->execute($this->dbal)->fetchAllAssociative(); return $this->nodeFactory->mapReferenceRowsToReferences( $referenceRows, @@ -260,7 +260,7 @@ public function findParentNode(NodeAggregateId $childNodeAggregateId): ?Node ->withRestriction($this->visibilityConstraints) ->withChildNodeAggregateId($childNodeAggregateId); - $nodeRow = $query->execute($this->getDatabaseConnection())->fetchAssociative(); + $nodeRow = $query->execute($this->dbal)->fetchAssociative(); return $nodeRow ? $this->nodeFactory->mapNodeRowToNode( $nodeRow, @@ -302,7 +302,7 @@ private function findChildNodeConnectedThroughEdgeName( ->withRestriction($this->visibilityConstraints) ->withChildNodeName($nodeName); - $nodeRow = $query->execute($this->getDatabaseConnection())->fetchAssociative(); + $nodeRow = $query->execute($this->dbal)->fetchAssociative(); return $nodeRow ? $this->nodeFactory->mapNodeRowToNode( $nodeRow, @@ -363,7 +363,7 @@ private function findAnySiblings( ->withOffset($pagination->offset); } - $siblingsRows = $query->execute($this->getDatabaseConnection())->fetchAllAssociative(); + $siblingsRows = $query->execute($this->dbal)->fetchAllAssociative(); return $this->nodeFactory->mapNodeRowsToNodes($siblingsRows, $this->visibilityConstraints); } @@ -450,7 +450,7 @@ public function findSubtree( - $nodeRows = $this->getDatabaseConnection()->executeQuery($query, $parameters, $types) + $nodeRows = $this->dbal->executeQuery($query, $parameters, $types) ->fetchAllAssociative(); if ($nodeRows === []) { return null; @@ -511,7 +511,7 @@ public function countNodes(): int 'dimensionSpacePointHash' => $this->dimensionSpacePoint->hash ]; - $result = $this->getDatabaseConnection()->executeQuery($query, $parameters)->fetchNumeric(); + $result = $this->dbal->executeQuery($query, $parameters)->fetchNumeric(); return $result ? $result[0] : 0; } @@ -531,7 +531,7 @@ private function findNodeByPathFromStartingNode(NodePath $path, Node $startingNo private function getDatabaseConnection(): DatabaseConnection { - return $this->databaseClient->getConnection(); + return $this->dbal; } public function jsonSerialize(): ContentSubgraphIdentity diff --git a/Neos.ContentGraph.PostgreSQLAdapter/src/HypergraphProjectionFactory.php b/Neos.ContentGraph.PostgreSQLAdapter/src/HypergraphProjectionFactory.php index 71c076400b6..ed6799b26a7 100644 --- a/Neos.ContentGraph.PostgreSQLAdapter/src/HypergraphProjectionFactory.php +++ b/Neos.ContentGraph.PostgreSQLAdapter/src/HypergraphProjectionFactory.php @@ -4,9 +4,9 @@ namespace Neos\ContentGraph\PostgreSQLAdapter; +use Doctrine\DBAL\Connection; use Neos\ContentGraph\PostgreSQLAdapter\Domain\Projection\HypergraphProjection; use Neos\ContentGraph\PostgreSQLAdapter\Domain\Repository\NodeFactory; -use Neos\ContentGraph\PostgreSQLAdapter\Infrastructure\PostgresDbalClientInterface; use Neos\ContentRepository\Core\Factory\ProjectionFactoryDependencies; use Neos\ContentRepository\Core\Projection\ProjectionFactoryInterface; use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId; @@ -18,7 +18,7 @@ final class HypergraphProjectionFactory implements ProjectionFactoryInterface { public function __construct( - private readonly PostgresDbalClientInterface $dbalClient + private readonly Connection $dbal, ) { } @@ -37,7 +37,7 @@ public function build( ); return new HypergraphProjection( - $this->dbalClient, + $this->dbal, new NodeFactory( $projectionFactoryDependencies->contentRepositoryId, $projectionFactoryDependencies->nodeTypeManager, diff --git a/Neos.ContentGraph.PostgreSQLAdapter/src/Infrastructure/PostgresDbalClientInterface.php b/Neos.ContentGraph.PostgreSQLAdapter/src/Infrastructure/PostgresDbalClientInterface.php deleted file mode 100644 index a77e88ce4d2..00000000000 --- a/Neos.ContentGraph.PostgreSQLAdapter/src/Infrastructure/PostgresDbalClientInterface.php +++ /dev/null @@ -1,25 +0,0 @@ -contentStreamId = contentStreamId::fromString('cs-identifier'); @@ -71,7 +71,7 @@ public function __construct( public function removeEverything(): void { $eventTableName = DoctrineEventStoreFactory::databaseTableName($this->contentRepositoryId); - $this->connection->executeStatement('TRUNCATE ' . $this->connection->quoteIdentifier($eventTableName)); + $this->dbal->executeStatement('TRUNCATE ' . $this->dbal->quoteIdentifier($eventTableName)); $this->contentRepository->resetProjectionStates(); } diff --git a/Neos.ContentRepository.BehavioralTests/Classes/Command/PerformanceMeasurementServiceFactory.php b/Neos.ContentRepository.BehavioralTests/Classes/Command/PerformanceMeasurementServiceFactory.php index 1b3c9611228..a4a9e11a16a 100644 --- a/Neos.ContentRepository.BehavioralTests/Classes/Command/PerformanceMeasurementServiceFactory.php +++ b/Neos.ContentRepository.BehavioralTests/Classes/Command/PerformanceMeasurementServiceFactory.php @@ -25,7 +25,7 @@ class PerformanceMeasurementServiceFactory implements ContentRepositoryServiceFactoryInterface { public function __construct( - private readonly Connection $connection, + private readonly Connection $dbal, ) { } @@ -35,7 +35,7 @@ public function build( return new PerformanceMeasurementService( $serviceFactoryDependencies->eventPersister, $serviceFactoryDependencies->contentRepository, - $this->connection, + $this->dbal, $serviceFactoryDependencies->contentRepositoryId ); } diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Bootstrap/FeatureContext.php b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Bootstrap/FeatureContext.php index 0aed9d47cc7..682bf3c0d66 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Bootstrap/FeatureContext.php +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Bootstrap/FeatureContext.php @@ -16,6 +16,7 @@ use Behat\Behat\Context\Context as BehatContext; use Behat\Behat\Hook\Scope\BeforeScenarioScope; +use Doctrine\DBAL\Connection; use GuzzleHttp\Psr7\Uri; use Neos\Behat\FlowBootstrapTrait; use Neos\ContentGraph\DoctrineDbalAdapter\Tests\Behavior\Features\Bootstrap\ProjectionIntegrityViolationDetectionTrait; @@ -28,7 +29,6 @@ use Neos\ContentRepository\Core\Factory\ContentRepositoryServiceFactoryInterface; use Neos\ContentRepository\Core\Factory\ContentRepositoryServiceInterface; use Neos\ContentRepository\Core\Feature\NodeModification\Dto\PropertyValuesToWrite; -use Neos\ContentRepository\Core\Infrastructure\DbalClientInterface; use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId; use Neos\ContentRepository\Core\Tests\Behavior\Fixtures\DayOfWeek; use Neos\ContentRepository\Core\Tests\Behavior\Fixtures\PostalAddress; @@ -59,7 +59,7 @@ public function __construct() { self::bootstrapFlow(); - $this->dbalClient = $this->getObject(DbalClientInterface::class); + $this->dbal = $this->getObject(Connection::class); $this->setUpInterleavingLogger(); $this->contentRepositoryRegistry = $this->getObject(ContentRepositoryRegistry::class); } diff --git a/Neos.ContentRepository.Core/Classes/Infrastructure/DbalClientInterface.php b/Neos.ContentRepository.Core/Classes/Infrastructure/DbalClientInterface.php deleted file mode 100644 index 8db7a998b6f..00000000000 --- a/Neos.ContentRepository.Core/Classes/Infrastructure/DbalClientInterface.php +++ /dev/null @@ -1,19 +0,0 @@ -client->getConnection(); - $contentStreamIds = $connection->executeQuery('SELECT contentstreamid FROM ' . $this->tableName)->fetchFirstColumn(); + $contentStreamIds = $this->dbal->executeQuery('SELECT contentstreamid FROM ' . $this->tableName)->fetchFirstColumn(); return array_map(ContentStreamId::fromString(...), $contentStreamIds); } @@ -78,8 +76,7 @@ public function findUnusedContentStreams(bool $findTemporaryContentStreams): ite $states[] = ContentStreamState::STATE_FORKED; } - $connection = $this->client->getConnection(); - $contentStreamIds = $connection->executeQuery( + $contentStreamIds = $this->dbal->executeQuery( ' SELECT contentstreamid FROM ' . $this->tableName . ' WHERE removed = FALSE @@ -101,9 +98,8 @@ public function findUnusedContentStreams(bool $findTemporaryContentStreams): ite public function findStateForContentStream(ContentStreamId $contentStreamId): ?ContentStreamState { - $connection = $this->client->getConnection(); /* @var $state string|false */ - $state = $connection->executeQuery( + $state = $this->dbal->executeQuery( ' SELECT state FROM ' . $this->tableName . ' WHERE contentstreamid = :contentStreamId @@ -122,8 +118,7 @@ public function findStateForContentStream(ContentStreamId $contentStreamId): ?Co */ public function findUnusedAndRemovedContentStreams(): iterable { - $connection = $this->client->getConnection(); - $contentStreamIds = $connection->executeQuery( + $contentStreamIds = $this->dbal->executeQuery( ' WITH RECURSIVE transitiveUsedContentStreams (contentstreamid) AS ( -- initial case: find all content streams currently in direct use by a workspace @@ -161,9 +156,8 @@ public function findUnusedAndRemovedContentStreams(): iterable public function findVersionForContentStream(ContentStreamId $contentStreamId): MaybeVersion { - $connection = $this->client->getConnection(); /* @var $state string|false */ - $version = $connection->executeQuery( + $version = $this->dbal->executeQuery( ' SELECT version FROM ' . $this->tableName . ' WHERE contentStreamId = :contentStreamId @@ -182,9 +176,8 @@ public function findVersionForContentStream(ContentStreamId $contentStreamId): M public function hasContentStream(ContentStreamId $contentStreamId): bool { - $connection = $this->client->getConnection(); /* @var $state string|false */ - $version = $connection->executeQuery( + $version = $this->dbal->executeQuery( ' SELECT version FROM ' . $this->tableName . ' WHERE contentStreamId = :contentStreamId diff --git a/Neos.ContentRepository.Core/Classes/Projection/ContentStream/ContentStreamProjection.php b/Neos.ContentRepository.Core/Classes/Projection/ContentStream/ContentStreamProjection.php index 8b990f42368..fe81d27fdef 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/ContentStream/ContentStreamProjection.php +++ b/Neos.ContentRepository.Core/Classes/Projection/ContentStream/ContentStreamProjection.php @@ -37,7 +37,6 @@ use Neos\ContentRepository\Core\Feature\WorkspacePublication\Event\WorkspaceWasPublished; use Neos\ContentRepository\Core\Feature\WorkspaceRebase\Event\WorkspaceRebaseFailed; use Neos\ContentRepository\Core\Feature\WorkspaceRebase\Event\WorkspaceWasRebased; -use Neos\ContentRepository\Core\Infrastructure\DbalClientInterface; use Neos\ContentRepository\Core\Projection\ProjectionInterface; use Neos\ContentRepository\Core\Projection\ProjectionStateInterface; use Neos\ContentRepository\Core\Projection\ProjectionStatus; @@ -64,7 +63,7 @@ class ContentStreamProjection implements ProjectionInterface private ?ContentStreamFinder $contentStreamFinder = null; public function __construct( - private readonly DbalClientInterface $dbalClient, + private readonly Connection $dbal, private readonly string $tableName ) { } @@ -73,15 +72,15 @@ public function setUp(): void { $statements = $this->determineRequiredSqlStatements(); foreach ($statements as $statement) { - $this->getDatabaseConnection()->executeStatement($statement); + $this->dbal->executeStatement($statement); } - CheckpointHelper::resetCheckpoint($this->getDatabaseConnection(), $this->tableName); + CheckpointHelper::resetCheckpoint($this->dbal, $this->tableName); } public function status(): ProjectionStatus { try { - $this->getDatabaseConnection()->connect(); + $this->dbal->connect(); } catch (\Throwable $e) { return ProjectionStatus::error(sprintf('Failed to connect to database: %s', $e->getMessage())); } @@ -106,8 +105,7 @@ public function status(): ProjectionStatus */ private function determineRequiredSqlStatements(): array { - $connection = $this->dbalClient->getConnection(); - $schemaManager = $connection->getSchemaManager(); + $schemaManager = $this->dbal->getSchemaManager(); if (!$schemaManager instanceof AbstractSchemaManager) { throw new \RuntimeException('Failed to retrieve Schema Manager', 1625653914); } @@ -124,20 +122,21 @@ private function determineRequiredSqlStatements(): array CheckpointHelper::checkpointTableSchema($this->tableName) ]); - return DbalSchemaDiff::determineRequiredSqlStatements($connection, $schema); + return DbalSchemaDiff::determineRequiredSqlStatements($this->dbal, $schema); } public function reset(): void { - $this->getDatabaseConnection()->executeStatement('TRUNCATE table ' . $this->tableName); - CheckpointHelper::resetCheckpoint($this->getDatabaseConnection(), $this->tableName); + $this->dbal->executeStatement('TRUNCATE table ' . $this->tableName); + CheckpointHelper::resetCheckpoint($this->dbal, $this->tableName); } public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void { - $this->getDatabaseConnection()->beginTransaction(); + $this->dbal->beginTransaction(); if ($event instanceof EmbedsContentStreamAndNodeAggregateId) { $this->updateContentStreamVersion($event, $eventEnvelope); + $this->dbal->commit(); return; } match ($event::class) { @@ -157,20 +156,20 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void DimensionShineThroughWasAdded::class => $this->whenDimensionShineThroughWasAdded($event, $eventEnvelope), default => null, }; - CheckpointHelper::updateCheckpoint($this->getDatabaseConnection(), $this->tableName, $eventEnvelope->sequenceNumber); - $this->getDatabaseConnection()->commit(); + CheckpointHelper::updateCheckpoint($this->dbal, $this->tableName, $eventEnvelope->sequenceNumber); + $this->dbal->commit(); } public function getCheckpoint(): SequenceNumber { - return CheckpointHelper::getCheckpoint($this->getDatabaseConnection(), $this->tableName); + return CheckpointHelper::getCheckpoint($this->dbal, $this->tableName); } public function getState(): ProjectionStateInterface { if (!$this->contentStreamFinder) { $this->contentStreamFinder = new ContentStreamFinder( - $this->dbalClient, + $this->dbal, $this->tableName ); } @@ -179,7 +178,7 @@ public function getState(): ProjectionStateInterface private function whenContentStreamWasCreated(ContentStreamWasCreated $event, EventEnvelope $eventEnvelope): void { - $this->getDatabaseConnection()->insert($this->tableName, [ + $this->dbal->insert($this->tableName, [ 'contentStreamId' => $event->contentStreamId->value, 'version' => self::extractVersion($eventEnvelope), 'state' => ContentStreamState::STATE_CREATED->value, @@ -206,7 +205,7 @@ private function whenWorkspaceWasCreated(WorkspaceWasCreated $event): void private function whenContentStreamWasForked(ContentStreamWasForked $event, EventEnvelope $eventEnvelope): void { - $this->getDatabaseConnection()->insert($this->tableName, [ + $this->dbal->insert($this->tableName, [ 'contentStreamId' => $event->newContentStreamId->value, 'version' => self::extractVersion($eventEnvelope), 'sourceContentStreamId' => $event->sourceContentStreamId->value, @@ -303,7 +302,7 @@ private function whenContentStreamWasClosed(ContentStreamWasClosed $event, Event $event->contentStreamId, ContentStreamState::STATE_CLOSED, ); - $this->getDatabaseConnection()->update($this->tableName, [ + $this->dbal->update($this->tableName, [ 'version' => self::extractVersion($eventEnvelope), ], [ 'contentStreamId' => $event->contentStreamId->value @@ -316,7 +315,7 @@ private function whenContentStreamWasReopened(ContentStreamWasReopened $event, E $event->contentStreamId, $event->previousState, ); - $this->getDatabaseConnection()->update($this->tableName, [ + $this->dbal->update($this->tableName, [ 'version' => self::extractVersion($eventEnvelope), ], [ 'contentStreamId' => $event->contentStreamId->value @@ -325,7 +324,7 @@ private function whenContentStreamWasReopened(ContentStreamWasReopened $event, E private function whenContentStreamWasRemoved(ContentStreamWasRemoved $event, EventEnvelope $eventEnvelope): void { - $this->getDatabaseConnection()->update($this->tableName, [ + $this->dbal->update($this->tableName, [ 'removed' => true, 'version' => self::extractVersion($eventEnvelope), ], [ @@ -335,7 +334,7 @@ private function whenContentStreamWasRemoved(ContentStreamWasRemoved $event, Eve private function whenDimensionShineThroughWasAdded(DimensionShineThroughWasAdded $event, EventEnvelope $eventEnvelope): void { - $this->getDatabaseConnection()->update($this->tableName, [ + $this->dbal->update($this->tableName, [ 'version' => self::extractVersion($eventEnvelope), ], [ 'contentStreamId' => $event->contentStreamId->value @@ -344,23 +343,18 @@ private function whenDimensionShineThroughWasAdded(DimensionShineThroughWasAdded private function updateStateForContentStream(ContentStreamId $contentStreamId, ContentStreamState $state): void { - $this->getDatabaseConnection()->update($this->tableName, [ + $this->dbal->update($this->tableName, [ 'state' => $state->value, ], [ 'contentStreamId' => $contentStreamId->value ]); } - private function getDatabaseConnection(): Connection - { - return $this->dbalClient->getConnection(); - } - private function updateContentStreamVersion( EmbedsContentStreamAndNodeAggregateId $eventInstance, EventEnvelope $eventEnvelope ): void { - $this->getDatabaseConnection()->update($this->tableName, [ + $this->dbal->update($this->tableName, [ 'version' => self::extractVersion($eventEnvelope), ], [ 'contentStreamId' => $eventInstance->getContentStreamId()->value diff --git a/Neos.ContentRepository.Core/Classes/Projection/ContentStream/ContentStreamProjectionFactory.php b/Neos.ContentRepository.Core/Classes/Projection/ContentStream/ContentStreamProjectionFactory.php index 4df27962c82..a7fa2c6bcd5 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/ContentStream/ContentStreamProjectionFactory.php +++ b/Neos.ContentRepository.Core/Classes/Projection/ContentStream/ContentStreamProjectionFactory.php @@ -14,8 +14,8 @@ namespace Neos\ContentRepository\Core\Projection\ContentStream; +use Doctrine\DBAL\Connection; use Neos\ContentRepository\Core\Factory\ProjectionFactoryDependencies; -use Neos\ContentRepository\Core\Infrastructure\DbalClientInterface; use Neos\ContentRepository\Core\Projection\ProjectionFactoryInterface; /** @@ -25,7 +25,7 @@ class ContentStreamProjectionFactory implements ProjectionFactoryInterface { public function __construct( - private readonly DbalClientInterface $dbalClient + private readonly Connection $dbal, ) { } @@ -39,7 +39,7 @@ public function build( (new \ReflectionClass(ContentStreamProjection::class))->getShortName() )); return new ContentStreamProjection( - $this->dbalClient, + $this->dbal, sprintf( 'cr_%s_p_%s', $projectionFactoryDependencies->contentRepositoryId->value, diff --git a/Neos.ContentRepository.Core/Classes/Projection/Workspace/WorkspaceFinder.php b/Neos.ContentRepository.Core/Classes/Projection/Workspace/WorkspaceFinder.php index 724b3c4ab84..4ec004a9cce 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/Workspace/WorkspaceFinder.php +++ b/Neos.ContentRepository.Core/Classes/Projection/Workspace/WorkspaceFinder.php @@ -14,7 +14,7 @@ namespace Neos\ContentRepository\Core\Projection\Workspace; -use Neos\ContentRepository\Core\Infrastructure\DbalClientInterface; +use Doctrine\DBAL\Connection; use Neos\ContentRepository\Core\Projection\ProjectionStateInterface; use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceDescription; @@ -29,7 +29,7 @@ final class WorkspaceFinder implements ProjectionStateInterface { public function __construct( - private readonly DbalClientInterface $client, + private readonly Connection $dbal, private readonly WorkspaceRuntimeCache $workspaceRuntimeCache, private readonly string $tableName ) { @@ -43,8 +43,7 @@ public function findOneByName(WorkspaceName $name): ?Workspace return $workspace; } - $connection = $this->client->getConnection(); - $workspaceRow = $connection->executeQuery( + $workspaceRow = $this->dbal->executeQuery( ' SELECT * FROM ' . $this->tableName . ' WHERE workspaceName = :workspaceName @@ -71,8 +70,7 @@ public function findOneByCurrentContentStreamId( return $workspace; } - $connection = $this->client->getConnection(); - $workspaceRow = $connection->executeQuery( + $workspaceRow = $this->dbal->executeQuery( ' SELECT * FROM ' . $this->tableName . ' WHERE currentContentStreamId = :currentContentStreamId @@ -99,8 +97,7 @@ public function findByBaseWorkspace(WorkspaceName $baseWorkspace): array { $result = []; - $connection = $this->client->getConnection(); - $workspaceRows = $connection->executeQuery( + $workspaceRows = $this->dbal->executeQuery( ' SELECT * FROM ' . $this->tableName . ' WHERE baseWorkspaceName = :workspaceName @@ -120,8 +117,7 @@ public function findByBaseWorkspace(WorkspaceName $baseWorkspace): array public function findOneByWorkspaceOwner(string $owner): ?Workspace { - $connection = $this->client->getConnection(); - $workspaceRow = $connection->executeQuery( + $workspaceRow = $this->dbal->executeQuery( ' SELECT * FROM ' . $this->tableName . ' WHERE workspaceOwner = :workspaceOwner @@ -142,8 +138,7 @@ public function findAll(): Workspaces { $result = []; - $connection = $this->client->getConnection(); - $workspaceRows = $connection->executeQuery( + $workspaceRows = $this->dbal->executeQuery( ' SELECT * FROM ' . $this->tableName . ' ' @@ -166,8 +161,7 @@ public function findOutdated(): array { $result = []; - $connection = $this->client->getConnection(); - $workspaceRows = $connection->executeQuery( + $workspaceRows = $this->dbal->executeQuery( ' SELECT * FROM ' . $this->tableName . ' WHERE status = :outdated ', diff --git a/Neos.ContentRepository.Core/Classes/Projection/Workspace/WorkspaceProjection.php b/Neos.ContentRepository.Core/Classes/Projection/Workspace/WorkspaceProjection.php index c2d984e35c7..83ab9593955 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/Workspace/WorkspaceProjection.php +++ b/Neos.ContentRepository.Core/Classes/Projection/Workspace/WorkspaceProjection.php @@ -33,7 +33,6 @@ use Neos\ContentRepository\Core\Feature\WorkspacePublication\Event\WorkspaceWasPublished; use Neos\ContentRepository\Core\Feature\WorkspaceRebase\Event\WorkspaceRebaseFailed; use Neos\ContentRepository\Core\Feature\WorkspaceRebase\Event\WorkspaceWasRebased; -use Neos\ContentRepository\Core\Infrastructure\DbalClientInterface; use Neos\ContentRepository\Core\Projection\ProjectionInterface; use Neos\ContentRepository\Core\Projection\ProjectionStatus; use Neos\ContentRepository\Core\Projection\WithMarkStaleInterface; @@ -61,7 +60,7 @@ class WorkspaceProjection implements ProjectionInterface, WithMarkStaleInterface private WorkspaceRuntimeCache $workspaceRuntimeCache; public function __construct( - private readonly DbalClientInterface $dbalClient, + private readonly Connection $dbal, private readonly string $tableName, ) { $this->workspaceRuntimeCache = new WorkspaceRuntimeCache(); @@ -70,15 +69,15 @@ public function __construct( public function setUp(): void { foreach ($this->determineRequiredSqlStatements() as $statement) { - $this->getDatabaseConnection()->executeStatement($statement); + $this->dbal->executeStatement($statement); } - CheckpointHelper::resetCheckpoint($this->getDatabaseConnection(), $this->tableName); + CheckpointHelper::resetCheckpoint($this->dbal, $this->tableName); } public function status(): ProjectionStatus { try { - $this->getDatabaseConnection()->connect(); + $this->dbal->connect(); } catch (\Throwable $e) { return ProjectionStatus::error(sprintf('Failed to connect to database: %s', $e->getMessage())); } @@ -103,8 +102,7 @@ public function status(): ProjectionStatus */ private function determineRequiredSqlStatements(): array { - $connection = $this->dbalClient->getConnection(); - $schemaManager = $connection->getSchemaManager(); + $schemaManager = $this->dbal->getSchemaManager(); if (!$schemaManager instanceof AbstractSchemaManager) { throw new \RuntimeException('Failed to retrieve Schema Manager', 1625653914); } @@ -122,18 +120,18 @@ private function determineRequiredSqlStatements(): array $checkpointTable = CheckpointHelper::checkpointTableSchema($this->tableName); $schema = DbalSchemaFactory::createSchemaWithTables($schemaManager, [$workspaceTable, $checkpointTable]); - return DbalSchemaDiff::determineRequiredSqlStatements($connection, $schema); + return DbalSchemaDiff::determineRequiredSqlStatements($this->dbal, $schema); } public function reset(): void { - $this->getDatabaseConnection()->exec('TRUNCATE ' . $this->tableName); - CheckpointHelper::resetCheckpoint($this->getDatabaseConnection(), $this->tableName); + $this->dbal->exec('TRUNCATE ' . $this->tableName); + CheckpointHelper::resetCheckpoint($this->dbal, $this->tableName); } public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void { - $this->getDatabaseConnection()->beginTransaction(); + $this->dbal->beginTransaction(); match ($event::class) { WorkspaceWasCreated::class => $this->whenWorkspaceWasCreated($event), WorkspaceWasRenamed::class => $this->whenWorkspaceWasRenamed($event), @@ -149,20 +147,20 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void WorkspaceBaseWorkspaceWasChanged::class => $this->whenWorkspaceBaseWorkspaceWasChanged($event), default => null, }; - CheckpointHelper::updateCheckpoint($this->getDatabaseConnection(), $this->tableName, $eventEnvelope->sequenceNumber); - $this->getDatabaseConnection()->commit(); + CheckpointHelper::updateCheckpoint($this->dbal, $this->tableName, $eventEnvelope->sequenceNumber); + $this->dbal->commit(); } public function getCheckpoint(): SequenceNumber { - return CheckpointHelper::getCheckpoint($this->getDatabaseConnection(), $this->tableName); + return CheckpointHelper::getCheckpoint($this->dbal, $this->tableName); } public function getState(): WorkspaceFinder { if (!$this->workspaceFinder) { $this->workspaceFinder = new WorkspaceFinder( - $this->dbalClient, + $this->dbal, $this->workspaceRuntimeCache, $this->tableName ); @@ -177,7 +175,7 @@ public function markStale(): void private function whenWorkspaceWasCreated(WorkspaceWasCreated $event): void { - $this->getDatabaseConnection()->insert($this->tableName, [ + $this->dbal->insert($this->tableName, [ 'workspaceName' => $event->workspaceName->value, 'baseWorkspaceName' => $event->baseWorkspaceName->value, 'workspaceTitle' => $event->workspaceTitle->value, @@ -190,7 +188,7 @@ private function whenWorkspaceWasCreated(WorkspaceWasCreated $event): void private function whenWorkspaceWasRenamed(WorkspaceWasRenamed $event): void { - $this->getDatabaseConnection()->update( + $this->dbal->update( $this->tableName, [ 'workspaceTitle' => $event->workspaceTitle->value, @@ -202,7 +200,7 @@ private function whenWorkspaceWasRenamed(WorkspaceWasRenamed $event): void private function whenRootWorkspaceWasCreated(RootWorkspaceWasCreated $event): void { - $this->getDatabaseConnection()->insert($this->tableName, [ + $this->dbal->insert($this->tableName, [ 'workspaceName' => $event->workspaceName->value, 'workspaceTitle' => $event->workspaceTitle->value, 'workspaceDescription' => $event->workspaceDescription->value, @@ -274,7 +272,7 @@ private function whenWorkspaceRebaseFailed(WorkspaceRebaseFailed $event): void private function whenWorkspaceWasRemoved(WorkspaceWasRemoved $event): void { - $this->getDatabaseConnection()->delete( + $this->dbal->delete( $this->tableName, ['workspaceName' => $event->workspaceName->value] ); @@ -282,7 +280,7 @@ private function whenWorkspaceWasRemoved(WorkspaceWasRemoved $event): void private function whenWorkspaceOwnerWasChanged(WorkspaceOwnerWasChanged $event): void { - $this->getDatabaseConnection()->update( + $this->dbal->update( $this->tableName, ['workspaceOwner' => $event->newWorkspaceOwner], ['workspaceName' => $event->workspaceName->value] @@ -291,7 +289,7 @@ private function whenWorkspaceOwnerWasChanged(WorkspaceOwnerWasChanged $event): private function whenWorkspaceBaseWorkspaceWasChanged(WorkspaceBaseWorkspaceWasChanged $event): void { - $this->getDatabaseConnection()->update( + $this->dbal->update( $this->tableName, [ 'baseWorkspaceName' => $event->baseWorkspaceName->value, @@ -305,7 +303,7 @@ private function updateContentStreamId( ContentStreamId $contentStreamId, WorkspaceName $workspaceName, ): void { - $this->getDatabaseConnection()->update($this->tableName, [ + $this->dbal->update($this->tableName, [ 'currentContentStreamId' => $contentStreamId->value, ], [ 'workspaceName' => $workspaceName->value @@ -314,7 +312,7 @@ private function updateContentStreamId( private function markWorkspaceAsUpToDate(WorkspaceName $workspaceName): void { - $this->getDatabaseConnection()->executeUpdate(' + $this->dbal->executeUpdate(' UPDATE ' . $this->tableName . ' SET status = :upToDate WHERE @@ -327,7 +325,7 @@ private function markWorkspaceAsUpToDate(WorkspaceName $workspaceName): void private function markDependentWorkspacesAsOutdated(WorkspaceName $baseWorkspaceName): void { - $this->getDatabaseConnection()->executeUpdate(' + $this->dbal->executeUpdate(' UPDATE ' . $this->tableName . ' SET status = :outdated WHERE @@ -340,7 +338,7 @@ private function markDependentWorkspacesAsOutdated(WorkspaceName $baseWorkspaceN private function markWorkspaceAsOutdated(WorkspaceName $workspaceName): void { - $this->getDatabaseConnection()->executeUpdate(' + $this->dbal->executeUpdate(' UPDATE ' . $this->tableName . ' SET status = :outdated @@ -354,7 +352,7 @@ private function markWorkspaceAsOutdated(WorkspaceName $workspaceName): void private function markWorkspaceAsOutdatedConflict(WorkspaceName $workspaceName): void { - $this->getDatabaseConnection()->executeUpdate(' + $this->dbal->executeUpdate(' UPDATE ' . $this->tableName . ' SET status = :outdatedConflict @@ -365,9 +363,4 @@ private function markWorkspaceAsOutdatedConflict(WorkspaceName $workspaceName): 'workspaceName' => $workspaceName->value ]); } - - private function getDatabaseConnection(): Connection - { - return $this->dbalClient->getConnection(); - } } diff --git a/Neos.ContentRepository.Core/Classes/Projection/Workspace/WorkspaceProjectionFactory.php b/Neos.ContentRepository.Core/Classes/Projection/Workspace/WorkspaceProjectionFactory.php index e0c47662ec5..094ee2e4e56 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/Workspace/WorkspaceProjectionFactory.php +++ b/Neos.ContentRepository.Core/Classes/Projection/Workspace/WorkspaceProjectionFactory.php @@ -14,8 +14,8 @@ namespace Neos\ContentRepository\Core\Projection\Workspace; +use Doctrine\DBAL\Connection; use Neos\ContentRepository\Core\Factory\ProjectionFactoryDependencies; -use Neos\ContentRepository\Core\Infrastructure\DbalClientInterface; use Neos\ContentRepository\Core\Projection\ProjectionFactoryInterface; /** @@ -25,7 +25,7 @@ class WorkspaceProjectionFactory implements ProjectionFactoryInterface { public function __construct( - private readonly DbalClientInterface $dbalClient + private readonly Connection $dbal, ) { } @@ -39,7 +39,7 @@ public function build( (new \ReflectionClass(WorkspaceProjection::class))->getShortName() )); return new WorkspaceProjection( - $this->dbalClient, + $this->dbal, sprintf( 'cr_%s_p_%s', $projectionFactoryDependencies->contentRepositoryId->value, diff --git a/Neos.ContentRepositoryRegistry.DoctrineDbalClient/Classes/DoctrineDbalClient.php b/Neos.ContentRepositoryRegistry.DoctrineDbalClient/Classes/DoctrineDbalClient.php deleted file mode 100644 index 47a3e5dec97..00000000000 --- a/Neos.ContentRepositoryRegistry.DoctrineDbalClient/Classes/DoctrineDbalClient.php +++ /dev/null @@ -1,66 +0,0 @@ - - */ - protected $backendOptions; - - /** - * @Flow\InjectConfiguration(package="Neos.Flow", path="persistence.doctrine.sqlLogger") - * @var string - */ - protected $sqlLoggerName; - - /** - * @var Connection - */ - protected $connection; - - public function initializeObject(): void - { - $configuration = new Configuration(); - if (!empty($this->sqlLoggerName)) { - /** @var SQLLogger $configuredSqlLogger */ - $configuredSqlLogger = new $this->sqlLoggerName(); - $configuration->setSQLLogger($configuredSqlLogger); - } - $this->connection = DriverManager::getConnection($this->backendOptions, $configuration); - } - - public function getConnection(): Connection - { - if (!$this->connection->isConnected()) { - $this->connection->connect(); - } - - return $this->connection; - } -} diff --git a/Neos.ContentRepositoryRegistry.DoctrineDbalClient/Configuration/Caches.yaml b/Neos.ContentRepositoryRegistry.DoctrineDbalClient/Configuration/Caches.yaml deleted file mode 100644 index 19b4e1c3b8f..00000000000 --- a/Neos.ContentRepositoryRegistry.DoctrineDbalClient/Configuration/Caches.yaml +++ /dev/null @@ -1,5 +0,0 @@ -Neos_ContentGraph_DoctrineDbalAdapter_ProcessedEvents: - frontend: Neos\Cache\Frontend\VariableFrontend - backend: Neos\Cache\Backend\FileBackend - backendOptions: - defaultLifetime: 400 diff --git a/Neos.ContentRepositoryRegistry.DoctrineDbalClient/Configuration/Objects.yaml b/Neos.ContentRepositoryRegistry.DoctrineDbalClient/Configuration/Objects.yaml index 1dfd0f4d332..c1bf859c1c2 100644 --- a/Neos.ContentRepositoryRegistry.DoctrineDbalClient/Configuration/Objects.yaml +++ b/Neos.ContentRepositoryRegistry.DoctrineDbalClient/Configuration/Objects.yaml @@ -1,6 +1,3 @@ -Neos\ContentRepository\Core\Infrastructure\DbalClientInterface: - className: 'Neos\ContentRepositoryRegistry\DoctrineDbalClient\DoctrineDbalClient' - Neos\ContentGraph\DoctrineDbalAdapter\DoctrineDbalContentGraphProjectionFactory: scope: singleton factoryObjectName: 'Neos\ContentRepositoryRegistry\Infrastructure\GenericObjectFactory' @@ -8,4 +5,4 @@ Neos\ContentGraph\DoctrineDbalAdapter\DoctrineDbalContentGraphProjectionFactory: 1: value: 'Neos\ContentGraph\DoctrineDbalAdapter\DoctrineDbalContentGraphProjectionFactory' 2: - object: 'Neos\ContentRepository\Core\Infrastructure\DbalClientInterface' + object: 'Doctrine\DBAL\Connection' diff --git a/Neos.ContentRepositoryRegistry.DoctrineDbalClient/Configuration/Settings.yaml b/Neos.ContentRepositoryRegistry.DoctrineDbalClient/Configuration/Settings.yaml index 2c39ca34a96..8d454334686 100644 --- a/Neos.ContentRepositoryRegistry.DoctrineDbalClient/Configuration/Settings.yaml +++ b/Neos.ContentRepositoryRegistry.DoctrineDbalClient/Configuration/Settings.yaml @@ -3,7 +3,6 @@ Neos: presets: 'default': projections: - # NOTE: the following name must be stable, because we use it f.e. in Neos UI to register - # catchUpHooks for content cache flushing + # NOTE: the following name should be stable, because there must only be a single content graph projection per content repository 'Neos.ContentRepository:ContentGraph': factoryObjectName: Neos\ContentGraph\DoctrineDbalAdapter\DoctrineDbalContentGraphProjectionFactory diff --git a/Neos.ContentRepositoryRegistry.DoctrineDbalClient/composer.json b/Neos.ContentRepositoryRegistry.DoctrineDbalClient/composer.json index b7653be7e81..f1c22ff9178 100644 --- a/Neos.ContentRepositoryRegistry.DoctrineDbalClient/composer.json +++ b/Neos.ContentRepositoryRegistry.DoctrineDbalClient/composer.json @@ -13,10 +13,5 @@ }, "provide": { "neos/contentrepositoryregistry-storageclient": "self.version" - }, - "autoload": { - "psr-4": { - "Neos\\ContentRepositoryRegistry\\DoctrineDbalClient\\": "Classes" - } } } diff --git a/Neos.ContentRepositoryRegistry.PostgresDbalClient/Classes/PostgresDbalClient.php b/Neos.ContentRepositoryRegistry.PostgresDbalClient/Classes/PostgresDbalClient.php deleted file mode 100644 index e9ac4790333..00000000000 --- a/Neos.ContentRepositoryRegistry.PostgresDbalClient/Classes/PostgresDbalClient.php +++ /dev/null @@ -1,64 +0,0 @@ - - */ - protected array $backendOptions = []; - - /** - * @Flow\InjectConfiguration(package="Neos.Flow", path="persistence.doctrine.sqlLogger") - * @var string|null - */ - protected ?string $sqlLogger; - - protected Connection $connection; - - public function initializeObject(): void - { - $configuration = new Configuration(); - if (!empty($this->sqlLogger)) { - $configuredSqlLoggerName = $this->sqlLogger; - /** @var SQLLogger $configuredSqlLogger */ - $configuredSqlLogger = new $configuredSqlLoggerName(); - $configuration->setSQLLogger($configuredSqlLogger); - } - $this->connection = DriverManager::getConnection($this->backendOptions, $configuration); - } - - public function getConnection(): Connection - { - if (!$this->connection->isConnected()) { - $this->connection->connect(); - } - - return $this->connection; - } -} diff --git a/Neos.ContentRepositoryRegistry.PostgresDbalClient/Configuration/Caches.yaml b/Neos.ContentRepositoryRegistry.PostgresDbalClient/Configuration/Caches.yaml deleted file mode 100644 index 056a5694303..00000000000 --- a/Neos.ContentRepositoryRegistry.PostgresDbalClient/Configuration/Caches.yaml +++ /dev/null @@ -1,5 +0,0 @@ -Neos_ContentGraph_PostgreSQLAdapter_ProcessedEvents: - frontend: Neos\Cache\Frontend\VariableFrontend - backend: Neos\Cache\Backend\FileBackend - backendOptions: - defaultLifetime: 400 diff --git a/Neos.ContentRepositoryRegistry.PostgresDbalClient/Configuration/Objects.yaml b/Neos.ContentRepositoryRegistry.PostgresDbalClient/Configuration/Objects.yaml index 5df3f8c0715..ac5a6a10759 100644 --- a/Neos.ContentRepositoryRegistry.PostgresDbalClient/Configuration/Objects.yaml +++ b/Neos.ContentRepositoryRegistry.PostgresDbalClient/Configuration/Objects.yaml @@ -5,4 +5,4 @@ Neos\ContentGraph\PostgreSQLAdapter\HypergraphProjectionFactory: 1: value: Neos\ContentGraph\PostgreSQLAdapter\HypergraphProjectionFactory 2: - object: 'Neos\ContentRepositoryRegistry\PostgresDbalClient\PostgresDbalClient' + object: 'Doctrine\DBAL\Connection' diff --git a/Neos.ContentRepositoryRegistry.PostgresDbalClient/Configuration/Settings.yaml b/Neos.ContentRepositoryRegistry.PostgresDbalClient/Configuration/Settings.yaml new file mode 100644 index 00000000000..a3956ff3a11 --- /dev/null +++ b/Neos.ContentRepositoryRegistry.PostgresDbalClient/Configuration/Settings.yaml @@ -0,0 +1,9 @@ +## uncomment the following lines in order to change the default implementation of the content graph projection +#Neos: +# ContentRepositoryRegistry: +# presets: +# 'default': +# projections: +# # NOTE: the following name should be stable, because there must only be a single content graph projection per content repository +# 'Neos.ContentRepository:ContentGraph': +# factoryObjectName: Neos\ContentGraph\PostgreSQLAdapter\HypergraphProjectionFactory diff --git a/Neos.ContentRepositoryRegistry.PostgresDbalClient/composer.json b/Neos.ContentRepositoryRegistry.PostgresDbalClient/composer.json index 57348e01009..10fbbf53c5f 100644 --- a/Neos.ContentRepositoryRegistry.PostgresDbalClient/composer.json +++ b/Neos.ContentRepositoryRegistry.PostgresDbalClient/composer.json @@ -13,10 +13,5 @@ }, "provide": { "neos/contentrepositoryregistry-storageclient": "self.version" - }, - "autoload": { - "psr-4": { - "Neos\\ContentRepositoryRegistry\\PostgresDbalClient\\": "Classes" - } } } diff --git a/Neos.ContentRepositoryRegistry/Configuration/Caches.yaml b/Neos.ContentRepositoryRegistry/Configuration/Caches.yaml deleted file mode 100644 index 19b4e1c3b8f..00000000000 --- a/Neos.ContentRepositoryRegistry/Configuration/Caches.yaml +++ /dev/null @@ -1,5 +0,0 @@ -Neos_ContentGraph_DoctrineDbalAdapter_ProcessedEvents: - frontend: Neos\Cache\Frontend\VariableFrontend - backend: Neos\Cache\Backend\FileBackend - backendOptions: - defaultLifetime: 400 diff --git a/Neos.ContentRepositoryRegistry/Configuration/Objects.yaml b/Neos.ContentRepositoryRegistry/Configuration/Objects.yaml index 89c3069794e..fa95c5a5dbb 100644 --- a/Neos.ContentRepositoryRegistry/Configuration/Objects.yaml +++ b/Neos.ContentRepositoryRegistry/Configuration/Objects.yaml @@ -14,7 +14,7 @@ Neos\ContentRepository\Core\Projection\ContentStream\ContentStreamProjectionFact 1: value: Neos\ContentRepository\Core\Projection\ContentStream\ContentStreamProjectionFactory 2: - object: 'Neos\ContentRepository\Core\Infrastructure\DbalClientInterface' + object: 'Doctrine\DBAL\Connection' Neos\ContentRepository\Core\Projection\Workspace\WorkspaceProjectionFactory: scope: singleton @@ -23,4 +23,4 @@ Neos\ContentRepository\Core\Projection\Workspace\WorkspaceProjectionFactory: 1: value: Neos\ContentRepository\Core\Projection\Workspace\WorkspaceProjectionFactory 2: - object: 'Neos\ContentRepository\Core\Infrastructure\DbalClientInterface' + object: 'Doctrine\DBAL\Connection' diff --git a/Neos.ContentRepositoryRegistry/Configuration/Settings.yaml b/Neos.ContentRepositoryRegistry/Configuration/Settings.yaml index 2b7446d75ad..7c9dc6dd183 100644 --- a/Neos.ContentRepositoryRegistry/Configuration/Settings.yaml +++ b/Neos.ContentRepositoryRegistry/Configuration/Settings.yaml @@ -73,8 +73,7 @@ Neos: factoryObjectName: Neos\ContentRepository\Core\Projection\ContentStream\ContentStreamProjectionFactory 'Neos.ContentRepository:Workspace': factoryObjectName: Neos\ContentRepository\Core\Projection\Workspace\WorkspaceProjectionFactory - # NOTE: the following name must be stable, because we use it f.e. in Neos UI to register - # catchUpHooks for content cache flushing + # NOTE: the following name should be stable, because there must only be a single content graph projection per content repository #'Neos.ContentRepository:ContentGraph': # factoryObjectName: Neos\ContentGraph\…Adapter\…ContentGraphProjectionFactory diff --git a/Neos.Neos/Classes/PendingChangesProjection/ChangeFinder.php b/Neos.Neos/Classes/PendingChangesProjection/ChangeFinder.php index 0bc48c0e98b..ef797900572 100644 --- a/Neos.Neos/Classes/PendingChangesProjection/ChangeFinder.php +++ b/Neos.Neos/Classes/PendingChangesProjection/ChangeFinder.php @@ -14,7 +14,7 @@ namespace Neos\Neos\PendingChangesProjection; -use Neos\ContentRepository\Core\Infrastructure\DbalClientInterface; +use Doctrine\DBAL\Connection; use Neos\ContentRepository\Core\Projection\ProjectionStateInterface; use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; use Neos\Flow\Annotations as Flow; @@ -28,12 +28,9 @@ */ final class ChangeFinder implements ProjectionStateInterface { - /** - * @param DbalClientInterface $client - */ public function __construct( - private readonly DbalClientInterface $client, - private readonly string $tableName + private readonly Connection $dbal, + private readonly string $tableName, ) { } @@ -43,8 +40,7 @@ public function __construct( */ public function findByContentStreamId(ContentStreamId $contentStreamId): array { - $connection = $this->client->getConnection(); - $changeRows = $connection->executeQuery( + $changeRows = $this->dbal->executeQuery( ' SELECT * FROM ' . $this->tableName . ' WHERE contentStreamId = :contentStreamId @@ -62,8 +58,7 @@ public function findByContentStreamId(ContentStreamId $contentStreamId): array public function countByContentStreamId(ContentStreamId $contentStreamId): int { - $connection = $this->client->getConnection(); - return (int)$connection->executeQuery( + return (int)$this->dbal->executeQuery( ' SELECT * FROM ' . $this->tableName . ' WHERE contentStreamId = :contentStreamId diff --git a/Neos.Neos/Classes/PendingChangesProjection/ChangeProjection.php b/Neos.Neos/Classes/PendingChangesProjection/ChangeProjection.php index 71b2817e84e..e6461c79dd2 100644 --- a/Neos.Neos/Classes/PendingChangesProjection/ChangeProjection.php +++ b/Neos.Neos/Classes/PendingChangesProjection/ChangeProjection.php @@ -35,7 +35,6 @@ use Neos\ContentRepository\Core\Feature\SubtreeTagging\Event\SubtreeWasTagged; use Neos\ContentRepository\Core\Feature\SubtreeTagging\Event\SubtreeWasUntagged; use Neos\ContentRepository\Core\Feature\WorkspaceCreation\Event\RootWorkspaceWasCreated; -use Neos\ContentRepository\Core\Infrastructure\DbalClientInterface; use Neos\ContentRepository\Core\Projection\ProjectionInterface; use Neos\ContentRepository\Core\Projection\ProjectionStatus; use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId; @@ -67,7 +66,7 @@ class ChangeProjection implements ProjectionInterface private ?array $liveContentStreamIdsRuntimeCache = null; public function __construct( - private readonly DbalClientInterface $dbalClient, + private readonly Connection $dbal, private readonly string $tableNamePrefix, ) { } @@ -76,15 +75,15 @@ public function __construct( public function setUp(): void { foreach ($this->determineRequiredSqlStatements() as $statement) { - $this->getDatabaseConnection()->executeStatement($statement); + $this->dbal->executeStatement($statement); } - CheckpointHelper::resetCheckpoint($this->getDatabaseConnection(), $this->tableNamePrefix); + CheckpointHelper::resetCheckpoint($this->dbal, $this->tableNamePrefix); } public function status(): ProjectionStatus { try { - $this->getDatabaseConnection()->connect(); + $this->dbal->connect(); } catch (\Throwable $e) { return ProjectionStatus::error(sprintf('Failed to connect to database: %s', $e->getMessage())); } @@ -109,8 +108,7 @@ public function status(): ProjectionStatus */ private function determineRequiredSqlStatements(): array { - $connection = $this->dbalClient->getConnection(); - $schemaManager = $connection->getSchemaManager(); + $schemaManager = $this->dbal->getSchemaManager(); if (!$schemaManager instanceof AbstractSchemaManager) { throw new \RuntimeException('Failed to retrieve Schema Manager', 1625653914); } @@ -143,19 +141,19 @@ private function determineRequiredSqlStatements(): array $checkpointTable = CheckpointHelper::checkpointTableSchema($this->tableNamePrefix); $schema = DbalSchemaFactory::createSchemaWithTables($schemaManager, [$changeTable, $liveContentStreamsTable, $checkpointTable]); - return DbalSchemaDiff::determineRequiredSqlStatements($connection, $schema); + return DbalSchemaDiff::determineRequiredSqlStatements($this->dbal, $schema); } public function reset(): void { - $this->getDatabaseConnection()->exec('TRUNCATE ' . $this->tableNamePrefix); - $this->getDatabaseConnection()->exec('TRUNCATE ' . $this->tableNamePrefix . '_livecontentstreams'); - CheckpointHelper::resetCheckpoint($this->getDatabaseConnection(), $this->tableNamePrefix); + $this->dbal->exec('TRUNCATE ' . $this->tableNamePrefix); + $this->dbal->exec('TRUNCATE ' . $this->tableNamePrefix . '_livecontentstreams'); + CheckpointHelper::resetCheckpoint($this->dbal, $this->tableNamePrefix); } public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void { - $this->getDatabaseConnection()->beginTransaction(); + $this->dbal->beginTransaction(); match ($event::class) { RootWorkspaceWasCreated::class => $this->whenRootWorkspaceWasCreated($event), NodeAggregateWasMoved::class => $this->whenNodeAggregateWasMoved($event), @@ -171,20 +169,20 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void NodePeerVariantWasCreated::class => $this->whenNodePeerVariantWasCreated($event), default => null, }; - CheckpointHelper::updateCheckpoint($this->getDatabaseConnection(), $this->tableNamePrefix, $eventEnvelope->sequenceNumber); - $this->getDatabaseConnection()->commit(); + CheckpointHelper::updateCheckpoint($this->dbal, $this->tableNamePrefix, $eventEnvelope->sequenceNumber); + $this->dbal->commit(); } public function getCheckpoint(): SequenceNumber { - return CheckpointHelper::getCheckpoint($this->getDatabaseConnection(), $this->tableNamePrefix); + return CheckpointHelper::getCheckpoint($this->dbal, $this->tableNamePrefix); } public function getState(): ChangeFinder { if (!$this->changeFinder) { $this->changeFinder = new ChangeFinder( - $this->dbalClient, + $this->dbal, $this->tableNamePrefix ); } @@ -194,7 +192,7 @@ public function getState(): ChangeFinder private function whenRootWorkspaceWasCreated(RootWorkspaceWasCreated $event): void { try { - $this->getDatabaseConnection()->insert($this->tableNamePrefix . '_livecontentstreams', [ + $this->dbal->insert($this->tableNamePrefix . '_livecontentstreams', [ 'contentStreamId' => $event->newContentStreamId->value, 'workspaceName' => $event->workspaceName->value, ]); @@ -278,7 +276,7 @@ private function whenNodeAggregateWasRemoved(NodeAggregateWasRemoved $event): vo return; } - $this->getDatabaseConnection()->executeUpdate( + $this->dbal->executeUpdate( 'DELETE FROM ' . $this->tableNamePrefix . ' WHERE contentStreamId = :contentStreamId @@ -297,7 +295,7 @@ private function whenNodeAggregateWasRemoved(NodeAggregateWasRemoved $event): vo ); foreach ($event->affectedOccupiedDimensionSpacePoints as $occupiedDimensionSpacePoint) { - $this->getDatabaseConnection()->executeUpdate( + $this->dbal->executeUpdate( 'INSERT INTO ' . $this->tableNamePrefix . ' (contentStreamId, nodeAggregateId, originDimensionSpacePoint, originDimensionSpacePointHash, created, deleted, changed, moved, removalAttachmentPoint) @@ -326,7 +324,7 @@ private function whenNodeAggregateWasRemoved(NodeAggregateWasRemoved $event): vo private function whenDimensionSpacePointWasMoved(DimensionSpacePointWasMoved $event): void { - $this->getDatabaseConnection()->executeStatement( + $this->dbal->executeStatement( ' UPDATE ' . $this->tableNamePrefix . ' c SET @@ -434,10 +432,10 @@ private function modifyChange( if ($change === null) { $change = new Change($contentStreamId, $nodeAggregateId, $originDimensionSpacePoint, false, false, false, false); $modifyFn($change); - $change->addToDatabase($this->getDatabaseConnection(), $this->tableNamePrefix); + $change->addToDatabase($this->dbal, $this->tableNamePrefix); } else { $modifyFn($change); - $change->updateToDatabase($this->getDatabaseConnection(), $this->tableNamePrefix); + $change->updateToDatabase($this->dbal, $this->tableNamePrefix); } } @@ -446,7 +444,7 @@ private function getChange( NodeAggregateId $nodeAggregateId, OriginDimensionSpacePoint $originDimensionSpacePoint, ): ?Change { - $changeRow = $this->getDatabaseConnection()->executeQuery( + $changeRow = $this->dbal->executeQuery( 'SELECT n.* FROM ' . $this->tableNamePrefix . ' n WHERE n.contentStreamId = :contentStreamId AND n.nodeAggregateId = :nodeAggregateId @@ -462,18 +460,10 @@ private function getChange( return $changeRow ? Change::fromDatabaseRow($changeRow) : null; } - /** - * @return Connection - */ - private function getDatabaseConnection(): Connection - { - return $this->dbalClient->getConnection(); - } - private function isLiveContentStream(ContentStreamId $contentStreamId): bool { if ($this->liveContentStreamIdsRuntimeCache === null) { - $this->liveContentStreamIdsRuntimeCache = $this->getDatabaseConnection()->fetchFirstColumn('SELECT contentstreamid FROM ' . $this->tableNamePrefix . '_livecontentstreams'); + $this->liveContentStreamIdsRuntimeCache = $this->dbal->fetchFirstColumn('SELECT contentstreamid FROM ' . $this->tableNamePrefix . '_livecontentstreams'); } return in_array($contentStreamId->value, $this->liveContentStreamIdsRuntimeCache, true); } diff --git a/Neos.Neos/Classes/PendingChangesProjection/ChangeProjectionFactory.php b/Neos.Neos/Classes/PendingChangesProjection/ChangeProjectionFactory.php index ca5f1a2e8a7..8b231897d78 100644 --- a/Neos.Neos/Classes/PendingChangesProjection/ChangeProjectionFactory.php +++ b/Neos.Neos/Classes/PendingChangesProjection/ChangeProjectionFactory.php @@ -14,8 +14,8 @@ namespace Neos\Neos\PendingChangesProjection; +use Doctrine\DBAL\Connection; use Neos\ContentRepository\Core\Factory\ProjectionFactoryDependencies; -use Neos\ContentRepository\Core\Infrastructure\DbalClientInterface; use Neos\ContentRepository\Core\Projection\ProjectionFactoryInterface; /** @@ -24,7 +24,7 @@ class ChangeProjectionFactory implements ProjectionFactoryInterface { public function __construct( - private readonly DbalClientInterface $dbalClient + private readonly Connection $dbal, ) { } @@ -33,7 +33,7 @@ public function build( array $options, ): ChangeProjection { return new ChangeProjection( - $this->dbalClient, + $this->dbal, sprintf( 'cr_%s_p_neos_change', $projectionFactoryDependencies->contentRepositoryId->value, diff --git a/composer.json b/composer.json index a4231726504..af95aa5438f 100644 --- a/composer.json +++ b/composer.json @@ -198,6 +198,9 @@ "Neos\\ContentRepositoryRegistry\\": [ "Neos.ContentRepositoryRegistry/Classes" ], + "Neos\\ContentRepository\\DbalTools\\": [ + "Neos.ContentRepository.DbalTools/Classes" + ], "Neos\\Diff\\": [ "Neos.Diff/Classes" ], From b817b1d7107f906f54b4a0cc0125aca0fb4ba56d Mon Sep 17 00:00:00 2001 From: Bastian Waidelich Date: Tue, 16 Apr 2024 15:16:30 +0200 Subject: [PATCH 09/21] Update composer manifest --- composer.json | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/composer.json b/composer.json index af95aa5438f..2140f292cb4 100644 --- a/composer.json +++ b/composer.json @@ -8,17 +8,16 @@ "require": { "neos/flow-development-collection": "9.0.x-dev", "doctrine/dbal": "^2.8", - "doctrine/migrations": "*", - "neos/eventstore": "^1", - "neos/eventstore-doctrineadapter": "^1 || ^2", "php": "^8.2", + "neos/eventstore": "^1", "neos/error-messages": "*", "neos/utility-objecthandling": "*", "neos/utility-arrays": "*", "symfony/serializer": "^6.3", "psr/clock": "^1", "behat/transliterator": "~1.0", - "ramsey/uuid": "^3.0 || ^4.0", + "ramsey/uuid": "^3 || ^4", + "symfony/lock": "^6", "league/flysystem": "^3", "webmozart/assert": "^1.11", "neos/flow": "*", @@ -128,6 +127,7 @@ "@test:behat-cli -c Neos.ContentRepository.LegacyNodeMigration/Tests/Behavior/behat.yml.dist", "@test:behat-cli -c Neos.ContentRepository.Export/Tests/Behavior/behat.yml.dist", "@test:behat-cli -c Neos.TimeableNodeVisibility/Tests/Behavior/behat.yml.dist", + "../../flow doctrine:migrate --quiet; ../../flow cr:setup", "@test:behat-cli -c Neos.Neos/Tests/Behavior/behat.yml" ], "test:behavioral:sync": [ @@ -140,6 +140,7 @@ "@test:behat-cli -vvv --stop-on-failure -c Neos.ContentRepository.LegacyNodeMigration/Tests/Behavior/behat.yml.dist", "@test:behat-cli -vvv --stop-on-failure -c Neos.ContentRepository.Export/Tests/Behavior/behat.yml.dist", "@test:behat-cli -vvv --stop-on-failure -c Neos.TimeableNodeVisibility/Tests/Behavior/behat.yml.dist", + "../../flow doctrine:migrate --quiet; ../../flow cr:setup", "@test:behat-cli -vvv --stop-on-failure -c Neos.Neos/Tests/Behavior/behat.yml" ], "test:behavioral:stop-on-failure:sync": [ @@ -168,6 +169,9 @@ "Neos\\ContentRepository\\Core\\": [ "Neos.ContentRepository.Core/Classes" ], + "Neos\\ContentRepository\\DbalTools\\": [ + "Neos.ContentRepository.DbalTools/Classes" + ], "Neos\\ContentRepository\\Export\\": [ "Neos.ContentRepository.Export/src/" ], @@ -186,21 +190,12 @@ "Neos\\ContentRepository\\TestSuite\\": [ "Neos.ContentRepository.TestSuite/Classes" ], - "Neos\\ContentRepositoryRegistry\\DoctrineDbalClient\\": [ - "Neos.ContentRepositoryRegistry.DoctrineDbalClient/Classes" - ], - "Neos\\ContentRepositoryRegistry\\PostgresDbalClient\\": [ - "Neos.ContentRepositoryRegistry.PostgresDbalClient/Classes" - ], "Neos\\ContentRepositoryRegistry\\TestSuite\\": [ "Neos.ContentRepositoryRegistry.TestSuite/Classes" ], "Neos\\ContentRepositoryRegistry\\": [ "Neos.ContentRepositoryRegistry/Classes" ], - "Neos\\ContentRepository\\DbalTools\\": [ - "Neos.ContentRepository.DbalTools/Classes" - ], "Neos\\Diff\\": [ "Neos.Diff/Classes" ], @@ -274,6 +269,9 @@ "Neos\\ContentRepository\\Core\\Tests\\": [ "Neos.ContentRepository.Core/Tests" ], + "Neos\\ContentRepository\\DbalTools\\Tests\\": [ + "Neos.ContentRepository.DbalTools/Tests" + ], "Neos\\ContentRepository\\LegacyNodeMigration\\Tests\\": [ "Neos.ContentRepository.LegacyNodeMigration/Tests" ], From cb653fda075fdd92b454a2db5dc8b484dbf58887 Mon Sep 17 00:00:00 2001 From: Bastian Waidelich Date: Tue, 16 Apr 2024 15:30:04 +0200 Subject: [PATCH 10/21] Tweak checkpoint error message --- .../src/DoctrineDbalContentGraphProjection.php | 2 +- .../src/Domain/Projection/HypergraphProjection.php | 2 +- .../Projection/ContentStream/ContentStreamProjection.php | 2 +- .../Classes/Projection/Workspace/WorkspaceProjection.php | 2 +- .../Classes/AssetUsage/Projection/AssetUsageProjection.php | 2 +- .../FrontendRouting/Projection/DocumentUriPathProjection.php | 2 +- Neos.Neos/Classes/PendingChangesProjection/ChangeProjection.php | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php index d3262df4f6b..b06a0ce1d21 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php @@ -141,7 +141,7 @@ public function status(): ProjectionStatus try { $this->getCheckpoint(); } catch (\Exception $exception) { - return ProjectionStatus::error($exception->getMessage()); + return ProjectionStatus::error('Error while retrieving checkpoint: ' . $exception->getMessage()); } return ProjectionStatus::ok(); } diff --git a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/HypergraphProjection.php b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/HypergraphProjection.php index bd498de6da6..39d0fde9122 100644 --- a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/HypergraphProjection.php +++ b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/HypergraphProjection.php @@ -121,7 +121,7 @@ public function status(): ProjectionStatus try { $this->getCheckpoint(); } catch (\Exception $exception) { - return ProjectionStatus::error($exception->getMessage()); + return ProjectionStatus::error('Error while retrieving checkpoint: ' . $exception->getMessage()); } return ProjectionStatus::ok(); } diff --git a/Neos.ContentRepository.Core/Classes/Projection/ContentStream/ContentStreamProjection.php b/Neos.ContentRepository.Core/Classes/Projection/ContentStream/ContentStreamProjection.php index fe81d27fdef..facafb9779f 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/ContentStream/ContentStreamProjection.php +++ b/Neos.ContentRepository.Core/Classes/Projection/ContentStream/ContentStreamProjection.php @@ -95,7 +95,7 @@ public function status(): ProjectionStatus try { $this->getCheckpoint(); } catch (\Exception $exception) { - return ProjectionStatus::error($exception->getMessage()); + return ProjectionStatus::error('Error while retrieving checkpoint: ' . $exception->getMessage()); } return ProjectionStatus::ok(); } diff --git a/Neos.ContentRepository.Core/Classes/Projection/Workspace/WorkspaceProjection.php b/Neos.ContentRepository.Core/Classes/Projection/Workspace/WorkspaceProjection.php index 83ab9593955..da6ecef9b90 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/Workspace/WorkspaceProjection.php +++ b/Neos.ContentRepository.Core/Classes/Projection/Workspace/WorkspaceProjection.php @@ -92,7 +92,7 @@ public function status(): ProjectionStatus try { $this->getCheckpoint(); } catch (\Exception $exception) { - return ProjectionStatus::error($exception->getMessage()); + return ProjectionStatus::error('Error while retrieving checkpoint: ' . $exception->getMessage()); } return ProjectionStatus::ok(); } diff --git a/Neos.Neos/Classes/AssetUsage/Projection/AssetUsageProjection.php b/Neos.Neos/Classes/AssetUsage/Projection/AssetUsageProjection.php index 9579dbb3af0..b5f5e0e3fc1 100644 --- a/Neos.Neos/Classes/AssetUsage/Projection/AssetUsageProjection.php +++ b/Neos.Neos/Classes/AssetUsage/Projection/AssetUsageProjection.php @@ -252,7 +252,7 @@ public function status(): ProjectionStatus try { $this->getCheckpoint(); } catch (\Exception $exception) { - return ProjectionStatus::error($exception->getMessage()); + return ProjectionStatus::error('Error while retrieving checkpoint: ' . $exception->getMessage()); } return ProjectionStatus::ok(); } diff --git a/Neos.Neos/Classes/FrontendRouting/Projection/DocumentUriPathProjection.php b/Neos.Neos/Classes/FrontendRouting/Projection/DocumentUriPathProjection.php index cf53b310675..feb69796f39 100644 --- a/Neos.Neos/Classes/FrontendRouting/Projection/DocumentUriPathProjection.php +++ b/Neos.Neos/Classes/FrontendRouting/Projection/DocumentUriPathProjection.php @@ -92,7 +92,7 @@ public function status(): ProjectionStatus try { $this->getCheckpoint(); } catch (\Exception $exception) { - return ProjectionStatus::error($exception->getMessage()); + return ProjectionStatus::error('Error while retrieving checkpoint: ' . $exception->getMessage()); } return ProjectionStatus::ok(); } diff --git a/Neos.Neos/Classes/PendingChangesProjection/ChangeProjection.php b/Neos.Neos/Classes/PendingChangesProjection/ChangeProjection.php index e6461c79dd2..aad423b04e9 100644 --- a/Neos.Neos/Classes/PendingChangesProjection/ChangeProjection.php +++ b/Neos.Neos/Classes/PendingChangesProjection/ChangeProjection.php @@ -98,7 +98,7 @@ public function status(): ProjectionStatus try { $this->getCheckpoint(); } catch (\Exception $exception) { - return ProjectionStatus::error($exception->getMessage()); + return ProjectionStatus::error('Error while retrieving checkpoint: ' . $exception->getMessage()); } return ProjectionStatus::ok(); } From 43da4c2c476bc62f8bca6105e7692bf49b7bafc8 Mon Sep 17 00:00:00 2001 From: Bastian Waidelich Date: Tue, 16 Apr 2024 15:32:20 +0200 Subject: [PATCH 11/21] Re-add `neos/eventstore-doctrineadapter` dependency --- Neos.ContentRepository.Core/composer.json | 1 + composer.json | 1 + 2 files changed, 2 insertions(+) diff --git a/Neos.ContentRepository.Core/composer.json b/Neos.ContentRepository.Core/composer.json index 4a7d56426ca..5d60bb7a02b 100644 --- a/Neos.ContentRepository.Core/composer.json +++ b/Neos.ContentRepository.Core/composer.json @@ -13,6 +13,7 @@ "require": { "php": "^8.2", "neos/eventstore": "^1", + "neos/eventstore-doctrineadapter": "^1 || ^2", "neos/error-messages": "*", "neos/utility-objecthandling": "*", "neos/utility-arrays": "*", diff --git a/composer.json b/composer.json index 2140f292cb4..4fd0de0f28b 100644 --- a/composer.json +++ b/composer.json @@ -10,6 +10,7 @@ "doctrine/dbal": "^2.8", "php": "^8.2", "neos/eventstore": "^1", + "neos/eventstore-doctrineadapter": "^1 || ^2", "neos/error-messages": "*", "neos/utility-objecthandling": "*", "neos/utility-arrays": "*", From bb1c498919a2f3670da1c242f2a3df7331c03356 Mon Sep 17 00:00:00 2001 From: Bastian Waidelich Date: Tue, 16 Apr 2024 15:38:13 +0200 Subject: [PATCH 12/21] Mostly cosmetic tweaks to satisfy linter --- .../src/Domain/Repository/ContentSubhypergraph.php | 5 ----- Neos.Fusion/Classes/Core/RuntimeConfiguration.php | 1 + 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Repository/ContentSubhypergraph.php b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Repository/ContentSubhypergraph.php index df2e0a7887e..5771b2479c1 100644 --- a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Repository/ContentSubhypergraph.php +++ b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Repository/ContentSubhypergraph.php @@ -529,11 +529,6 @@ private function findNodeByPathFromStartingNode(NodePath $path, Node $startingNo return $currentNode; } - private function getDatabaseConnection(): DatabaseConnection - { - return $this->dbal; - } - public function jsonSerialize(): ContentSubgraphIdentity { return $this->getIdentity(); diff --git a/Neos.Fusion/Classes/Core/RuntimeConfiguration.php b/Neos.Fusion/Classes/Core/RuntimeConfiguration.php index 9c207dc9c63..85a4cd8a426 100644 --- a/Neos.Fusion/Classes/Core/RuntimeConfiguration.php +++ b/Neos.Fusion/Classes/Core/RuntimeConfiguration.php @@ -68,6 +68,7 @@ public function forPath(string $fusionPath): array if ($fusionPath === '') { throw new Exception('Fusion path cannot be empty.', 1695308681); } + $currentPrototypeDefinitions = []; // Find longest prefix of path that already is in path cache $pathUntilNow = ''; From e62cb87c14f2d1d2048a8502c296db445dd1661e Mon Sep 17 00:00:00 2001 From: Bastian Waidelich Date: Wed, 17 Apr 2024 14:19:20 +0200 Subject: [PATCH 13/21] Make checkpoint table check a platform specific check ..to avoid status from showing a diff everytime --- Neos.ContentRepository.DbalTools/Classes/CheckpointHelper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Neos.ContentRepository.DbalTools/Classes/CheckpointHelper.php b/Neos.ContentRepository.DbalTools/Classes/CheckpointHelper.php index a6841a6f6e8..3b57a43e0f7 100644 --- a/Neos.ContentRepository.DbalTools/Classes/CheckpointHelper.php +++ b/Neos.ContentRepository.DbalTools/Classes/CheckpointHelper.php @@ -33,7 +33,7 @@ private function __construct() public static function checkpointTableSchema(string $tableNamePrefix): Table { return (new Table($tableNamePrefix . self::CHECKPOINT_TABLE_NAME_SUFFIX, [ - (new Column('id', Type::getType(Types::INTEGER)))->setCustomSchemaOption('check', 'CHECK (id = 0)'), + (new Column('id', Type::getType(Types::INTEGER)))->setPlatformOption('check', 'CHECK (id = 0)'), (new Column('appliedsequencenumber', Type::getType(Types::INTEGER))), ])) ->setPrimaryKey(['id']); From 7cc13ed40b5553111549fb66945aaea5c2ae9fea Mon Sep 17 00:00:00 2001 From: Bastian Waidelich Date: Wed, 17 Apr 2024 17:31:00 +0200 Subject: [PATCH 14/21] Remove notion of "sync" from composer scripts and readme --- .composer.json | 8 -------- .github/workflows/build.yml | 2 +- Readme.rst | 7 ------- composer.json | 8 -------- 4 files changed, 1 insertion(+), 24 deletions(-) diff --git a/.composer.json b/.composer.json index 903520e398f..6f7f5947917 100644 --- a/.composer.json +++ b/.composer.json @@ -45,10 +45,6 @@ "../../flow doctrine:migrate --quiet; ../../flow cr:setup", "@test:behat-cli -c Neos.Neos/Tests/Behavior/behat.yml" ], - "test:behavioral:sync": [ - "@putenv CATCHUPTRIGGER_ENABLE_SYNCHRONOUS_OPTION=1", - "@test:behavioral" - ], "test:behavioral:stop-on-failure": [ "@test:behat-cli -vvv --stop-on-failure -c Neos.ContentRepository.BehavioralTests/Tests/Behavior/behat.yml.dist", "@test:behat-cli -vvv --stop-on-failure -c Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/behat.yml.dist", @@ -58,10 +54,6 @@ "../../flow doctrine:migrate --quiet; ../../flow cr:setup", "@test:behat-cli -vvv --stop-on-failure -c Neos.Neos/Tests/Behavior/behat.yml" ], - "test:behavioral:stop-on-failure:sync": [ - "@putenv CATCHUPTRIGGER_ENABLE_SYNCHRONOUS_OPTION=1", - "@test:behavioral:stop-on-failure" - ], "test": [ "@test:unit", "@test:functional", diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9774cd47fe3..74d6e20291e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -249,7 +249,7 @@ jobs: # DEBUG MODE: ALTERNATIVELY, comment in the following lines to dump the DB. # do not exit the script if the tests break; as we want to upload the database dumps afterwards. set +e - composer test:behavioral:stop-on-failure:sync + composer test:behavioral:stop-on-failure retVal=$? # automatically search for race conditions diff --git a/Readme.rst b/Readme.rst index 4e114e2462d..f8200689add 100644 --- a/Readme.rst +++ b/Readme.rst @@ -188,13 +188,6 @@ we use the right versions etc). cd Packages/Neos composer test:behavioral -Running all tests can take a long time, depending on the hardware. -To speed up the process, Behat tests can be executed in a "synchronous" mode: - - .. code-block:: bash - - composer test:behavioral:sync - Alternatively, if you want to reproduce errors as they happen inside the CI system, but you develop on Mac OS, you might want to run the Behat tests in a Docker container (= a linux environment) as well. We have seen cases where they behave differently, i.e. where they run without race diff --git a/composer.json b/composer.json index 4fd0de0f28b..a753930c36a 100644 --- a/composer.json +++ b/composer.json @@ -131,10 +131,6 @@ "../../flow doctrine:migrate --quiet; ../../flow cr:setup", "@test:behat-cli -c Neos.Neos/Tests/Behavior/behat.yml" ], - "test:behavioral:sync": [ - "@putenv CATCHUPTRIGGER_ENABLE_SYNCHRONOUS_OPTION=1", - "@test:behavioral" - ], "test:behavioral:stop-on-failure": [ "@test:behat-cli -vvv --stop-on-failure -c Neos.ContentRepository.BehavioralTests/Tests/Behavior/behat.yml.dist", "@test:behat-cli -vvv --stop-on-failure -c Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/behat.yml.dist", @@ -144,10 +140,6 @@ "../../flow doctrine:migrate --quiet; ../../flow cr:setup", "@test:behat-cli -vvv --stop-on-failure -c Neos.Neos/Tests/Behavior/behat.yml" ], - "test:behavioral:stop-on-failure:sync": [ - "@putenv CATCHUPTRIGGER_ENABLE_SYNCHRONOUS_OPTION=1", - "@test:behavioral:stop-on-failure" - ], "test": [ "@test:unit", "@test:functional", From fc6ec5c4c0586ce6fdf6b4fb0c6b19c7971e770f Mon Sep 17 00:00:00 2001 From: Bastian Waidelich Date: Wed, 17 Apr 2024 17:33:09 +0200 Subject: [PATCH 15/21] Remove ProjectionCatchUpTriggerInterface and implementations ...for now --- .../Command/PerformanceMeasurementService.php | 4 +-- .../WorkspaceWritingDuringPublication.php | 1 - .../Classes/ContentRepository.php | 2 +- .../Classes/EventStore/EventPersister.php | 7 ++--- .../Factory/ContentRepositoryFactory.php | 3 -- .../Feature/WorkspaceCommandHandler.php | 4 +++ .../ProjectionCatchUpTriggerInterface.php | 18 ----------- .../Projection/WithMarkStaleInterface.php | 3 +- .../src/StructureAdjustmentService.php | 2 +- .../Features/Bootstrap/CRTestSuiteTrait.php | 1 - ...ricCommandExecutionAndEventPublication.php | 2 +- .../Classes/ContentRepositoryRegistry.php | 14 --------- .../DefaultCatchUpTrigger.php | 30 ------------------- ...DefaultProjectionCatchUpTriggerFactory.php | 23 -------------- ...ojectionCatchUpTriggerFactoryInterface.php | 12 -------- .../Configuration/Settings.yaml | 3 -- 16 files changed, 14 insertions(+), 115 deletions(-) delete mode 100644 Neos.ContentRepository.Core/Classes/Projection/ProjectionCatchUpTriggerInterface.php delete mode 100644 Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/DefaultCatchUpTrigger.php delete mode 100644 Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/DefaultProjectionCatchUpTriggerFactory.php delete mode 100644 Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/ProjectionCatchUpTriggerFactoryInterface.php diff --git a/Neos.ContentRepository.BehavioralTests/Classes/Command/PerformanceMeasurementService.php b/Neos.ContentRepository.BehavioralTests/Classes/Command/PerformanceMeasurementService.php index a16d29d090f..d331979c725 100644 --- a/Neos.ContentRepository.BehavioralTests/Classes/Command/PerformanceMeasurementService.php +++ b/Neos.ContentRepository.BehavioralTests/Classes/Command/PerformanceMeasurementService.php @@ -93,7 +93,7 @@ public function createNodesForPerformanceTest(int $nodesPerLevel, int $levels): NodeAggregateClassification::CLASSIFICATION_ROOT, ); - $this->eventPersister->publishEvents(new EventsToPublish( + $this->eventPersister->publishEvents($this->contentRepository, new EventsToPublish( $this->contentStreamEventStream->getEventStreamName(), Events::with($rootNodeAggregateWasCreated), ExpectedVersion::ANY() @@ -103,7 +103,7 @@ public function createNodesForPerformanceTest(int $nodesPerLevel, int $levels): $sumSoFar = 0; $events = []; $this->createHierarchy($rootNodeAggregateId, 1, $levels, $nodesPerLevel, $sumSoFar, $events); - $this->eventPersister->publishEvents(new EventsToPublish( + $this->eventPersister->publishEvents($this->contentRepository, new EventsToPublish( $this->contentStreamEventStream->getEventStreamName(), Events::fromArray($events), ExpectedVersion::ANY() diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Functional/Feature/WorkspacePublication/WorkspaceWritingDuringPublication.php b/Neos.ContentRepository.BehavioralTests/Tests/Functional/Feature/WorkspacePublication/WorkspaceWritingDuringPublication.php index 8196cbfcd89..f89eac38b18 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Functional/Feature/WorkspacePublication/WorkspaceWritingDuringPublication.php +++ b/Neos.ContentRepository.BehavioralTests/Tests/Functional/Feature/WorkspacePublication/WorkspaceWritingDuringPublication.php @@ -43,7 +43,6 @@ use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceTitle; use Neos\ContentRepository\TestSuite\Behavior\Features\Bootstrap\CRTestSuiteTrait; use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry; -use Neos\ContentRepositoryRegistry\Factory\ProjectionCatchUpTrigger\DefaultCatchUpTrigger; use Neos\EventStore\Exception\ConcurrencyException; use Neos\Flow\Tests\FunctionalTestCase; use PHPUnit\Framework\Assert; diff --git a/Neos.ContentRepository.Core/Classes/ContentRepository.php b/Neos.ContentRepository.Core/Classes/ContentRepository.php index 9f35e6ea7a8..e753d30bb9a 100644 --- a/Neos.ContentRepository.Core/Classes/ContentRepository.php +++ b/Neos.ContentRepository.Core/Classes/ContentRepository.php @@ -125,7 +125,7 @@ public function handle(CommandInterface $command): object $eventsToPublish->expectedVersion, ); - $this->eventPersister->publishEvents($eventsToPublish); + $this->eventPersister->publishEvents($this, $eventsToPublish); return new class { /** * @deprecated backwards compatibility layer diff --git a/Neos.ContentRepository.Core/Classes/EventStore/EventPersister.php b/Neos.ContentRepository.Core/Classes/EventStore/EventPersister.php index 04cc11ba712..8a7a43a62a4 100644 --- a/Neos.ContentRepository.Core/Classes/EventStore/EventPersister.php +++ b/Neos.ContentRepository.Core/Classes/EventStore/EventPersister.php @@ -4,7 +4,7 @@ namespace Neos\ContentRepository\Core\EventStore; -use Neos\ContentRepository\Core\Projection\ProjectionCatchUpTriggerInterface; +use Neos\ContentRepository\Core\ContentRepository; use Neos\ContentRepository\Core\Projection\Projections; use Neos\ContentRepository\Core\Projection\WithMarkStaleInterface; use Neos\EventStore\EventStoreInterface; @@ -23,7 +23,6 @@ final class EventPersister { public function __construct( private readonly EventStoreInterface $eventStore, - private readonly ProjectionCatchUpTriggerInterface $projectionCatchUpTrigger, private readonly EventNormalizer $eventNormalizer, private readonly Projections $projections, ) { @@ -33,7 +32,7 @@ public function __construct( * @param EventsToPublish $eventsToPublish * @throws ConcurrencyException in case the expectedVersion does not match */ - public function publishEvents(EventsToPublish $eventsToPublish): void + public function publishEvents(ContentRepository $contentRepository, EventsToPublish $eventsToPublish): void { if ($eventsToPublish->events->isEmpty()) { return; @@ -53,7 +52,7 @@ public function publishEvents(EventsToPublish $eventsToPublish): void $projection->markStale(); } } - $this->projectionCatchUpTrigger->triggerCatchUp(); + $contentRepository->catchUpProjections(); } private function normalizeEvent(EventInterface|DecoratedEvent $event): Event diff --git a/Neos.ContentRepository.Core/Classes/Factory/ContentRepositoryFactory.php b/Neos.ContentRepository.Core/Classes/Factory/ContentRepositoryFactory.php index b23f23851c0..c14bf686d38 100644 --- a/Neos.ContentRepository.Core/Classes/Factory/ContentRepositoryFactory.php +++ b/Neos.ContentRepository.Core/Classes/Factory/ContentRepositoryFactory.php @@ -28,7 +28,6 @@ use Neos\ContentRepository\Core\Feature\WorkspaceCommandHandler; use Neos\ContentRepository\Core\Infrastructure\Property\PropertyConverter; use Neos\ContentRepository\Core\NodeType\NodeTypeManager; -use Neos\ContentRepository\Core\Projection\ProjectionCatchUpTriggerInterface; use Neos\ContentRepository\Core\Projection\ProjectionsAndCatchUpHooks; use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId; use Neos\ContentRepository\Core\SharedModel\User\UserIdProviderInterface; @@ -53,7 +52,6 @@ public function __construct( ContentDimensionSourceInterface $contentDimensionSource, Serializer $propertySerializer, ProjectionsAndCatchUpHooksFactory $projectionsAndCatchUpHooksFactory, - private readonly ProjectionCatchUpTriggerInterface $projectionCatchUpTrigger, private readonly UserIdProviderInterface $userIdProvider, private readonly ClockInterface $clock, ) { @@ -165,7 +163,6 @@ private function buildEventPersister(): EventPersister if (!$this->eventPersister) { $this->eventPersister = new EventPersister( $this->projectionFactoryDependencies->eventStore, - $this->projectionCatchUpTrigger, $this->projectionFactoryDependencies->eventNormalizer, $this->projectionsAndCatchUpHooks->projections, ); diff --git a/Neos.ContentRepository.Core/Classes/Feature/WorkspaceCommandHandler.php b/Neos.ContentRepository.Core/Classes/Feature/WorkspaceCommandHandler.php index 24e44575341..617c0ecf50d 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/WorkspaceCommandHandler.php +++ b/Neos.ContentRepository.Core/Classes/Feature/WorkspaceCommandHandler.php @@ -247,6 +247,7 @@ private function handlePublishWorkspace( $baseWorkspace = $this->requireBaseWorkspace($workspace, $contentRepository); $this->publishContentStream( + $contentRepository, $workspace->currentContentStreamId, $baseWorkspace->currentContentStreamId ); @@ -281,6 +282,7 @@ private function handlePublishWorkspace( * @throws \Exception */ private function publishContentStream( + ContentRepository $contentRepository, ContentStreamId $contentStreamId, ContentStreamId $baseContentStreamId, ): void { @@ -332,6 +334,7 @@ private function publishContentStream( } try { $this->eventPersister->publishEvents( + $contentRepository, new EventsToPublish( $baseWorkspaceContentStreamName->getEventStreamName(), Events::fromArray($events), @@ -540,6 +543,7 @@ function () use ($matchingCommands, $contentRepository, $baseWorkspace): void { // 5) take EVENTS(MATCHING) and apply them to base WS. $this->publishContentStream( + $contentRepository, $command->contentStreamIdForMatchingPart, $baseWorkspace->currentContentStreamId ); diff --git a/Neos.ContentRepository.Core/Classes/Projection/ProjectionCatchUpTriggerInterface.php b/Neos.ContentRepository.Core/Classes/Projection/ProjectionCatchUpTriggerInterface.php deleted file mode 100644 index d4b7331533e..00000000000 --- a/Neos.ContentRepository.Core/Classes/Projection/ProjectionCatchUpTriggerInterface.php +++ /dev/null @@ -1,18 +0,0 @@ -remediation; $eventsToPublish = $remediation(); assert($eventsToPublish instanceof EventsToPublish); - $this->eventPersister->publishEvents($eventsToPublish); + $this->eventPersister->publishEvents($this->contentRepository, $eventsToPublish); } } } diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteTrait.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteTrait.php index f2c0210cf4d..3211465748c 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteTrait.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteTrait.php @@ -49,7 +49,6 @@ use Neos\ContentRepository\TestSuite\Behavior\Features\Bootstrap\Features\WorkspaceCreation; use Neos\ContentRepository\TestSuite\Behavior\Features\Bootstrap\Features\WorkspaceDiscarding; use Neos\ContentRepository\TestSuite\Behavior\Features\Bootstrap\Features\WorkspacePublishing; -use Neos\ContentRepositoryRegistry\Factory\ProjectionCatchUpTrigger\DefaultCatchUpTrigger; use Neos\EventStore\EventStoreInterface; use PHPUnit\Framework\Assert; diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/GenericCommandExecutionAndEventPublication.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/GenericCommandExecutionAndEventPublication.php index c8e2118d5e4..bc49c4c9e37 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/GenericCommandExecutionAndEventPublication.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/GenericCommandExecutionAndEventPublication.php @@ -140,7 +140,7 @@ protected function publishEvent(string $eventType, StreamName $streamName, array ->getValue($eventPersister); $event = $eventNormalizer->denormalize($artificiallyConstructedEvent); - $eventPersister->publishEvents(new EventsToPublish( + $eventPersister->publishEvents($this->currentContentRepository, new EventsToPublish( $streamName, Events::with($event), ExpectedVersion::ANY() diff --git a/Neos.ContentRepositoryRegistry/Classes/ContentRepositoryRegistry.php b/Neos.ContentRepositoryRegistry/Classes/ContentRepositoryRegistry.php index 25daca7cf84..72388acbd06 100644 --- a/Neos.ContentRepositoryRegistry/Classes/ContentRepositoryRegistry.php +++ b/Neos.ContentRepositoryRegistry/Classes/ContentRepositoryRegistry.php @@ -13,7 +13,6 @@ use Neos\ContentRepository\Core\Projection\CatchUpHookFactoryInterface; use Neos\ContentRepository\Core\Projection\ContentGraph\ContentSubgraphInterface; use Neos\ContentRepository\Core\Projection\ContentGraph\Node; -use Neos\ContentRepository\Core\Projection\ProjectionCatchUpTriggerInterface; use Neos\ContentRepository\Core\Projection\ProjectionFactoryInterface; use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId; use Neos\ContentRepository\Core\SharedModel\User\UserIdProviderInterface; @@ -23,7 +22,6 @@ use Neos\ContentRepositoryRegistry\Factory\ContentDimensionSource\ContentDimensionSourceFactoryInterface; use Neos\ContentRepositoryRegistry\Factory\EventStore\EventStoreFactoryInterface; use Neos\ContentRepositoryRegistry\Factory\NodeTypeManager\NodeTypeManagerFactoryInterface; -use Neos\ContentRepositoryRegistry\Factory\ProjectionCatchUpTrigger\ProjectionCatchUpTriggerFactoryInterface; use Neos\ContentRepositoryRegistry\Factory\UserIdProvider\UserIdProviderFactoryInterface; use Neos\EventStore\EventStoreInterface; use Neos\Flow\Annotations as Flow; @@ -155,7 +153,6 @@ private function buildFactory(ContentRepositoryId $contentRepositoryId): Content $this->buildContentDimensionSource($contentRepositoryId, $contentRepositorySettings), $this->buildPropertySerializer($contentRepositoryId, $contentRepositorySettings), $this->buildProjectionsFactory($contentRepositoryId, $contentRepositorySettings), - $this->buildProjectionCatchUpTrigger($contentRepositoryId, $contentRepositorySettings), $this->buildUserIdProvider($contentRepositoryId, $contentRepositorySettings), $clock, ); @@ -249,17 +246,6 @@ private function buildProjectionsFactory(ContentRepositoryId $contentRepositoryI return $projectionsFactory; } - /** @param array $contentRepositorySettings */ - private function buildProjectionCatchUpTrigger(ContentRepositoryId $contentRepositoryId, array $contentRepositorySettings): ProjectionCatchUpTriggerInterface - { - isset($contentRepositorySettings['projectionCatchUpTrigger']['factoryObjectName']) || throw InvalidConfigurationException::fromMessage('Content repository "%s" does not have projectionCatchUpTrigger.factoryObjectName configured.', $contentRepositoryId->value); - $projectionCatchUpTriggerFactory = $this->objectManager->get($contentRepositorySettings['projectionCatchUpTrigger']['factoryObjectName']); - if (!$projectionCatchUpTriggerFactory instanceof ProjectionCatchUpTriggerFactoryInterface) { - throw InvalidConfigurationException::fromMessage('projectionCatchUpTrigger.factoryObjectName for content repository "%s" is not an instance of %s but %s.', $contentRepositoryId->value, ProjectionCatchUpTriggerFactoryInterface::class, get_debug_type($projectionCatchUpTriggerFactory)); - } - return $projectionCatchUpTriggerFactory->build($contentRepositoryId, $contentRepositorySettings['projectionCatchUpTrigger']['options'] ?? []); - } - /** @param array $contentRepositorySettings */ private function buildUserIdProvider(ContentRepositoryId $contentRepositoryId, array $contentRepositorySettings): UserIdProviderInterface { diff --git a/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/DefaultCatchUpTrigger.php b/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/DefaultCatchUpTrigger.php deleted file mode 100644 index d37045664b9..00000000000 --- a/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/DefaultCatchUpTrigger.php +++ /dev/null @@ -1,30 +0,0 @@ -contentRepositoryRegistry->get($this->contentRepositoryId); - $contentRepository->catchUpProjections(); - } -} diff --git a/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/DefaultProjectionCatchUpTriggerFactory.php b/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/DefaultProjectionCatchUpTriggerFactory.php deleted file mode 100644 index 7d7948ecce6..00000000000 --- a/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/DefaultProjectionCatchUpTriggerFactory.php +++ /dev/null @@ -1,23 +0,0 @@ - $options */ - public function build(ContentRepositoryId $contentRepositoryId, array $options): DefaultCatchUpTrigger - { - return new DefaultCatchUpTrigger($this->contentRepositoryRegistry, $contentRepositoryId); - } -} diff --git a/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/ProjectionCatchUpTriggerFactoryInterface.php b/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/ProjectionCatchUpTriggerFactoryInterface.php deleted file mode 100644 index 5f73b1859ad..00000000000 --- a/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/ProjectionCatchUpTriggerFactoryInterface.php +++ /dev/null @@ -1,12 +0,0 @@ - $options */ - public function build(ContentRepositoryId $contentRepositoryId, array $options): ProjectionCatchUpTriggerInterface; -} diff --git a/Neos.ContentRepositoryRegistry/Configuration/Settings.yaml b/Neos.ContentRepositoryRegistry/Configuration/Settings.yaml index 7c9dc6dd183..f0c3630611c 100644 --- a/Neos.ContentRepositoryRegistry/Configuration/Settings.yaml +++ b/Neos.ContentRepositoryRegistry/Configuration/Settings.yaml @@ -31,9 +31,6 @@ Neos: contentDimensionSource: factoryObjectName: Neos\ContentRepositoryRegistry\Factory\ContentDimensionSource\ConfigurationBasedContentDimensionSourceFactory - projectionCatchUpTrigger: - factoryObjectName: Neos\ContentRepositoryRegistry\Factory\ProjectionCatchUpTrigger\DefaultProjectionCatchUpTriggerFactory - userIdProvider: factoryObjectName: Neos\ContentRepositoryRegistry\Factory\UserIdProvider\StaticUserIdProviderFactory From ed47eb63336261e0ca0ccd1f3aaabc0eb5a91b4a Mon Sep 17 00:00:00 2001 From: Bastian Waidelich Date: Fri, 26 Apr 2024 17:15:15 +0200 Subject: [PATCH 16/21] Fix ContentStreamProjection checkpoint --- .../Classes/Projection/ContentStream/ContentStreamProjection.php | 1 + 1 file changed, 1 insertion(+) diff --git a/Neos.ContentRepository.Core/Classes/Projection/ContentStream/ContentStreamProjection.php b/Neos.ContentRepository.Core/Classes/Projection/ContentStream/ContentStreamProjection.php index facafb9779f..8b523c81b13 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/ContentStream/ContentStreamProjection.php +++ b/Neos.ContentRepository.Core/Classes/Projection/ContentStream/ContentStreamProjection.php @@ -136,6 +136,7 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void $this->dbal->beginTransaction(); if ($event instanceof EmbedsContentStreamAndNodeAggregateId) { $this->updateContentStreamVersion($event, $eventEnvelope); + CheckpointHelper::updateCheckpoint($this->dbal, $this->tableName, $eventEnvelope->sequenceNumber); $this->dbal->commit(); return; } From 4c68ca7d418b52eb82d416ae00c56954b5549dab Mon Sep 17 00:00:00 2001 From: Bastian Waidelich Date: Wed, 1 May 2024 10:57:53 +0200 Subject: [PATCH 17/21] BUGFIX: Remove doctrine migrate and cr setup commands from behat scripts See #5005 --- .composer.json | 2 -- composer.json | 2 -- 2 files changed, 4 deletions(-) diff --git a/.composer.json b/.composer.json index 6f7f5947917..0cd8cff5364 100644 --- a/.composer.json +++ b/.composer.json @@ -42,7 +42,6 @@ "@test:behat-cli -c Neos.ContentRepository.LegacyNodeMigration/Tests/Behavior/behat.yml.dist", "@test:behat-cli -c Neos.ContentRepository.Export/Tests/Behavior/behat.yml.dist", "@test:behat-cli -c Neos.TimeableNodeVisibility/Tests/Behavior/behat.yml.dist", - "../../flow doctrine:migrate --quiet; ../../flow cr:setup", "@test:behat-cli -c Neos.Neos/Tests/Behavior/behat.yml" ], "test:behavioral:stop-on-failure": [ @@ -51,7 +50,6 @@ "@test:behat-cli -vvv --stop-on-failure -c Neos.ContentRepository.LegacyNodeMigration/Tests/Behavior/behat.yml.dist", "@test:behat-cli -vvv --stop-on-failure -c Neos.ContentRepository.Export/Tests/Behavior/behat.yml.dist", "@test:behat-cli -vvv --stop-on-failure -c Neos.TimeableNodeVisibility/Tests/Behavior/behat.yml.dist", - "../../flow doctrine:migrate --quiet; ../../flow cr:setup", "@test:behat-cli -vvv --stop-on-failure -c Neos.Neos/Tests/Behavior/behat.yml" ], "test": [ diff --git a/composer.json b/composer.json index a753930c36a..b32542b05e0 100644 --- a/composer.json +++ b/composer.json @@ -128,7 +128,6 @@ "@test:behat-cli -c Neos.ContentRepository.LegacyNodeMigration/Tests/Behavior/behat.yml.dist", "@test:behat-cli -c Neos.ContentRepository.Export/Tests/Behavior/behat.yml.dist", "@test:behat-cli -c Neos.TimeableNodeVisibility/Tests/Behavior/behat.yml.dist", - "../../flow doctrine:migrate --quiet; ../../flow cr:setup", "@test:behat-cli -c Neos.Neos/Tests/Behavior/behat.yml" ], "test:behavioral:stop-on-failure": [ @@ -137,7 +136,6 @@ "@test:behat-cli -vvv --stop-on-failure -c Neos.ContentRepository.LegacyNodeMigration/Tests/Behavior/behat.yml.dist", "@test:behat-cli -vvv --stop-on-failure -c Neos.ContentRepository.Export/Tests/Behavior/behat.yml.dist", "@test:behat-cli -vvv --stop-on-failure -c Neos.TimeableNodeVisibility/Tests/Behavior/behat.yml.dist", - "../../flow doctrine:migrate --quiet; ../../flow cr:setup", "@test:behat-cli -vvv --stop-on-failure -c Neos.Neos/Tests/Behavior/behat.yml" ], "test": [ From 7bfd9419c80990ec6bc991260ca38c8c0b71b7ef Mon Sep 17 00:00:00 2001 From: Bastian Waidelich Date: Wed, 1 May 2024 11:47:47 +0200 Subject: [PATCH 18/21] Use dedicated connection for EventStore in order to prevent nested transactions potentially leading to RuntimeException of A transaction is active already, can't commit events! --- .../Factory/EventStore/DoctrineEventStoreFactory.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Neos.ContentRepositoryRegistry/Classes/Factory/EventStore/DoctrineEventStoreFactory.php b/Neos.ContentRepositoryRegistry/Classes/Factory/EventStore/DoctrineEventStoreFactory.php index f5874b41990..f42bf4571a7 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Factory/EventStore/DoctrineEventStoreFactory.php +++ b/Neos.ContentRepositoryRegistry/Classes/Factory/EventStore/DoctrineEventStoreFactory.php @@ -3,7 +3,8 @@ namespace Neos\ContentRepositoryRegistry\Factory\EventStore; -use Doctrine\DBAL\Connection; +use Doctrine\DBAL\DriverManager; +use Doctrine\ORM\EntityManagerInterface; use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId; use Neos\EventStore\DoctrineAdapter\DoctrineEventStore; use Neos\EventStore\EventStoreInterface; @@ -12,15 +13,17 @@ class DoctrineEventStoreFactory implements EventStoreFactoryInterface { public function __construct( - private readonly Connection $connection, + private readonly EntityManagerInterface $entityManager, ) { } /** @param array $options */ public function build(ContentRepositoryId $contentRepositoryId, array $options, ClockInterface $clock): EventStoreInterface { + // We create a new connection instance in order to avoid nested transactions + $connection = DriverManager::getConnection($this->entityManager->getConnection()->getParams(), $this->entityManager->getConfiguration(), $this->entityManager->getEventManager()); return new DoctrineEventStore( - $this->connection, + $connection, self::databaseTableName($contentRepositoryId), $clock ); From e2e8af6e2f858c8c1a2b65f3ed690740efe601b1 Mon Sep 17 00:00:00 2001 From: Bastian Waidelich Date: Wed, 1 May 2024 12:49:15 +0200 Subject: [PATCH 19/21] Re-use previously created event store instances --- .../EventStore/DoctrineEventStoreFactory.php | 31 +++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/Neos.ContentRepositoryRegistry/Classes/Factory/EventStore/DoctrineEventStoreFactory.php b/Neos.ContentRepositoryRegistry/Classes/Factory/EventStore/DoctrineEventStoreFactory.php index f42bf4571a7..6b7748f5602 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Factory/EventStore/DoctrineEventStoreFactory.php +++ b/Neos.ContentRepositoryRegistry/Classes/Factory/EventStore/DoctrineEventStoreFactory.php @@ -7,26 +7,39 @@ use Doctrine\ORM\EntityManagerInterface; use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId; use Neos\EventStore\DoctrineAdapter\DoctrineEventStore; -use Neos\EventStore\EventStoreInterface; use Psr\Clock\ClockInterface; class DoctrineEventStoreFactory implements EventStoreFactoryInterface { + /** + * @var array Runtime cache for created event store instances to prevent too many connections + */ + private static array $instances = []; + public function __construct( private readonly EntityManagerInterface $entityManager, ) { } /** @param array $options */ - public function build(ContentRepositoryId $contentRepositoryId, array $options, ClockInterface $clock): EventStoreInterface + public function build(ContentRepositoryId $contentRepositoryId, array $options, ClockInterface $clock): DoctrineEventStore { - // We create a new connection instance in order to avoid nested transactions - $connection = DriverManager::getConnection($this->entityManager->getConnection()->getParams(), $this->entityManager->getConfiguration(), $this->entityManager->getEventManager()); - return new DoctrineEventStore( - $connection, - self::databaseTableName($contentRepositoryId), - $clock - ); + $dsn = $options['dsn'] ?? null; + $hash = md5($contentRepositoryId->value . '|' . $clock::class . '|' . $dsn); + if (!array_key_exists($hash, self::$instances)) { + if ($dsn !== null) { + $connection = DriverManager::getConnection(['url' => $dsn]); + } else { + // We create a new connection instance in order to avoid nested transactions + $connection = DriverManager::getConnection($this->entityManager->getConnection()->getParams(), $this->entityManager->getConfiguration(), $this->entityManager->getEventManager()); + } + self::$instances[$hash] = new DoctrineEventStore( + $connection, + self::databaseTableName($contentRepositoryId), + $clock + ); + } + return self::$instances[$hash]; } public static function databaseTableName(ContentRepositoryId $contentRepositoryId): string From adf6eefb97ed767ba1d33d61c6367001db9acf44 Mon Sep 17 00:00:00 2001 From: mhsdesign <85400359+mhsdesign@users.noreply.github.com> Date: Fri, 17 May 2024 10:32:01 +0200 Subject: [PATCH 20/21] TASK: Adjustments after merging 9.0 (beta10) to satisfy phpstan mostly --- .../src/ContentGraphFactory.php | 8 ++++---- .../src/ContentGraphTableNames.php | 2 +- .../src/DoctrineDbalContentGraphProjection.php | 9 +++++---- .../src/DoctrineDbalContentGraphSchemaBuilder.php | 2 +- .../src/Domain/Repository/ContentGraph.php | 2 +- .../src/Domain/Repository/ContentSubgraph.php | 3 ++- .../src/Domain/Repository/ProjectionContentGraph.php | 1 - .../src/ContentHyperGraphFactory.php | 8 ++++---- .../Classes/CommandHandlingDependencies.php | 4 ++-- .../Command/ContentGraphIntegrityCommandController.php | 6 +++--- phpstan.neon.dist | 4 ++++ 11 files changed, 27 insertions(+), 22 deletions(-) diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/ContentGraphFactory.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/ContentGraphFactory.php index 66ae7720899..6af078fac08 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/ContentGraphFactory.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/ContentGraphFactory.php @@ -12,10 +12,10 @@ namespace Neos\ContentGraph\DoctrineDbalAdapter; +use Doctrine\DBAL\Connection; use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\ContentGraph; use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\NodeFactory; use Neos\ContentRepository\Core\ContentGraphFactoryInterface; -use Neos\ContentRepository\Core\Infrastructure\DbalClientInterface; use Neos\ContentRepository\Core\NodeType\NodeTypeManager; use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId; use Neos\ContentRepository\Core\SharedModel\Exception\WorkspaceDoesNotExist; @@ -29,7 +29,7 @@ final readonly class ContentGraphFactory implements ContentGraphFactoryInterface { public function __construct( - private DbalClientInterface $client, + private Connection $dbal, private NodeFactory $nodeFactory, private ContentRepositoryId $contentRepositoryId, private NodeTypeManager $nodeTypeManager, @@ -46,7 +46,7 @@ public function buildForWorkspace(WorkspaceName $workspaceName): ContentGraph 'workspace' )); - $row = $this->client->getConnection()->executeQuery( + $row = $this->dbal->executeQuery( ' SELECT * FROM ' . $tableName . ' WHERE workspaceName = :workspaceName @@ -66,6 +66,6 @@ public function buildForWorkspace(WorkspaceName $workspaceName): ContentGraph public function buildForWorkspaceAndContentStream(WorkspaceName $workspaceName, ContentStreamId $contentStreamId): ContentGraph { - return new ContentGraph($this->client, $this->nodeFactory, $this->contentRepositoryId, $this->nodeTypeManager, $this->tableNames, $workspaceName, $contentStreamId); + return new ContentGraph($this->dbal, $this->nodeFactory, $this->contentRepositoryId, $this->nodeTypeManager, $this->tableNames, $workspaceName, $contentStreamId); } } diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/ContentGraphTableNames.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/ContentGraphTableNames.php index 0804d77e7e0..438a4ec0e19 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/ContentGraphTableNames.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/ContentGraphTableNames.php @@ -11,7 +11,7 @@ final readonly class ContentGraphTableNames { private function __construct( - private string $tableNamePrefix + public string $tableNamePrefix ) { } diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php index 0e6ef46e433..953caf3d6bf 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php @@ -52,6 +52,7 @@ use Neos\ContentRepository\Core\SharedModel\Node\NodeName; use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; use Neos\ContentRepository\DbalTools\CheckpointHelper; +use Neos\ContentRepository\DbalTools\DbalSchemaDiff; use Neos\EventStore\Model\Event\SequenceNumber; use Neos\EventStore\Model\EventEnvelope; @@ -88,7 +89,7 @@ public function setUp(): void foreach ($this->determineRequiredSqlStatements() as $statement) { $this->dbal->executeStatement($statement); } - CheckpointHelper::resetCheckpoint($this->dbal, $this->getTableNamePrefix()); + CheckpointHelper::resetCheckpoint($this->dbal, $this->tableNames->tableNamePrefix); } /** @@ -133,7 +134,7 @@ public function reset(): void $this->dbal->executeQuery('TRUNCATE table ' . $this->tableNames->hierarchyRelation()); $this->dbal->executeQuery('TRUNCATE table ' . $this->tableNames->referenceRelation()); $this->dbal->executeQuery('TRUNCATE table ' . $this->tableNames->dimensionSpacePoints()); - CheckpointHelper::resetCheckpoint($this->dbal, $this->getTableNamePrefix()); + CheckpointHelper::resetCheckpoint($this->dbal, $this->tableNames->tableNamePrefix); $this->getState()->forgetInstances(); } @@ -161,13 +162,13 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void SubtreeWasUntagged::class => $this->whenSubtreeWasUntagged($event), default => null, }; - CheckpointHelper::updateCheckpoint($this->dbal, $this->getTableNamePrefix(), $eventEnvelope->sequenceNumber); + CheckpointHelper::updateCheckpoint($this->dbal, $this->tableNames->tableNamePrefix, $eventEnvelope->sequenceNumber); $this->dbal->commit(); } public function getCheckpoint(): SequenceNumber { - return CheckpointHelper::getCheckpoint($this->dbal, $this->getTableNamePrefix()); + return CheckpointHelper::getCheckpoint($this->dbal, $this->tableNames->tableNamePrefix); } public function getState(): ContentGraphFinder diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphSchemaBuilder.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphSchemaBuilder.php index 6bfe58e089c..7c4c92d3fa5 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphSchemaBuilder.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphSchemaBuilder.php @@ -30,7 +30,7 @@ public function buildSchema(AbstractSchemaManager $schemaManager): Schema $this->createHierarchyRelationTable(), $this->createReferenceRelationTable(), $this->createDimensionSpacePointsTable(), - CheckpointHelper::checkpointTableSchema($this->tableNamePrefix), + CheckpointHelper::checkpointTableSchema($this->contentGraphTableNames->tableNamePrefix), ]); } diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ContentGraph.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ContentGraph.php index c647b52d0c4..b5992bd4a02 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ContentGraph.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ContentGraph.php @@ -80,7 +80,7 @@ public function __construct( public readonly WorkspaceName $workspaceName, public readonly ContentStreamId $contentStreamId ) { - $this->nodeQueryBuilder = new NodeQueryBuilder($this->client->getConnection(), $this->tableNames); + $this->nodeQueryBuilder = new NodeQueryBuilder($this->dbal, $this->tableNames); } public function getContentRepositoryId(): ContentRepositoryId diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ContentSubgraph.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ContentSubgraph.php index 4124e049acf..918fb09c502 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ContentSubgraph.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ContentSubgraph.php @@ -14,6 +14,7 @@ namespace Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository; +use Doctrine\DBAL\Connection; use Doctrine\DBAL\Driver\Exception as DbalDriverException; use Doctrine\DBAL\Exception as DbalException; use Doctrine\DBAL\ForwardCompatibility\Result; @@ -100,7 +101,7 @@ public function __construct( private readonly NodeTypeManager $nodeTypeManager, ContentGraphTableNames $tableNames ) { - $this->nodeQueryBuilder = new NodeQueryBuilder($this->client->getConnection(), $tableNames); + $this->nodeQueryBuilder = new NodeQueryBuilder($this->dbal, $tableNames); } public function getContentRepositoryId(): ContentRepositoryId diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ProjectionContentGraph.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ProjectionContentGraph.php index e3f566d9a04..30b9518c84d 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ProjectionContentGraph.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ProjectionContentGraph.php @@ -26,7 +26,6 @@ use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePointSet; use Neos\ContentRepository\Core\DimensionSpace\OriginDimensionSpacePoint; use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId; -use Neos\ContentRepository\Core\SharedModel\Node\NodeName; use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; /** diff --git a/Neos.ContentGraph.PostgreSQLAdapter/src/ContentHyperGraphFactory.php b/Neos.ContentGraph.PostgreSQLAdapter/src/ContentHyperGraphFactory.php index ebb74ab5035..55b8b529a80 100644 --- a/Neos.ContentGraph.PostgreSQLAdapter/src/ContentHyperGraphFactory.php +++ b/Neos.ContentGraph.PostgreSQLAdapter/src/ContentHyperGraphFactory.php @@ -2,9 +2,9 @@ namespace Neos\ContentGraph\PostgreSQLAdapter; +use Doctrine\DBAL\Connection; use Neos\ContentGraph\PostgreSQLAdapter\Domain\Repository\ContentHypergraph; use Neos\ContentGraph\PostgreSQLAdapter\Domain\Repository\NodeFactory; -use Neos\ContentGraph\PostgreSQLAdapter\Infrastructure\PostgresDbalClientInterface; use Neos\ContentRepository\Core\ContentGraphFactoryInterface; use Neos\ContentRepository\Core\ContentGraphFinder; use Neos\ContentRepository\Core\NodeType\NodeTypeManager; @@ -21,7 +21,7 @@ final readonly class ContentHyperGraphFactory implements ContentGraphFactoryInterface { public function __construct( - private PostgresDbalClientInterface $databaseClient, + private Connection $dbal, private NodeFactory $nodeFactory, private ContentRepositoryId $contentRepositoryId, private NodeTypeManager $nodeTypeManager, @@ -38,7 +38,7 @@ public function buildForWorkspace(WorkspaceName $workspaceName): ContentGraphInt 'Workspace' )); - $row = $this->databaseClient->getConnection()->executeQuery( + $row = $this->dbal->executeQuery( ' SELECT * FROM ' . $tableName . ' WHERE workspaceName = :workspaceName @@ -57,6 +57,6 @@ public function buildForWorkspace(WorkspaceName $workspaceName): ContentGraphInt public function buildForWorkspaceAndContentStream(WorkspaceName $workspaceName, ContentStreamId $contentStreamId): ContentGraphInterface { - return new ContentHyperGraph($this->databaseClient, $this->nodeFactory, $this->contentRepositoryId, $this->nodeTypeManager, $this->tableNamePrefix, $workspaceName, $contentStreamId); + return new ContentHyperGraph($this->dbal, $this->nodeFactory, $this->contentRepositoryId, $this->nodeTypeManager, $this->tableNamePrefix, $workspaceName, $contentStreamId); } } diff --git a/Neos.ContentRepository.Core/Classes/CommandHandlingDependencies.php b/Neos.ContentRepository.Core/Classes/CommandHandlingDependencies.php index c0b5270cc37..b138e9fd052 100644 --- a/Neos.ContentRepository.Core/Classes/CommandHandlingDependencies.php +++ b/Neos.ContentRepository.Core/Classes/CommandHandlingDependencies.php @@ -41,9 +41,9 @@ public function __construct(private readonly ContentRepository $contentRepositor { } - public function handle(CommandInterface $command): CommandResult + public function handle(CommandInterface $command): void { - return $this->contentRepository->handle($command); + $this->contentRepository->handle($command); } public function getWorkspaceFinder(): WorkspaceFinder diff --git a/Neos.ContentRepositoryRegistry/Classes/Command/ContentGraphIntegrityCommandController.php b/Neos.ContentRepositoryRegistry/Classes/Command/ContentGraphIntegrityCommandController.php index 71683ca6422..fc083b8d34b 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Command/ContentGraphIntegrityCommandController.php +++ b/Neos.ContentRepositoryRegistry/Classes/Command/ContentGraphIntegrityCommandController.php @@ -11,8 +11,8 @@ * source code. */ +use Doctrine\DBAL\Connection; use Neos\ContentGraph\DoctrineDbalAdapter\DoctrineDbalProjectionIntegrityViolationDetectionRunnerFactory; -use Neos\ContentRepository\Core\Infrastructure\DbalClientInterface; use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId; use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry; use Neos\Error\Messages\Result; @@ -25,7 +25,7 @@ final class ContentGraphIntegrityCommandController extends CommandController private const OUTPUT_MODE_LOG = 'log'; #[Flow\Inject()] - protected DbalClientInterface $dbalClient; + protected Connection $connection; #[Flow\Inject()] protected ContentRepositoryRegistry $contentRepositoryRegistry; @@ -34,7 +34,7 @@ public function runViolationDetectionCommand(string $contentRepository = 'defaul { $detectionRunner = $this->contentRepositoryRegistry->buildService( ContentRepositoryId::fromString($contentRepository), - new DoctrineDbalProjectionIntegrityViolationDetectionRunnerFactory($this->dbalClient) + new DoctrineDbalProjectionIntegrityViolationDetectionRunnerFactory($this->connection) ); $outputMode = $this->resolveOutputMode($outputMode); diff --git a/phpstan.neon.dist b/phpstan.neon.dist index c157d6569f9..9d89d3089f2 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -9,6 +9,7 @@ parameters: - Neos.ContentGraph.PostgreSQLAdapter/src - Neos.ContentRepository.BehavioralTests/Classes - Neos.ContentRepository.Core/Classes + - Neos.ContentRepository.DbalTools - Neos.ContentRepository.Export/src - Neos.ContentRepository.LegacyNodeMigration/Classes - Neos.ContentRepository.NodeAccess/Classes @@ -16,6 +17,9 @@ parameters: - Neos.ContentRepository.StructureAdjustment/src - Neos.ContentRepository.TestSuite/Classes - Neos.ContentRepositoryRegistry/Classes + - Neos.ContentRepositoryRegistry.DoctrineDbalClient + - Neos.ContentRepositoryRegistry.PostgresDbalClient + - Neos.ContentRepositoryRegistry.TestSuite - Neos.Neos/Classes - Neos.TimeableNodeVisibility/Classes - Neos.NodeTypes.Form/Classes From 3abc8f04c622a1ef5bd1e26d8aea35294c0fdb13 Mon Sep 17 00:00:00 2001 From: Bastian Waidelich Date: Sun, 19 May 2024 18:49:34 +0200 Subject: [PATCH 21/21] Make ContentGraphTableNames::tableNamePrefix private again --- .../src/ContentGraphTableNames.php | 2 +- .../src/DoctrineDbalContentGraphProjection.php | 6 +++--- .../DoctrineDbalContentGraphSchemaBuilder.php | 2 +- .../Domain/Projection/HypergraphProjection.php | 6 +++--- .../ContentStream/ContentStreamProjection.php | 10 +++++----- .../Workspace/WorkspaceProjection.php | 8 ++++---- .../Classes/CheckpointHelper.php | 18 ++++++++---------- .../Projection/AssetUsageProjection.php | 9 ++++----- .../Projection/DocumentUriPathProjection.php | 7 +++---- .../DocumentUriPathSchemaBuilder.php | 2 +- .../ChangeProjection.php | 9 ++++----- 11 files changed, 37 insertions(+), 42 deletions(-) diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/ContentGraphTableNames.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/ContentGraphTableNames.php index 438a4ec0e19..0804d77e7e0 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/ContentGraphTableNames.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/ContentGraphTableNames.php @@ -11,7 +11,7 @@ final readonly class ContentGraphTableNames { private function __construct( - public string $tableNamePrefix + private string $tableNamePrefix ) { } diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php index 51a0b2bfa09..44af777c6cc 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php @@ -135,7 +135,7 @@ public function reset(): void $this->dbal->executeQuery('TRUNCATE table ' . $this->tableNames->hierarchyRelation()); $this->dbal->executeQuery('TRUNCATE table ' . $this->tableNames->referenceRelation()); $this->dbal->executeQuery('TRUNCATE table ' . $this->tableNames->dimensionSpacePoints()); - CheckpointHelper::resetCheckpoint($this->dbal, $this->tableNames->tableNamePrefix); + CheckpointHelper::resetCheckpoint($this->dbal, $this->tableNames->checkpoint()); $this->getState()->forgetInstances(); } @@ -163,13 +163,13 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void SubtreeWasUntagged::class => $this->whenSubtreeWasUntagged($event), default => null, }; - CheckpointHelper::updateCheckpoint($this->dbal, $this->tableNames->tableNamePrefix, $eventEnvelope->sequenceNumber); + CheckpointHelper::updateCheckpoint($this->dbal, $this->tableNames->checkpoint(), $eventEnvelope->sequenceNumber); $this->dbal->commit(); } public function getCheckpoint(): SequenceNumber { - return CheckpointHelper::getCheckpoint($this->dbal, $this->tableNames->tableNamePrefix); + return CheckpointHelper::getCheckpoint($this->dbal, $this->tableNames->checkpoint()); } public function getState(): ContentGraphFinder diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphSchemaBuilder.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphSchemaBuilder.php index 7c4c92d3fa5..02dab89a18f 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphSchemaBuilder.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphSchemaBuilder.php @@ -30,7 +30,7 @@ public function buildSchema(AbstractSchemaManager $schemaManager): Schema $this->createHierarchyRelationTable(), $this->createReferenceRelationTable(), $this->createDimensionSpacePointsTable(), - CheckpointHelper::checkpointTableSchema($this->contentGraphTableNames->tableNamePrefix), + CheckpointHelper::checkpointTableSchema($this->contentGraphTableNames->checkpoint()), ]); } diff --git a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/HypergraphProjection.php b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/HypergraphProjection.php index 94fe0e5ab4c..f8bd9ee49f8 100644 --- a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/HypergraphProjection.php +++ b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/HypergraphProjection.php @@ -135,7 +135,7 @@ public function reset(): void { $this->truncateDatabaseTables(); - CheckpointHelper::resetCheckpoint($this->dbal, $this->tableNamePrefix); + CheckpointHelper::resetCheckpoint($this->dbal, $this->tableNamePrefix . '_checkpoint'); } private function truncateDatabaseTables(): void @@ -174,13 +174,13 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void NodePeerVariantWasCreated::class => $this->whenNodePeerVariantWasCreated($event), default => null, }; - CheckpointHelper::updateCheckpoint($this->dbal, $this->tableNamePrefix, $eventEnvelope->sequenceNumber); + CheckpointHelper::updateCheckpoint($this->dbal, $this->tableNamePrefix . '_checkpoint', $eventEnvelope->sequenceNumber); $this->dbal->commit(); } public function getCheckpoint(): SequenceNumber { - return CheckpointHelper::getCheckpoint($this->dbal, $this->tableNamePrefix); + return CheckpointHelper::getCheckpoint($this->dbal, $this->tableNamePrefix . '_checkpoint'); } public function getState(): ContentGraphFinder diff --git a/Neos.ContentRepository.Core/Classes/Projection/ContentStream/ContentStreamProjection.php b/Neos.ContentRepository.Core/Classes/Projection/ContentStream/ContentStreamProjection.php index 84db0fad8c8..2008a93c37a 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/ContentStream/ContentStreamProjection.php +++ b/Neos.ContentRepository.Core/Classes/Projection/ContentStream/ContentStreamProjection.php @@ -123,7 +123,7 @@ private function determineRequiredSqlStatements(): array (new Column('state', Type::getType(Types::BINARY)))->setLength(20)->setNotnull(true), (new Column('removed', Type::getType(Types::BOOLEAN)))->setDefault(false)->setNotnull(false) ])), - CheckpointHelper::checkpointTableSchema($this->tableName) + CheckpointHelper::checkpointTableSchema($this->tableName . '_checkpoint') ]); return DbalSchemaDiff::determineRequiredSqlStatements($this->dbal, $schema); @@ -132,7 +132,7 @@ private function determineRequiredSqlStatements(): array public function reset(): void { $this->dbal->executeStatement('TRUNCATE table ' . $this->tableName); - CheckpointHelper::resetCheckpoint($this->dbal, $this->tableName); + CheckpointHelper::resetCheckpoint($this->dbal, $this->tableName . '_checkpoint'); } public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void @@ -140,7 +140,7 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void $this->dbal->beginTransaction(); if ($event instanceof EmbedsContentStreamAndNodeAggregateId) { $this->updateContentStreamVersion($event, $eventEnvelope); - CheckpointHelper::updateCheckpoint($this->dbal, $this->tableName, $eventEnvelope->sequenceNumber); + CheckpointHelper::updateCheckpoint($this->dbal, $this->tableName . '_checkpoint', $eventEnvelope->sequenceNumber); $this->dbal->commit(); return; } @@ -161,13 +161,13 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void DimensionShineThroughWasAdded::class => $this->whenDimensionShineThroughWasAdded($event, $eventEnvelope), default => null, }; - CheckpointHelper::updateCheckpoint($this->dbal, $this->tableName, $eventEnvelope->sequenceNumber); + CheckpointHelper::updateCheckpoint($this->dbal, $this->tableName . '_checkpoint', $eventEnvelope->sequenceNumber); $this->dbal->commit(); } public function getCheckpoint(): SequenceNumber { - return CheckpointHelper::getCheckpoint($this->dbal, $this->tableName); + return CheckpointHelper::getCheckpoint($this->dbal, $this->tableName . '_checkpoint'); } public function getState(): ProjectionStateInterface diff --git a/Neos.ContentRepository.Core/Classes/Projection/Workspace/WorkspaceProjection.php b/Neos.ContentRepository.Core/Classes/Projection/Workspace/WorkspaceProjection.php index 0a5f778c7a8..88adf22b60b 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/Workspace/WorkspaceProjection.php +++ b/Neos.ContentRepository.Core/Classes/Projection/Workspace/WorkspaceProjection.php @@ -116,7 +116,7 @@ private function determineRequiredSqlStatements(): array (new Column('status', Type::getType(Types::BINARY)))->setLength(20)->setNotnull(false) ]); $workspaceTable->setPrimaryKey(['workspacename']); - $checkpointTable = CheckpointHelper::checkpointTableSchema($this->tableName); + $checkpointTable = CheckpointHelper::checkpointTableSchema($this->tableName . '_checkpoint'); $schema = DbalSchemaFactory::createSchemaWithTables($schemaManager, [$workspaceTable, $checkpointTable]); return DbalSchemaDiff::determineRequiredSqlStatements($this->dbal, $schema); @@ -125,7 +125,7 @@ private function determineRequiredSqlStatements(): array public function reset(): void { $this->dbal->exec('TRUNCATE ' . $this->tableName); - CheckpointHelper::resetCheckpoint($this->dbal, $this->tableName); + CheckpointHelper::resetCheckpoint($this->dbal, $this->tableName . '_checkpoint'); } public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void @@ -146,13 +146,13 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void WorkspaceBaseWorkspaceWasChanged::class => $this->whenWorkspaceBaseWorkspaceWasChanged($event), default => null, }; - CheckpointHelper::updateCheckpoint($this->dbal, $this->tableName, $eventEnvelope->sequenceNumber); + CheckpointHelper::updateCheckpoint($this->dbal, $this->tableName . '_checkpoint', $eventEnvelope->sequenceNumber); $this->dbal->commit(); } public function getCheckpoint(): SequenceNumber { - return CheckpointHelper::getCheckpoint($this->dbal, $this->tableName); + return CheckpointHelper::getCheckpoint($this->dbal, $this->tableName . '_checkpoint'); } public function getState(): WorkspaceFinder diff --git a/Neos.ContentRepository.DbalTools/Classes/CheckpointHelper.php b/Neos.ContentRepository.DbalTools/Classes/CheckpointHelper.php index 3b57a43e0f7..4f492ea2289 100644 --- a/Neos.ContentRepository.DbalTools/Classes/CheckpointHelper.php +++ b/Neos.ContentRepository.DbalTools/Classes/CheckpointHelper.php @@ -23,35 +23,33 @@ */ final class CheckpointHelper { - private const CHECKPOINT_TABLE_NAME_SUFFIX = '_checkpoint'; - // This class only contains static members and should not be constructed private function __construct() { } - public static function checkpointTableSchema(string $tableNamePrefix): Table + public static function checkpointTableSchema(string $tableName): Table { - return (new Table($tableNamePrefix . self::CHECKPOINT_TABLE_NAME_SUFFIX, [ + return (new Table($tableName, [ (new Column('id', Type::getType(Types::INTEGER)))->setPlatformOption('check', 'CHECK (id = 0)'), (new Column('appliedsequencenumber', Type::getType(Types::INTEGER))), ])) ->setPrimaryKey(['id']); } - public static function resetCheckpoint(Connection $connection, string $tableNamePrefix): void + public static function resetCheckpoint(Connection $connection, string $tableName): void { - $connection->executeStatement('INSERT INTO ' . $connection->quoteIdentifier($tableNamePrefix . self::CHECKPOINT_TABLE_NAME_SUFFIX) . ' (id, appliedsequencenumber) VALUES (0, 0) ON DUPLICATE KEY UPDATE appliedsequencenumber = 0'); + $connection->executeStatement('INSERT INTO ' . $connection->quoteIdentifier($tableName) . ' (id, appliedsequencenumber) VALUES (0, 0) ON DUPLICATE KEY UPDATE appliedsequencenumber = 0'); } - public static function updateCheckpoint(Connection $connection, string $tableNamePrefix, SequenceNumber $sequenceNumber): void + public static function updateCheckpoint(Connection $connection, string $tableName, SequenceNumber $sequenceNumber): void { - $connection->executeStatement('UPDATE ' . $connection->quoteIdentifier($tableNamePrefix . self::CHECKPOINT_TABLE_NAME_SUFFIX) . ' SET appliedsequencenumber = :sequenceNumber WHERE id = 0', ['sequenceNumber' => $sequenceNumber->value]); + $connection->executeStatement('UPDATE ' . $connection->quoteIdentifier($tableName) . ' SET appliedsequencenumber = :sequenceNumber WHERE id = 0', ['sequenceNumber' => $sequenceNumber->value]); } - public static function getCheckpoint(Connection $connection, string $tableNamePrefix): SequenceNumber + public static function getCheckpoint(Connection $connection, string $tableName): SequenceNumber { - $highestAppliedSequenceNumber = $connection->fetchOne('SELECT appliedsequencenumber FROM ' . $connection->quoteIdentifier($tableNamePrefix . self::CHECKPOINT_TABLE_NAME_SUFFIX) . ' LIMIT 1 '); + $highestAppliedSequenceNumber = $connection->fetchOne('SELECT appliedsequencenumber FROM ' . $connection->quoteIdentifier($tableName) . ' LIMIT 1 '); if (!is_numeric($highestAppliedSequenceNumber)) { throw new \RuntimeException('Failed to fetch highest applied sequence number', 1712942681); } diff --git a/Neos.Neos/Classes/AssetUsage/Projection/AssetUsageProjection.php b/Neos.Neos/Classes/AssetUsage/Projection/AssetUsageProjection.php index b5f5e0e3fc1..59c075cf595 100644 --- a/Neos.Neos/Classes/AssetUsage/Projection/AssetUsageProjection.php +++ b/Neos.Neos/Classes/AssetUsage/Projection/AssetUsageProjection.php @@ -61,7 +61,7 @@ public function __construct( public function reset(): void { $this->repository->reset(); - CheckpointHelper::resetCheckpoint($this->dbal, $this->repository->getTableNamePrefix()); + CheckpointHelper::resetCheckpoint($this->dbal, $this->repository->getTableNamePrefix() . '_checkpoint'); } public function whenNodeAggregateWithNodeWasCreated(NodeAggregateWithNodeWasCreated $event, EventEnvelope $eventEnvelope): void @@ -228,7 +228,6 @@ public function setUp(): void foreach ($this->determineRequiredSqlStatements() as $statement) { $this->dbal->executeStatement($statement); } - CheckpointHelper::resetCheckpoint($this->dbal, $this->repository->getTableNamePrefix()); } public function status(): ProjectionStatus @@ -274,13 +273,13 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void ContentStreamWasRemoved::class => $this->whenContentStreamWasRemoved($event), default => null, }; - CheckpointHelper::updateCheckpoint($this->dbal, $this->repository->getTableNamePrefix(), $eventEnvelope->sequenceNumber); + CheckpointHelper::updateCheckpoint($this->dbal, $this->repository->getTableNamePrefix() . '_checkpoint', $eventEnvelope->sequenceNumber); $this->dbal->commit(); } public function getCheckpoint(): SequenceNumber { - return CheckpointHelper::getCheckpoint($this->dbal, $this->repository->getTableNamePrefix()); + return CheckpointHelper::getCheckpoint($this->dbal, $this->repository->getTableNamePrefix() . '_checkpoint'); } public function getState(): AssetUsageFinder @@ -300,7 +299,7 @@ private function determineRequiredSqlStatements(): array if (!$schemaManager instanceof AbstractSchemaManager) { throw new \RuntimeException('Failed to retrieve Schema Manager', 1625653914); } - $checkpointTable = CheckpointHelper::checkpointTableSchema($this->repository->getTableNamePrefix()); + $checkpointTable = CheckpointHelper::checkpointTableSchema($this->repository->getTableNamePrefix() . '_checkpoint'); $schema = DbalSchemaFactory::createSchemaWithTables($schemaManager, [$checkpointTable]); return DbalSchemaDiff::determineRequiredSqlStatements($this->dbal, $schema); diff --git a/Neos.Neos/Classes/FrontendRouting/Projection/DocumentUriPathProjection.php b/Neos.Neos/Classes/FrontendRouting/Projection/DocumentUriPathProjection.php index 917fa57f642..2177ce11f6c 100644 --- a/Neos.Neos/Classes/FrontendRouting/Projection/DocumentUriPathProjection.php +++ b/Neos.Neos/Classes/FrontendRouting/Projection/DocumentUriPathProjection.php @@ -68,7 +68,6 @@ public function setUp(): void foreach ($this->determineRequiredSqlStatements() as $statement) { $this->dbal->executeStatement($statement); } - CheckpointHelper::resetCheckpoint($this->dbal, $this->tableNamePrefix); } public function status(): ProjectionStatus @@ -111,7 +110,7 @@ private function determineRequiredSqlStatements(): array public function reset(): void { $this->truncateDatabaseTables(); - CheckpointHelper::resetCheckpoint($this->dbal, $this->tableNamePrefix); + CheckpointHelper::resetCheckpoint($this->dbal, $this->tableNamePrefix . '_checkpoint'); $this->stateAccessor = null; } @@ -146,13 +145,13 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void DimensionShineThroughWasAdded::class => $this->whenDimensionShineThroughWasAdded($event), default => null, }; - CheckpointHelper::updateCheckpoint($this->dbal, $this->tableNamePrefix, $eventEnvelope->sequenceNumber); + CheckpointHelper::updateCheckpoint($this->dbal, $this->tableNamePrefix . '_checkpoint', $eventEnvelope->sequenceNumber); $this->dbal->commit(); } public function getCheckpoint(): SequenceNumber { - return CheckpointHelper::getCheckpoint($this->dbal, $this->tableNamePrefix); + return CheckpointHelper::getCheckpoint($this->dbal, $this->tableNamePrefix . '_checkpoint'); } public function getState(): DocumentUriPathFinder diff --git a/Neos.Neos/Classes/FrontendRouting/Projection/DocumentUriPathSchemaBuilder.php b/Neos.Neos/Classes/FrontendRouting/Projection/DocumentUriPathSchemaBuilder.php index eb59fa3d085..187c239c835 100644 --- a/Neos.Neos/Classes/FrontendRouting/Projection/DocumentUriPathSchemaBuilder.php +++ b/Neos.Neos/Classes/FrontendRouting/Projection/DocumentUriPathSchemaBuilder.php @@ -25,7 +25,7 @@ public function buildSchema(AbstractSchemaManager $schemaManager): Schema $schema = DbalSchemaFactory::createSchemaWithTables($schemaManager, [ $this->createUriTable(), $this->createLiveContentStreamsTable(), - CheckpointHelper::checkpointTableSchema($this->tableNamePrefix), + CheckpointHelper::checkpointTableSchema($this->tableNamePrefix . '_checkpoint'), ]); return $schema; diff --git a/Neos.Neos/Classes/PendingChangesProjection/ChangeProjection.php b/Neos.Neos/Classes/PendingChangesProjection/ChangeProjection.php index 6560949bd20..ea2afa54f36 100644 --- a/Neos.Neos/Classes/PendingChangesProjection/ChangeProjection.php +++ b/Neos.Neos/Classes/PendingChangesProjection/ChangeProjection.php @@ -78,7 +78,6 @@ public function setUp(): void foreach ($this->determineRequiredSqlStatements() as $statement) { $this->dbal->executeStatement($statement); } - CheckpointHelper::resetCheckpoint($this->dbal, $this->tableNamePrefix); } public function status(): ProjectionStatus @@ -139,7 +138,7 @@ private function determineRequiredSqlStatements(): array ]); $liveContentStreamsTable->setPrimaryKey(['contentstreamid']); - $checkpointTable = CheckpointHelper::checkpointTableSchema($this->tableNamePrefix); + $checkpointTable = CheckpointHelper::checkpointTableSchema($this->tableNamePrefix . '_checkpoint'); $schema = DbalSchemaFactory::createSchemaWithTables($schemaManager, [$changeTable, $liveContentStreamsTable, $checkpointTable]); return DbalSchemaDiff::determineRequiredSqlStatements($this->dbal, $schema); @@ -149,7 +148,7 @@ public function reset(): void { $this->dbal->exec('TRUNCATE ' . $this->tableNamePrefix); $this->dbal->exec('TRUNCATE ' . $this->tableNamePrefix . '_livecontentstreams'); - CheckpointHelper::resetCheckpoint($this->dbal, $this->tableNamePrefix); + CheckpointHelper::resetCheckpoint($this->dbal, $this->tableNamePrefix . '_checkpoint'); } public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void @@ -170,13 +169,13 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void NodePeerVariantWasCreated::class => $this->whenNodePeerVariantWasCreated($event), default => null, }; - CheckpointHelper::updateCheckpoint($this->dbal, $this->tableNamePrefix, $eventEnvelope->sequenceNumber); + CheckpointHelper::updateCheckpoint($this->dbal, $this->tableNamePrefix . '_checkpoint', $eventEnvelope->sequenceNumber); $this->dbal->commit(); } public function getCheckpoint(): SequenceNumber { - return CheckpointHelper::getCheckpoint($this->dbal, $this->tableNamePrefix); + return CheckpointHelper::getCheckpoint($this->dbal, $this->tableNamePrefix . '_checkpoint'); } public function getState(): ChangeFinder