Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FEATURE: ContentGraphAdapter for write side access #4979

Closed
wants to merge 20 commits into from
Closed
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
554 changes: 554 additions & 0 deletions Neos.ContentGraph.DoctrineDbalAdapter/src/ContentGraphAdapter.php
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should refine this naming

Large diffs are not rendered by default.

@@ -0,0 +1,65 @@
<?php

namespace Neos\ContentGraph\DoctrineDbalAdapter;

use Doctrine\DBAL\Connection;
use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\DimensionSpacePointsRepository;
use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\NodeFactory;
use Neos\ContentRepository\Core\Factory\ProjectionFactoryDependencies;
use Neos\ContentRepository\Core\Feature\ContentGraphAdapterFactoryInterface;
use Neos\ContentRepository\Core\Feature\ContentGraphAdapterInterface;
use Neos\ContentRepository\Core\NodeType\NodeTypeManager;
use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId;
use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId;
use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName;

/**
* Factory for the ContentGraphAdapter implementation for doctrine DBAL
*
* @internal
*/
class ContentGraphAdapterFactory implements ContentGraphAdapterFactoryInterface
{
private NodeFactory $nodeFactory;

private NodeTypeManager $nodeTypeManager;

private string $tableNamePrefix;

private ContentRepositoryId $contentRepositoryId;

public function __construct(
private readonly Connection $dbalConnection,
ProjectionFactoryDependencies $projectionFactoryDependencies
) {
$tableNamePrefix = DoctrineDbalContentGraphProjectionFactory::graphProjectionTableNamePrefix(
$projectionFactoryDependencies->contentRepositoryId
);
$this->tableNamePrefix = $tableNamePrefix;
$this->contentRepositoryId = $projectionFactoryDependencies->contentRepositoryId;

$dimensionSpacePointsRepository = new DimensionSpacePointsRepository($this->dbalConnection, $tableNamePrefix);
$this->nodeTypeManager = $projectionFactoryDependencies->nodeTypeManager;
$this->nodeFactory = new NodeFactory(
$projectionFactoryDependencies->contentRepositoryId,
$projectionFactoryDependencies->nodeTypeManager,
$projectionFactoryDependencies->propertyConverter,
$dimensionSpacePointsRepository
);
}

public function create(WorkspaceName $workspaceName, ContentStreamId $contentStreamId): ContentGraphAdapterInterface
{
return new ContentGraphAdapter($this->dbalConnection, $this->tableNamePrefix, $this->contentRepositoryId, $this->nodeFactory, $this->nodeTypeManager, $workspaceName, $contentStreamId);
}

public function createFromContentStreamId(ContentStreamId $contentStreamId): ContentGraphAdapterInterface
{
return new ContentGraphAdapter($this->dbalConnection, $this->tableNamePrefix, $this->contentRepositoryId, $this->nodeFactory, $this->nodeTypeManager, null, $contentStreamId);
}

public function createFromWorkspaceName(WorkspaceName $workspaceName): ContentGraphAdapterInterface
{
return new ContentGraphAdapter($this->dbalConnection, $this->tableNamePrefix, $this->contentRepositoryId, $this->nodeFactory, $this->nodeTypeManager, $workspaceName, null);
}
}
@@ -0,0 +1,23 @@
<?php

namespace Neos\ContentGraph\DoctrineDbalAdapter;

use Neos\ContentRepository\Core\Factory\ProjectionFactoryDependencies;
use Neos\ContentRepository\Core\Feature\ContentGraphAdapterFactoryBuilderInterface;
use Neos\ContentRepository\Core\Infrastructure\DbalClientInterface;

/**
* Builder to combine injected dependencies and ProjectionFActoryDependencies into a ContentGraphAdapterFactory
* @internal
*/
class ContentGraphAdapterFactoryBuilder implements ContentGraphAdapterFactoryBuilderInterface
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't mind getting around having this, and am happy for suggestions, I don't really see it though. An ugly option would be to to have something along the lines of:

ContentGraphAdapterFactory::injectProjectionDependencies(ProjectionFactoryDependencies $projectionFactoryDependencies)

