Skip to content

Commit

Permalink
BUGFIX: Reintroduce catchup hooks for all projections
Browse files Browse the repository at this point in the history
Also allows the `Vendor.Package:FakeCatchupHook` to be picked up for testing
  • Loading branch information
mhsdesign committed Nov 23, 2024
1 parent 6f43825 commit 60d4f8c
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ final class ContentRepositoryFactory
private ?ContentRepository $contentRepositoryRuntimeCache = null;

/**
* @param CatchUpHookFactoryInterface<ContentGraphReadModelInterface> $contentGraphCatchUpHookFactory
* @param CatchUpHookFactoryInterface<ContentGraphReadModelInterface>|null $contentGraphCatchUpHookFactory
*/
public function __construct(
private readonly ContentRepositoryId $contentRepositoryId,
Expand All @@ -77,7 +77,7 @@ public function __construct(
private readonly ClockInterface $clock,
SubscriptionStoreInterface $subscriptionStore,
ContentGraphProjectionFactoryInterface $contentGraphProjectionFactory,
private readonly CatchUpHookFactoryInterface $contentGraphCatchUpHookFactory,
private readonly CatchUpHookFactoryInterface|null $contentGraphCatchUpHookFactory,
private readonly CommandHooksFactory $commandHooksFactory,
private readonly ContentRepositorySubscriberFactories $additionalSubscriberFactories,
LoggerInterface|null $logger = null,
Expand Down Expand Up @@ -115,7 +115,7 @@ private function buildContentGraphSubscriber(): ProjectionSubscriber
return new ProjectionSubscriber(
SubscriptionId::fromString('contentGraph'),
$this->contentGraphProjection,
$this->contentGraphCatchUpHookFactory->build(CatchUpHookFactoryDependencies::create(
$this->contentGraphCatchUpHookFactory?->build(CatchUpHookFactoryDependencies::create(
$this->contentRepositoryId,
$this->contentGraphProjection->getState(),
$this->subscriberFactoryDependencies->nodeTypeManager,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

namespace Neos\ContentRepository\Core\Factory;

use Neos\ContentRepository\Core\Projection\CatchUpHook\CatchUpHookFactoryDependencies;
use Neos\ContentRepository\Core\Projection\CatchUpHook\CatchUpHookFactoryInterface;
use Neos\ContentRepository\Core\Projection\ProjectionFactoryInterface;
use Neos\ContentRepository\Core\Projection\ProjectionInterface;
use Neos\ContentRepository\Core\Projection\ProjectionStateInterface;
Expand All @@ -27,21 +29,32 @@
{
/**
* @param ProjectionFactoryInterface<ProjectionInterface<ProjectionStateInterface>> $projectionFactory
* @param CatchUpHookFactoryInterface<ProjectionStateInterface>|null $catchUpHookFactory
* @param array<string, mixed> $projectionFactoryOptions
*/
public function __construct(
private SubscriptionId $subscriptionId,
private ProjectionFactoryInterface $projectionFactory,
private ?CatchUpHookFactoryInterface $catchUpHookFactory,
private array $projectionFactoryOptions,
) {
}

public function build(SubscriberFactoryDependencies $dependencies): ProjectionSubscriber
{
$projection = $this->projectionFactory->build($dependencies, $this->projectionFactoryOptions);
$catchUpHook = $this->catchUpHookFactory?->build(CatchUpHookFactoryDependencies::create(
$dependencies->contentRepositoryId,
$projection->getState(),
$dependencies->nodeTypeManager,
$dependencies->contentDimensionSource,
$dependencies->interDimensionalVariationGraph,
));

return new ProjectionSubscriber(
$this->subscriptionId,
$this->projectionFactory->build($dependencies, $this->projectionFactoryOptions),
null
$projection,
$catchUpHook,
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ private function has(string $catchUpHookFactoryClassName): bool
return array_key_exists($catchUpHookFactoryClassName, $this->catchUpHookFactories);
}

public function isEmpty(): bool
{
return $this->catchUpHookFactories === [];
}

public function build(CatchUpHookFactoryDependencies $dependencies): CatchUpHookInterface
{
$catchUpHooks = array_map(static fn(CatchUpHookFactoryInterface $catchUpHookFactory) => $catchUpHookFactory->build($dependencies), $this->catchUpHookFactories);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
use Neos\ContentRepository\Core\Projection\ContentGraph\ContentSubgraphInterface;
use Neos\ContentRepository\Core\Projection\ContentGraph\Node;
use Neos\ContentRepository\Core\Projection\ProjectionFactoryInterface;
use Neos\ContentRepository\Core\Projection\ProjectionStateInterface;
use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId;
use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryIds;
use Neos\ContentRepository\Core\Subscription\Store\SubscriptionStoreInterface;
Expand Down Expand Up @@ -57,6 +58,9 @@ final class ContentRepositoryRegistry
*/
private array $factoryInstances = [];

/**
* @var array<string, mixed>
*/
private array $settings;

#[Flow\Inject(name: 'Neos.ContentRepositoryRegistry:Logger', lazy: false)]
Expand Down Expand Up @@ -183,6 +187,8 @@ private function buildFactory(ContentRepositoryId $contentRepositoryId): Content
unset($contentRepositorySettings['preset']);
}
try {
/** @var CatchUpHookFactoryInterface<ContentGraphReadModelInterface>|null $contentGraphCatchUpHookFactory */
$contentGraphCatchUpHookFactory = $this->buildCatchUpHookFactory($contentRepositoryId, 'contentGraph', $contentRepositorySettings['contentGraphProjection']);
$clock = $this->buildClock($contentRepositoryId, $contentRepositorySettings);
return new ContentRepositoryFactory(
$contentRepositoryId,
Expand All @@ -194,7 +200,7 @@ private function buildFactory(ContentRepositoryId $contentRepositoryId): Content
$clock,
$this->buildSubscriptionStore($contentRepositoryId, $clock, $contentRepositorySettings),
$this->buildContentGraphProjectionFactory($contentRepositoryId, $contentRepositorySettings),
$this->buildContentGraphCatchUpHookFactory($contentRepositoryId, $contentRepositorySettings),
$contentGraphCatchUpHookFactory,
$this->buildCommandHooksFactory($contentRepositoryId, $contentRepositorySettings),
$this->buildAdditionalSubscribersFactories($contentRepositoryId, $contentRepositorySettings),
$this->logger,
Expand Down Expand Up @@ -275,27 +281,29 @@ private function buildContentGraphProjectionFactory(ContentRepositoryId $content
}

/**
* @param array<string, mixed> $contentRepositorySettings
* @return CatchUpHookFactoryInterface<ContentGraphReadModelInterface>
* @param array<string, mixed> $projectionOptions
* @return CatchUpHookFactoryInterface<ProjectionStateInterface>|null
*/
private function buildContentGraphCatchUpHookFactory(ContentRepositoryId $contentRepositoryId, array $contentRepositorySettings): CatchUpHookFactoryInterface
private function buildCatchUpHookFactory(ContentRepositoryId $contentRepositoryId, string $projectionName, array $projectionOptions): ?CatchUpHookFactoryInterface
{
if (!isset($contentRepositorySettings['contentGraphProjection']['catchUpHooks'])) {
throw InvalidConfigurationException::fromMessage('Content repository "%s" does not have the contentGraphProjection.catchUpHooks configured.', $contentRepositoryId->value);
if (!isset($projectionOptions['catchUpHooks'])) {
return null;
}
$catchUpHookFactories = CatchUpHookFactories::create();
foreach ($contentRepositorySettings['contentGraphProjection']['catchUpHooks'] as $catchUpHookName => $catchUpHookOptions) {
foreach ($projectionOptions['catchUpHooks'] as $catchUpHookName => $catchUpHookOptions) {
if ($catchUpHookOptions === null) {
// Allow catch up hooks to be disabled by setting their configuration to `null`
continue;
}
$catchUpHookFactory = $this->objectManager->get($catchUpHookOptions['factoryObjectName']);
if (!$catchUpHookFactory instanceof CatchUpHookFactoryInterface) {
throw InvalidConfigurationException::fromMessage('CatchUpHook factory object name for content graph CatchUpHook "%s" (content repository "%s") is not an instance of %s but %s', $catchUpHookName, $contentRepositoryId->value, CatchUpHookFactoryInterface::class, get_debug_type($catchUpHookFactory));
throw InvalidConfigurationException::fromMessage('CatchUpHook factory object name for hook "%s" in projection "%s" (content repository "%s") is not an instance of %s but %s', $catchUpHookName, $projectionName, $contentRepositoryId->value, CatchUpHookFactoryInterface::class, get_debug_type($catchUpHookFactory));
}
$catchUpHookFactories = $catchUpHookFactories->with($catchUpHookFactory);
}
/** @var CatchUpHookFactoryInterface<ContentGraphReadModelInterface> $catchUpHookFactories */
if ($catchUpHookFactories->isEmpty()) {
return null;
}
return $catchUpHookFactories;
}

Expand Down Expand Up @@ -344,6 +352,7 @@ private function buildAdditionalSubscribersFactories(ContentRepositoryId $conten
$projectionSubscriberFactories[$projectionName] = new ProjectionSubscriberFactory(
SubscriptionId::fromString($projectionName),
$projectionFactory,
$this->buildCatchUpHookFactory($contentRepositoryId, $projectionName, $projectionOptions),
$projectionOptions['options'] ?? [],
);
}
Expand Down

0 comments on commit 60d4f8c

Please sign in to comment.