Skip to content

Commit b1168c4

Browse files
committed
Merge remote-tracking branch 'origin/9.0' into task/schema-postgresql
2 parents 7e15553 + f0c6111 commit b1168c4

File tree

144 files changed

+6947
-1979
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

144 files changed

+6947
-1979
lines changed

Neos.ContentGraph.DoctrineDbalAdapter/src/ContentGraphTableNames.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,4 @@ public function contentStream(): string
5151
{
5252
return $this->tableNamePrefix . '_contentstream';
5353
}
54-
55-
public function checkpoint(): string
56-
{
57-
return $this->tableNamePrefix . '_checkpoint';
58-
}
5954
}

Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php

Lines changed: 2 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,8 @@
5959
use Neos\ContentRepository\Core\Feature\WorkspacePublication\Event\WorkspaceWasPublished;
6060
use Neos\ContentRepository\Core\Feature\WorkspaceRebase\Event\WorkspaceRebaseFailed;
6161
use Neos\ContentRepository\Core\Feature\WorkspaceRebase\Event\WorkspaceWasRebased;
62-
use Neos\ContentRepository\Core\Infrastructure\DbalCheckpointStorage;
6362
use Neos\ContentRepository\Core\Infrastructure\DbalSchemaDiff;
6463
use Neos\ContentRepository\Core\NodeType\NodeTypeName;
65-
use Neos\ContentRepository\Core\Projection\CheckpointStorageStatusType;
6664
use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphProjectionInterface;
6765
use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphReadModelInterface;
6866
use Neos\ContentRepository\Core\Projection\ContentGraph\NodeTags;
@@ -73,7 +71,6 @@
7371
use Neos\ContentRepository\Core\SharedModel\Node\NodeName;
7472
use Neos\ContentRepository\Core\SharedModel\Node\ReferenceName;
7573
use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId;
76-
use Neos\EventStore\Model\Event\SequenceNumber;
7774
use Neos\EventStore\Model\EventEnvelope;
7875