and the ContentGraphAdapterFactory::__construct just gets the adapter dependencies injected (eg. DBALClient), but then all methods in the ContentGraphAdapterFactory need to throw a "TooEarly" Exception if the projection dependencies were not injected yet.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIS we only need it to pass in ContentRepositoryId, NodeTypeManager and PropertyConverter – Maybe we can make these explicit dependencies somehow

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

..or even make the NodeFactory an explicit dependency (via some NodeFactoryInterface) but I don't know... Let's discuss

{
public function __construct(private readonly DbalClientInterface $dbalClient)
{
}

public function build(ProjectionFactoryDependencies $projectionFactoryDependencies): ContentGraphAdapterFactory
{
return new ContentGraphAdapterFactory($this->dbalClient->getConnection(), $projectionFactoryDependencies);
}
}

Large diffs are not rendered by default.

Large diffs are not rendered by default.

319 changes: 319 additions & 0 deletions Neos.ContentGraph.DoctrineDbalAdapter/src/NodeQueryBuilder.php

Large diffs are not rendered by default.

Expand Up @@ -10,3 +10,5 @@ Neos:
factoryObjectName: 'Neos\ContentRepository\BehavioralTests\TestSuite\Behavior\GherkinPyStringNodeBasedNodeTypeManagerFactory'
contentDimensionSource:
factoryObjectName: 'Neos\ContentRepository\BehavioralTests\TestSuite\Behavior\GherkinTableNodeBasedContentDimensionSourceFactory'
contentGraphAdapterFactory:
factoryObjectName: Neos\ContentGraph\DoctrineDbalAdapter\ContentGraphAdapterFactoryBuilder
Expand Up @@ -77,7 +77,7 @@ Feature: Constraint checks on SetNodeReferences
| sourceNodeAggregateId | "source-nodandaise" |
| referenceName | "referenceProperty" |
| references | [{"target":"anthony-destinode"}] |
Then the last command should have thrown an exception of type "ContentStreamDoesNotExistYet" with code 1710407870
Then the last command should have thrown an exception of type "ContentStreamDoesNotExistYet" with code 1521386692

# checks for sourceNodeAggregateId
Scenario: Try to reference nodes in a non-existent node aggregate
Expand Down
1 change: 1 addition & 0 deletions Neos.ContentRepository.Core/Classes/ContentRepository.php
Expand Up @@ -29,6 +29,7 @@
use Neos\ContentRepository\Core\NodeType\NodeTypeManager;
use Neos\ContentRepository\Core\Projection\CatchUp;
use Neos\ContentRepository\Core\Projection\CatchUpOptions;
use Neos\ContentRepository\Core\Feature\ContentGraphAdapterInterface;
use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphInterface;
use Neos\ContentRepository\Core\Projection\ContentStream\ContentStreamFinder;
use Neos\ContentRepository\Core\Projection\ProjectionInterface;
Expand Down
Expand Up @@ -21,6 +21,8 @@
use Neos\ContentRepository\Core\DimensionSpace\InterDimensionalVariationGraph;
use Neos\ContentRepository\Core\EventStore\EventNormalizer;
use Neos\ContentRepository\Core\EventStore\EventPersister;
use Neos\ContentRepository\Core\Feature\ContentGraphAdapterFactoryBuilderInterface;
use Neos\ContentRepository\Core\Feature\ContentGraphAdapterProvider;
use Neos\ContentRepository\Core\Feature\ContentStreamCommandHandler;
use Neos\ContentRepository\Core\Feature\DimensionSpaceAdjustment\DimensionSpaceCommandHandler;
use Neos\ContentRepository\Core\Feature\NodeAggregateCommandHandler;
Expand All @@ -46,6 +48,8 @@ final class ContentRepositoryFactory
private ProjectionFactoryDependencies $projectionFactoryDependencies;
private ProjectionsAndCatchUpHooks $projectionsAndCatchUpHooks;

private ContentGraphAdapterProvider $contentGraphAdapterProvider;

