Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/9.0' into bugfix/fail-early-if-s…
Browse files Browse the repository at this point in the history
…et-properties-is-empty
  • Loading branch information
mhsdesign committed Jan 9, 2025
2 parents 455e12f + f20b28c commit b6a5f8d
Show file tree
Hide file tree
Showing 230 changed files with 8,210 additions and 3,052 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,4 @@ public function contentStream(): string
{
return $this->tableNamePrefix . '_contentstream';
}

public function checkpoint(): string
{
return $this->tableNamePrefix . '_checkpoint';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,11 @@
use Neos\ContentRepository\Core\Feature\WorkspaceModification\Event\WorkspaceBaseWorkspaceWasChanged;
use Neos\ContentRepository\Core\Feature\WorkspaceModification\Event\WorkspaceWasRemoved;
use Neos\ContentRepository\Core\Feature\WorkspacePublication\Event\WorkspaceWasDiscarded;
use Neos\ContentRepository\Core\Feature\WorkspacePublication\Event\WorkspaceWasPartiallyDiscarded;
use Neos\ContentRepository\Core\Feature\WorkspacePublication\Event\WorkspaceWasPartiallyPublished;
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\DbalSchemaDiff;
use Neos\ContentRepository\Core\NodeType\NodeTypeName;
use Neos\ContentRepository\Core\Projection\CheckpointStorageStatusType;
use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphProjectionInterface;
use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphReadModelInterface;
use Neos\ContentRepository\Core\Projection\ContentGraph\NodeTags;
Expand All @@ -75,7 +71,6 @@
use Neos\ContentRepository\Core\SharedModel\Node\NodeName;
use Neos\ContentRepository\Core\SharedModel\Node\ReferenceName;
use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId;
use Neos\EventStore\Model\Event\SequenceNumber;
use Neos\EventStore\Model\EventEnvelope;

/**
Expand All @@ -93,20 +88,13 @@ final class DoctrineDbalContentGraphProjection implements ContentGraphProjection

public const RELATION_DEFAULT_OFFSET = 128;

private DbalCheckpointStorage $checkpointStorage;

public function __construct(
private readonly Connection $dbal,
private readonly ProjectionContentGraph $projectionContentGraph,
private readonly ContentGraphTableNames $tableNames,
private readonly DimensionSpacePointsRepository $dimensionSpacePointsRepository,
private readonly ContentGraphReadModelInterface $contentGraphReadModel
) {
$this->checkpointStorage = new DbalCheckpointStorage(
$this->dbal,
$this->tableNames->checkpoint(),
self::class
);
}

public function setUp(): void
Expand All @@ -120,18 +108,10 @@ public function setUp(): void
throw new \RuntimeException(sprintf('Failed to setup projection %s: %s', self::class, $e->getMessage()), 1716478255, $e);
}
}
$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->dbal->connect();
} catch (\Throwable $e) {
Expand All @@ -149,61 +129,16 @@ public function status(): ProjectionStatus
return ProjectionStatus::ok();
}

public function reset(): void
public function resetState(): void
{
$this->truncateDatabaseTables();

$this->checkpointStorage->acquireLock();
$this->checkpointStorage->updateAndReleaseLock(SequenceNumber::none());
}

public function getCheckpointStorage(): DbalCheckpointStorage
{
return $this->checkpointStorage;
}

public function getState(): ContentGraphReadModelInterface
{
return $this->contentGraphReadModel;
}

public function canHandle(EventInterface $event): bool
{
return in_array($event::class, [
ContentStreamWasClosed::class,
ContentStreamWasCreated::class,
ContentStreamWasForked::class,
ContentStreamWasRemoved::class,
ContentStreamWasReopened::class,
DimensionShineThroughWasAdded::class,
DimensionSpacePointWasMoved::class,
NodeAggregateNameWasChanged::class,
NodeAggregateTypeWasChanged::class,
NodeAggregateWasMoved::class,
NodeAggregateWasRemoved::class,
NodeAggregateWithNodeWasCreated::class,
NodeGeneralizationVariantWasCreated::class,
NodePeerVariantWasCreated::class,
NodePropertiesWereSet::class,
NodeReferencesWereSet::class,
NodeSpecializationVariantWasCreated::class,
RootNodeAggregateDimensionsWereUpdated::class,
RootNodeAggregateWithNodeWasCreated::class,
RootWorkspaceWasCreated::class,
SubtreeWasTagged::class,
SubtreeWasUntagged::class,
WorkspaceBaseWorkspaceWasChanged::class,
WorkspaceRebaseFailed::class,
WorkspaceWasCreated::class,
WorkspaceWasDiscarded::class,
WorkspaceWasPartiallyDiscarded::class,
WorkspaceWasPartiallyPublished::class,
WorkspaceWasPublished::class,
WorkspaceWasRebased::class,
WorkspaceWasRemoved::class,
]) || $event instanceof EmbedsContentStreamId;
}

public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void
{
match ($event::class) {
Expand Down Expand Up @@ -233,12 +168,10 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void
WorkspaceRebaseFailed::class => $this->whenWorkspaceRebaseFailed($event),
WorkspaceWasCreated::class => $this->whenWorkspaceWasCreated($event),
WorkspaceWasDiscarded::class => $this->whenWorkspaceWasDiscarded($event),
WorkspaceWasPartiallyDiscarded::class => $this->whenWorkspaceWasPartiallyDiscarded($event),
WorkspaceWasPartiallyPublished::class => $this->whenWorkspaceWasPartiallyPublished($event),
WorkspaceWasPublished::class => $this->whenWorkspaceWasPublished($event),
WorkspaceWasRebased::class => $this->whenWorkspaceWasRebased($event),
WorkspaceWasRemoved::class => $this->whenWorkspaceWasRemoved($event),
default => $event instanceof EmbedsContentStreamId || throw new \InvalidArgumentException(sprintf('Unsupported event %s', get_debug_type($event))),
default => null,
};
if (
$event instanceof EmbedsContentStreamId
Expand Down Expand Up @@ -774,16 +707,6 @@ private function whenWorkspaceWasDiscarded(WorkspaceWasDiscarded $event): void
$this->updateWorkspaceContentStreamId($event->workspaceName, $event->newContentStreamId);
}

private function whenWorkspaceWasPartiallyDiscarded(WorkspaceWasPartiallyDiscarded $event): void
{
$this->updateWorkspaceContentStreamId($event->workspaceName, $event->newContentStreamId);
}

private function whenWorkspaceWasPartiallyPublished(WorkspaceWasPartiallyPublished $event): void
{
$this->updateWorkspaceContentStreamId($event->sourceWorkspaceName, $event->newSourceContentStreamId);
}

private function whenWorkspaceWasPublished(WorkspaceWasPublished $event): void
{
$this->updateWorkspaceContentStreamId($event->sourceWorkspaceName, $event->newSourceContentStreamId);
Expand All @@ -806,8 +729,7 @@ private function whenWorkspaceWasRemoved(WorkspaceWasRemoved $event): void
*/
private function determineRequiredSqlStatements(): array
{
$schemaManager = $this->dbal->createSchemaManager();
$schema = (new DoctrineDbalContentGraphSchemaBuilder($this->tableNames))->buildSchema($schemaManager);
$schema = (new DoctrineDbalContentGraphSchemaBuilder($this->tableNames))->buildSchema($this->dbal);
return DbalSchemaDiff::determineRequiredSqlStatements($this->dbal, $schema);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
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\Factory\SubscriberFactoryDependencies;
use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphProjectionFactoryInterface;

/**
Expand All @@ -24,8 +24,7 @@ public function __construct(
}

public function build(
ProjectionFactoryDependencies $projectionFactoryDependencies,
array $options,
SubscriberFactoryDependencies $projectionFactoryDependencies,
): DoctrineDbalContentGraphProjection {
$tableNames = ContentGraphTableNames::create(
$projectionFactoryDependencies->contentRepositoryId
Expand All @@ -35,7 +34,7 @@ public function build(

$nodeFactory = new NodeFactory(
$projectionFactoryDependencies->contentRepositoryId,
$projectionFactoryDependencies->propertyConverter,
$projectionFactoryDependencies->getPropertyConverter(),
$dimensionSpacePointsRepository
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Neos\ContentGraph\DoctrineDbalAdapter;

use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Exception as DBALException;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Schema\AbstractSchemaManager;
Expand All @@ -19,38 +20,32 @@
*/
class DoctrineDbalContentGraphSchemaBuilder
{
private const DEFAULT_TEXT_COLLATION = 'utf8mb4_unicode_520_ci';

public function __construct(
private readonly ContentGraphTableNames $tableNames
) {
}

/**
* @param AbstractSchemaManager<AbstractPlatform> $schemaManager
* @return Schema
*/
public function buildSchema(AbstractSchemaManager $schemaManager): Schema
public function buildSchema(Connection $connection): Schema
{
return DbalSchemaFactory::createSchemaWithTables($schemaManager, [
$this->createNodeTable(),
$this->createHierarchyRelationTable(),
$this->createReferenceRelationTable(),
$this->createDimensionSpacePointsTable(),
$this->createWorkspaceTable(),
$this->createContentStreamTable(),
return DbalSchemaFactory::createSchemaWithTables($connection, [
$this->createNodeTable($connection->getDatabasePlatform()),
$this->createHierarchyRelationTable($connection->getDatabasePlatform()),
$this->createReferenceRelationTable($connection->getDatabasePlatform()),
$this->createDimensionSpacePointsTable($connection->getDatabasePlatform()),
$this->createWorkspaceTable($connection->getDatabasePlatform()),
$this->createContentStreamTable($connection->getDatabasePlatform()),
]);
}

private function createNodeTable(): Table
private function createNodeTable(AbstractPlatform $platform): Table
{
$table = self::createTable($this->tableNames->node(), [
DbalSchemaFactory::columnForNodeAnchorPoint('relationanchorpoint')->setAutoincrement(true),
DbalSchemaFactory::columnForNodeAggregateId('nodeaggregateid')->setNotnull(false),
DbalSchemaFactory::columnForDimensionSpacePointHash('origindimensionspacepointhash')->setNotnull(false),
DbalSchemaFactory::columnForNodeTypeName('nodetypename'),
(new Column('name', self::type(Types::STRING)))->setLength(255)->setNotnull(false)->setPlatformOption('charset', 'ascii')->setPlatformOption('collation', 'ascii_general_ci'),
(new Column('properties', self::type(Types::TEXT)))->setNotnull(true)->setPlatformOption('collation', self::DEFAULT_TEXT_COLLATION),
DbalSchemaFactory::columnForNodeAnchorPoint('relationanchorpoint', $platform)->setAutoincrement(true),
DbalSchemaFactory::columnForNodeAggregateId('nodeaggregateid', $platform)->setNotnull(false),
DbalSchemaFactory::columnForDimensionSpacePointHash('origindimensionspacepointhash', $platform)->setNotnull(false),
DbalSchemaFactory::columnForNodeTypeName('nodetypename', $platform),
(new Column('name', self::type(Types::STRING)))->setLength(255)->setNotnull(false),
DbalSchemaFactory::columnForProperties('properties', $platform)->setNotnull(true),
(new Column('classification', self::type(Types::BINARY)))->setLength(20)->setNotnull(true),
(new Column('created', self::type(Types::DATETIME_IMMUTABLE)))->setDefault('CURRENT_TIMESTAMP')->setNotnull(true),
(new Column('originalcreated', self::type(Types::DATETIME_IMMUTABLE)))->setDefault('CURRENT_TIMESTAMP')->setNotnull(true),
Expand All @@ -64,14 +59,14 @@ private function createNodeTable(): Table
->addIndex(['nodetypename']);
}

private function createHierarchyRelationTable(): Table
private function createHierarchyRelationTable(AbstractPlatform $platform): Table
{
$table = self::createTable($this->tableNames->hierarchyRelation(), [
(new Column('position', self::type(Types::INTEGER)))->setNotnull(true),
DbalSchemaFactory::columnForContentStreamId('contentstreamid')->setNotnull(true),
DbalSchemaFactory::columnForDimensionSpacePointHash('dimensionspacepointhash')->setNotnull(true),
DbalSchemaFactory::columnForNodeAnchorPoint('parentnodeanchor'),
DbalSchemaFactory::columnForNodeAnchorPoint('childnodeanchor'),
DbalSchemaFactory::columnForContentStreamId('contentstreamid', $platform)->setNotnull(true),
DbalSchemaFactory::columnForDimensionSpacePointHash('dimensionspacepointhash', $platform)->setNotnull(true),
DbalSchemaFactory::columnForNodeAnchorPoint('parentnodeanchor', $platform),
DbalSchemaFactory::columnForNodeAnchorPoint('childnodeanchor', $platform),
(new Column('subtreetags', self::type(Types::JSON))),
]);

Expand All @@ -84,50 +79,50 @@ private function createHierarchyRelationTable(): Table
->addIndex(['contentstreamid', 'dimensionspacepointhash']);
}

private function createDimensionSpacePointsTable(): Table
private function createDimensionSpacePointsTable(AbstractPlatform $platform): Table
{
$table = self::createTable($this->tableNames->dimensionSpacePoints(), [
DbalSchemaFactory::columnForDimensionSpacePointHash('hash')->setNotnull(true),
DbalSchemaFactory::columnForDimensionSpacePoint('dimensionspacepoint')->setNotnull(true)
DbalSchemaFactory::columnForDimensionSpacePointHash('hash', $platform)->setNotnull(true),
DbalSchemaFactory::columnForDimensionSpacePoint('dimensionspacepoint', $platform)->setNotnull(true)
]);

return $table
->setPrimaryKey(['hash']);
}

private function createReferenceRelationTable(): Table
private function createReferenceRelationTable(AbstractPlatform $platform): Table
{
$table = self::createTable($this->tableNames->referenceRelation(), [
(new Column('name', self::type(Types::STRING)))->setLength(255)->setNotnull(true)->setPlatformOption('charset', 'ascii')->setPlatformOption('collation', 'ascii_general_ci'),
(new Column('name', self::type(Types::STRING)))->setLength(255)->setNotnull(true),
(new Column('position', self::type(Types::INTEGER)))->setNotnull(true),
DbalSchemaFactory::columnForNodeAnchorPoint('nodeanchorpoint'),
(new Column('properties', self::type(Types::TEXT)))->setNotnull(false)->setPlatformOption('collation', self::DEFAULT_TEXT_COLLATION),
DbalSchemaFactory::columnForNodeAggregateId('destinationnodeaggregateid')->setNotnull(true)
DbalSchemaFactory::columnForNodeAnchorPoint('nodeanchorpoint', $platform),
DbalSchemaFactory::columnForProperties('properties', $platform)->setNotnull(false),
DbalSchemaFactory::columnForNodeAggregateId('destinationnodeaggregateid', $platform)->setNotnull(true)
]);

return $table
->setPrimaryKey(['name', 'position', 'nodeanchorpoint']);
}

private function createWorkspaceTable(): Table
private function createWorkspaceTable(AbstractPlatform $platform): Table
{
$workspaceTable = self::createTable($this->tableNames->workspace(), [
DbalSchemaFactory::columnForWorkspaceName('name')->setNotnull(true),
DbalSchemaFactory::columnForWorkspaceName('baseWorkspaceName')->setNotnull(false),
DbalSchemaFactory::columnForContentStreamId('currentContentStreamId')->setNotNull(true),
DbalSchemaFactory::columnForWorkspaceName('name', $platform)->setNotnull(true),
DbalSchemaFactory::columnForWorkspaceName('baseWorkspaceName', $platform)->setNotnull(false),
DbalSchemaFactory::columnForContentStreamId('currentContentStreamId', $platform)->setNotNull(true),
]);

$workspaceTable->addUniqueIndex(['currentContentStreamId']);

return $workspaceTable->setPrimaryKey(['name']);
}

private function createContentStreamTable(): Table
private function createContentStreamTable(AbstractPlatform $platform): Table
{
$contentStreamTable = self::createTable($this->tableNames->contentStream(), [
DbalSchemaFactory::columnForContentStreamId('id')->setNotnull(true),
DbalSchemaFactory::columnForContentStreamId('id', $platform)->setNotnull(true),
(new Column('version', Type::getType(Types::INTEGER)))->setNotnull(true),
DbalSchemaFactory::columnForContentStreamId('sourceContentStreamId')->setNotnull(false),
DbalSchemaFactory::columnForContentStreamId('sourceContentStreamId', $platform)->setNotnull(false),
(new Column('sourceContentStreamVersion', Type::getType(Types::INTEGER)))->setNotnull(false),
(new Column('closed', Type::getType(Types::BOOLEAN)))->setNotnull(true),
(new Column('hasChanges', Type::getType(Types::BOOLEAN)))->setNotnull(true),
Expand Down
Loading

0 comments on commit b6a5f8d

Please sign in to comment.