7976
/**
@@ -91,20 +88,13 @@ final class DoctrineDbalContentGraphProjection implements ContentGraphProjection
9188

9289
public const RELATION_DEFAULT_OFFSET = 128;
9390

94-
private DbalCheckpointStorage $checkpointStorage;
95-
9691
public function __construct(
9792
private readonly Connection $dbal,
9893
private readonly ProjectionContentGraph $projectionContentGraph,
9994
private readonly ContentGraphTableNames $tableNames,
10095
private readonly DimensionSpacePointsRepository $dimensionSpacePointsRepository,
10196
private readonly ContentGraphReadModelInterface $contentGraphReadModel
10297
) {
103-
$this->checkpointStorage = new DbalCheckpointStorage(
104-
$this->dbal,
105-
$this->tableNames->checkpoint(),
106-
self::class
107-
);
10898
}
10999

110100
public function setUp(): void
@@ -118,18 +108,10 @@ public function setUp(): void
118108
throw new \RuntimeException(sprintf('Failed to setup projection %s: %s', self::class, $e->getMessage()), 1716478255, $e);
119109
}
120110
}
121-
$this->checkpointStorage->setUp();
122111
}
123112

124113
public function status(): ProjectionStatus
125114
{
126-
$checkpointStorageStatus = $this->checkpointStorage->status();
127-
if ($checkpointStorageStatus->type === CheckpointStorageStatusType::ERROR) {
128-
return ProjectionStatus::error($checkpointStorageStatus->details);
129-
}
130-
if ($checkpointStorageStatus->type === CheckpointStorageStatusType::SETUP_REQUIRED) {
131-
return ProjectionStatus::setupRequired($checkpointStorageStatus->details);
132-
}
133115
try {
134116
$this->dbal->connect();
135117
} catch (\Throwable $e) {
@@ -147,59 +129,16 @@ public function status(): ProjectionStatus
147129
return ProjectionStatus::ok();
148130
}
149131

150-
public function reset(): void
132+
public function resetState(): void
151133
{
152134
$this->truncateDatabaseTables();
153-
154-
$this->checkpointStorage->acquireLock();
155-
$this->checkpointStorage->updateAndReleaseLock(SequenceNumber::none());
156-
}
157-
158-
public function getCheckpointStorage(): DbalCheckpointStorage
159-
{
160-
return $this->checkpointStorage;
161135
}
162136

163137
public function getState(): ContentGraphReadModelInterface
164138
{
165139
return $this->contentGraphReadModel;
166140
}
167141

168-
public function canHandle(EventInterface $event): bool
169-
{
170-
return in_array($event::class, [
171-
ContentStreamWasClosed::class,
172-
ContentStreamWasCreated::class,
173-
ContentStreamWasForked::class,
174-
ContentStreamWasRemoved::class,
175-
ContentStreamWasReopened::class,
176-
DimensionShineThroughWasAdded::class,
177-
DimensionSpacePointWasMoved::class,
178-
NodeAggregateNameWasChanged::class,
179-
NodeAggregateTypeWasChanged::class,
180-
NodeAggregateWasMoved::class,
181-
NodeAggregateWasRemoved::class,
182-
NodeAggregateWithNodeWasCreated::class,
183-
NodeGeneralizationVariantWasCreated::class,
184-
NodePeerVariantWasCreated::class,
185-
NodePropertiesWereSet::class,
186-
NodeReferencesWereSet::class,
187-
NodeSpecializationVariantWasCreated::class,
188-
RootNodeAggregateDimensionsWereUpdated::class,
189-
RootNodeAggregateWithNodeWasCreated::class,
190-
RootWorkspaceWasCreated::class,
191-
SubtreeWasTagged::class,
192-
SubtreeWasUntagged::class,
193-
WorkspaceBaseWorkspaceWasChanged::class,
194-
WorkspaceRebaseFailed::class,
195-
WorkspaceWasCreated::class,
196-
WorkspaceWasDiscarded::class,
197-
WorkspaceWasPublished::class,
198-
WorkspaceWasRebased::class,
199-
WorkspaceWasRemoved::class,
200-
]) || $event instanceof EmbedsContentStreamId;
201-
}
202-
203142
public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void
204143
{
205144
match ($event::class) {
@@ -232,7 +171,7 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void
232171
WorkspaceWasPublished::class => $this->whenWorkspaceWasPublished($event),
233172
WorkspaceWasRebased::class => $this->whenWorkspaceWasRebased($event),
234173
WorkspaceWasRemoved::class => $this->whenWorkspaceWasRemoved($event),
235-
default => $event instanceof EmbedsContentStreamId || throw new \InvalidArgumentException(sprintf('Unsupported event %s', get_debug_type($event))),
174+
default => null,
236175
};
237176
if (
238177
$event instanceof EmbedsContentStreamId

Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjectionFactory.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\DimensionSpacePointsRepository;
99
use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\NodeFactory;
1010
use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\ProjectionContentGraph;
11-
use Neos\ContentRepository\Core\Factory\ProjectionFactoryDependencies;
11+
use Neos\ContentRepository\Core\Factory\SubscriberFactoryDependencies;
1212
use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphProjectionFactoryInterface;
1313

1414
/**
@@ -24,8 +24,7 @@ public function __construct(
2424
}
2525

2626
public function build(
27-
ProjectionFactoryDependencies $projectionFactoryDependencies,
28-
array $options,
27+
SubscriberFactoryDependencies $projectionFactoryDependencies,
2928
): DoctrineDbalContentGraphProjection {
3029
$tableNames = ContentGraphTableNames::create(
3130
$projectionFactoryDependencies->contentRepositoryId
@@ -35,7 +34,7 @@ public function build(
3534

3635
$nodeFactory = new NodeFactory(
3736
$projectionFactoryDependencies->contentRepositoryId,
38-
$projectionFactoryDependencies->propertyConverter,
37+
$projectionFactoryDependencies->getPropertyConverter(),
3938
$dimensionSpacePointsRepository
4039
);
4140

Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/HypergraphProjection.php

Lines changed: 4 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
namespace Neos\ContentGraph\PostgreSQLAdapter\Domain\Projection;
1616

1717
use Doctrine\DBAL\Connection;
18-
use Doctrine\DBAL\Schema\AbstractSchemaManager;
1918
use Neos\ContentGraph\PostgreSQLAdapter\Domain\Projection\Feature\ContentStreamForking;
2019
use Neos\ContentGraph\PostgreSQLAdapter\Domain\Projection\Feature\NodeCreation;
2120
use Neos\ContentGraph\PostgreSQLAdapter\Domain\Projection\Feature\NodeModification;
@@ -26,7 +25,6 @@
2625
use Neos\ContentGraph\PostgreSQLAdapter\Domain\Projection\Feature\NodeVariation;
2726
use Neos\ContentGraph\PostgreSQLAdapter\Domain\Projection\Feature\SubtreeTagging;
2827
use Neos\ContentGraph\PostgreSQLAdapter\Domain\Projection\SchemaBuilder\HypergraphSchemaBuilder;
29-
use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphReadModelInterface;
3028
use Neos\ContentRepository\Core\EventStore\EventInterface;
3129
use Neos\ContentRepository\Core\Feature\ContentStreamForking\Event\ContentStreamWasForked;
3230
use Neos\ContentRepository\Core\Feature\NodeCreation\Event\NodeAggregateWithNodeWasCreated;
@@ -41,12 +39,10 @@
4139
use Neos\ContentRepository\Core\Feature\RootNodeCreation\Event\RootNodeAggregateWithNodeWasCreated;
4240
use Neos\ContentRepository\Core\Feature\SubtreeTagging\Event\SubtreeWasTagged;
4341
use Neos\ContentRepository\Core\Feature\SubtreeTagging\Event\SubtreeWasUntagged;
44-
use Neos\ContentRepository\Core\Infrastructure\DbalCheckpointStorage;
4542
use Neos\ContentRepository\Core\Infrastructure\DbalSchemaDiff;
46-
use Neos\ContentRepository\Core\Projection\CheckpointStorageStatusType;
47-
use Neos\ContentRepository\Core\Projection\ProjectionStatus;
4843
use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphProjectionInterface;
49-
use Neos\EventStore\Model\Event\SequenceNumber;
44+
use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphReadModelInterface;
45+
use Neos\ContentRepository\Core\Projection\ProjectionStatus;
5046
use Neos\EventStore\Model\EventEnvelope;
5147

5248
/**
@@ -66,7 +62,6 @@ final class HypergraphProjection implements ContentGraphProjectionInterface
6662
use NodeTypeChange;
6763
use NodeVariation;
6864

69-
private DbalCheckpointStorage $checkpointStorage;
7065
private ProjectionHypergraph $projectionHypergraph;
7166

7267
public function __construct(
@@ -75,11 +70,6 @@ public function __construct(
7570
private readonly ContentGraphReadModelInterface $contentGraphReadModel
7671
) {
7772
$this->projectionHypergraph = new ProjectionHypergraph($this->dbal, $this->tableNamePrefix);
78-
$this->checkpointStorage = new DbalCheckpointStorage(
79-
$this->dbal,
80-
$this->tableNamePrefix . '_checkpoint',
81-
self::class
82-
);
8373
}
8474

8575

@@ -97,18 +87,10 @@ public function setUp(): void
9787
create index if not exists restriction_affected
9888
on ' . $this->tableNamePrefix . '_restrictionhyperrelation using gin (affectednodeaggregateids);
9989
');
100-
$this->checkpointStorage->setUp();
10190
}
10291

10392
public function status(): ProjectionStatus
10493
{
105-
$checkpointStorageStatus = $this->checkpointStorage->status();
106-
if ($checkpointStorageStatus->type === CheckpointStorageStatusType::ERROR) {
107-
return ProjectionStatus::error($checkpointStorageStatus->details);
108-
}
109-
if ($checkpointStorageStatus->type === CheckpointStorageStatusType::SETUP_REQUIRED) {
110-
return ProjectionStatus::setupRequired($checkpointStorageStatus->details);
111-
}
11294
try {
11395
$this->getDatabaseConnection()->connect();
11496
} catch (\Throwable $e) {
@@ -135,12 +117,9 @@ private function determineRequiredSqlStatements(): array
135117
return DbalSchemaDiff::determineRequiredSqlStatements($this->dbal, $schema);
136118
}
137119

138-
public function reset(): void
120+
public function resetState(): void
139121
{
140122
$this->truncateDatabaseTables();
141-
142-
$this->checkpointStorage->acquireLock();
143-
$this->checkpointStorage->updateAndReleaseLock(SequenceNumber::none());
144123
}
145124

146125
private function truncateDatabaseTables(): void
@@ -151,39 +130,6 @@ private function truncateDatabaseTables(): void
151130
$this->dbal->executeQuery('TRUNCATE table ' . $this->tableNamePrefix . '_restrictionhyperrelation');
152131
}
153132

154-
public function canHandle(EventInterface $event): bool
155-
{
156-
return in_array($event::class, [
157-
// ContentStreamForking
158-
ContentStreamWasForked::class,
159-
// NodeCreation
160-
RootNodeAggregateWithNodeWasCreated::class,
161-
NodeAggregateWithNodeWasCreated::class,
162-
// SubtreeTagging
163-
SubtreeWasTagged::class,
164-
SubtreeWasUntagged::class,
165-
// NodeModification
166-
NodePropertiesWereSet::class,
167-
// NodeReferencing
168-
NodeReferencesWereSet::class,
169-
// NodeRemoval
170-
NodeAggregateWasRemoved::class,
171-
// NodeRenaming
172-
NodeAggregateNameWasChanged::class,
173-
// NodeTypeChange
174-
NodeAggregateTypeWasChanged::class,
175-
// NodeVariation
176-
NodeSpecializationVariantWasCreated::class,
177-
NodeGeneralizationVariantWasCreated::class,
178-
NodePeerVariantWasCreated::class,
179-
// TODO: not yet supported:
180-
//ContentStreamWasRemoved::class,
181-
//DimensionSpacePointWasMoved::class,
182-
//DimensionShineThroughWasAdded::class,
183-
//NodeAggregateWasMoved::class,
184-
]);
185-
}
186-
187133
public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void
188134
{
189135
match ($event::class) {
@@ -209,7 +155,7 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void
209155
NodeSpecializationVariantWasCreated::class => $this->whenNodeSpecializationVariantWasCreated($event),
210156
NodeGeneralizationVariantWasCreated::class => $this->whenNodeGeneralizationVariantWasCreated($event),
211157
NodePeerVariantWasCreated::class => $this->whenNodePeerVariantWasCreated($event),
212-
default => throw new \InvalidArgumentException(sprintf('Unsupported event %s', get_debug_type($event))),
158+
default => null,
213159
};
214160
}
215161

@@ -228,11 +174,6 @@ public function inSimulation(\Closure $fn): mixed
228174
}
229175
}
230176

231-
public function getCheckpointStorage(): DbalCheckpointStorage
232-
{
233-
return $this->checkpointStorage;
234-
}
235-
236177
public function getState(): ContentGraphReadModelInterface
237178
{
238179
return $this->contentGraphReadModel;

Neos.ContentGraph.PostgreSQLAdapter/src/HypergraphProjectionFactory.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use Doctrine\DBAL\Connection;
88
use Neos\ContentGraph\PostgreSQLAdapter\Domain\Projection\HypergraphProjection;
99
use Neos\ContentGraph\PostgreSQLAdapter\Domain\Repository\NodeFactory;
10-
use Neos\ContentRepository\Core\Factory\ProjectionFactoryDependencies;
10+
use Neos\ContentRepository\Core\Factory\SubscriberFactoryDependencies;
1111
use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphProjectionFactoryInterface;
1212
use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId;
1313

@@ -28,16 +28,15 @@ public static function graphProjectionTableNamePrefix(
2828
}
2929

3030
public function build(
31-
ProjectionFactoryDependencies $projectionFactoryDependencies,
32-
array $options,
31+
SubscriberFactoryDependencies $projectionFactoryDependencies,
3332
): HypergraphProjection {
3433
$tableNamePrefix = self::graphProjectionTableNamePrefix(
3534
$projectionFactoryDependencies->contentRepositoryId
3635
);
3736

3837
$nodeFactory = new NodeFactory(
3938
$projectionFactoryDependencies->contentRepositoryId,
40-
$projectionFactoryDependencies->propertyConverter
39+
$projectionFactoryDependencies->getPropertyConverter()
4140
);
4241

4342
return new HypergraphProjection(

Neos.ContentRepository.BehavioralTests/Classes/ProjectionRaceConditionTester/RaceTrackerCatchUpHook.php

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,13 @@
1717
use Neos\ContentRepository\BehavioralTests\ProjectionRaceConditionTester\Dto\TraceEntries;
1818
use Neos\ContentRepository\BehavioralTests\ProjectionRaceConditionTester\Dto\TraceEntryType;
1919
use Neos\ContentRepository\Core\EventStore\EventInterface;
20-
use Neos\ContentRepository\Core\Projection\CatchUpHookInterface;
20+
use Neos\ContentRepository\Core\Projection\CatchUpHook\CatchUpHookInterface;
21+
use Neos\ContentRepository\Core\Subscription\SubscriptionStatus;
2122
use Neos\EventStore\Model\EventEnvelope;
2223
use Neos\Flow\Annotations as Flow;
2324

2425
/**
25-
* We had some race conditions in projections, where {@see \Neos\ContentRepository\Core\Infrastructure\DbalCheckpointStorage} was not working properly.
26+
* We had some race conditions in projections
2627
* We saw some non-deterministic, random errors when running the tests - unluckily only on Linux, not on OSX:
2728
* On OSX, forking a new subprocess in {@see SubprocessProjectionCatchUpTrigger} is *WAY* slower than in Linux;
2829
* and thus the race conditions which appears if two projector instances of the same class run concurrently
@@ -73,7 +74,7 @@
7374
*
7475
* When {@see onBeforeEvent} is called, we know that we are inside applyEvent() in the diagram above,
7576
* thus we know the lock *HAS* been acquired.
76-
* When {@see onBeforeBatchCompleted}is called, we know the lock will be released directly afterwards.
77+
* When {@see onAfterCatchUp}is called, we know the lock will be released directly afterwards.
7778
*
7879
* We track these timings across processes in a single Redis Stream. Because Redis is single-threaded,
7980
* we can be sure that we observe the correct, total order of interleavings *across multiple processes*
@@ -107,7 +108,7 @@ final class RaceTrackerCatchUpHook implements CatchUpHookInterface
107108
protected $configuration;
108109
private bool $inCriticalSection = false;
109110

110-
public function onBeforeCatchUp(): void
111+
public function onBeforeCatchUp(SubscriptionStatus $subscriptionStatus): void
111112
{
112113
RedisInterleavingLogger::connect($this->configuration['redis']['host'], $this->configuration['redis']['port']);
113114
}
@@ -126,16 +127,16 @@ public function onAfterEvent(EventInterface $eventInstance, EventEnvelope $event
126127
{
127128
}
128129

129-
public function onBeforeBatchCompleted(): void
130+
public function onAfterBatchCompleted(): void
131+
{
132+
}
133+
134+
public function onAfterCatchUp(): void
130135
{
131136
// we only want to track relevant lock release calls (i.e. if we were in the event processing loop before)
132137
if ($this->inCriticalSection) {
133138
$this->inCriticalSection = false;
134139
RedisInterleavingLogger::trace(TraceEntryType::LockWillBeReleasedIfItWasAcquiredBefore);
135140
}
136141
}
137-
138-
public function onAfterCatchUp(): void
139-
{
140-
}
141142
}

0 commit comments

Comments
 (0)