public function __construct(
private readonly ContentRepositoryId $contentRepositoryId,
EventStoreInterface $eventStore,
Expand All @@ -56,6 +60,7 @@ public function __construct(
private readonly ProjectionCatchUpTriggerInterface $projectionCatchUpTrigger,
private readonly UserIdProviderInterface $userIdProvider,
private readonly ClockInterface $clock,
ContentGraphAdapterFactoryBuilderInterface $contentGraphAdapterFactoryBuilder,
) {
$contentDimensionZookeeper = new ContentDimensionZookeeper($contentDimensionSource);
$interDimensionalVariationGraph = new InterDimensionalVariationGraph(
Expand All @@ -73,6 +78,8 @@ public function __construct(
new PropertyConverter($propertySerializer)
);
$this->projectionsAndCatchUpHooks = $projectionsAndCatchUpHooksFactory->build($this->projectionFactoryDependencies);

$this->contentGraphAdapterProvider = new ContentGraphAdapterProvider($contentGraphAdapterFactoryBuilder->build($this->projectionFactoryDependencies));
}

// The following properties store "singleton" references of objects for this content repository
Expand Down Expand Up @@ -120,11 +127,13 @@ public function getOrBuild(): ContentRepository
public function buildService(
ContentRepositoryServiceFactoryInterface $serviceFactory
): ContentRepositoryServiceInterface {

$serviceFactoryDependencies = ContentRepositoryServiceFactoryDependencies::create(
$this->projectionFactoryDependencies,
$this->getOrBuild(),
$this->buildEventPersister(),
$this->projectionsAndCatchUpHooks->projections,
$this->contentGraphAdapterProvider
);
return $serviceFactory->build($serviceFactoryDependencies);
}
Expand All @@ -134,26 +143,31 @@ private function buildCommandBus(): CommandBus
if (!$this->commandBus) {
$this->commandBus = new CommandBus(
new ContentStreamCommandHandler(
$this->contentGraphAdapterProvider
),
new WorkspaceCommandHandler(
$this->buildEventPersister(),
$this->projectionFactoryDependencies->eventStore,
$this->projectionFactoryDependencies->eventNormalizer,
$this->contentGraphAdapterProvider
),
new NodeAggregateCommandHandler(
$this->projectionFactoryDependencies->nodeTypeManager,
$this->projectionFactoryDependencies->contentDimensionZookeeper,
$this->projectionFactoryDependencies->interDimensionalVariationGraph,
$this->projectionFactoryDependencies->propertyConverter
$this->projectionFactoryDependencies->propertyConverter,
$this->contentGraphAdapterProvider
),
new DimensionSpaceCommandHandler(
$this->projectionFactoryDependencies->contentDimensionZookeeper,
$this->projectionFactoryDependencies->interDimensionalVariationGraph
$this->projectionFactoryDependencies->interDimensionalVariationGraph,
$this->contentGraphAdapterProvider
),
new NodeDuplicationCommandHandler(
$this->projectionFactoryDependencies->nodeTypeManager,
$this->projectionFactoryDependencies->contentDimensionZookeeper,
$this->projectionFactoryDependencies->interDimensionalVariationGraph
$this->projectionFactoryDependencies->interDimensionalVariationGraph,
$this->contentGraphAdapterProvider
)
);
}
Expand Down
Expand Up @@ -20,6 +20,7 @@
use Neos\ContentRepository\Core\DimensionSpace\InterDimensionalVariationGraph;
use Neos\ContentRepository\Core\EventStore\EventNormalizer;
use Neos\ContentRepository\Core\EventStore\EventPersister;
use Neos\ContentRepository\Core\Feature\ContentGraphAdapterProvider;
use Neos\ContentRepository\Core\Infrastructure\Property\PropertyConverter;
use Neos\ContentRepository\Core\NodeType\NodeTypeManager;
use Neos\ContentRepository\Core\Projection\Projections;
Expand Down Expand Up @@ -47,6 +48,7 @@ private function __construct(
// we don't need CommandBus, because this is included in ContentRepository->handle()
public EventPersister $eventPersister,
public Projections $projections,
public ContentGraphAdapterProvider $contentGraphAdapterProvider
) {
}

Expand All @@ -58,6 +60,7 @@ public static function create(
ContentRepository $contentRepository,
EventPersister $eventPersister,
Projections $projections,
ContentGraphAdapterProvider $contentGraphAdapterProvider
): self {
return new self(
$projectionFactoryDependencies->contentRepositoryId,
Expand All @@ -71,6 +74,7 @@ public static function create(
$contentRepository,
$eventPersister,
$projections,
$contentGraphAdapterProvider
);
}
}