Skip to content

Commit 008a835

Browse files
committed
TASK: Refactor document identifier builder
The builder is now configurable via the objects.yaml. With this, the change can got to a minor version and the new identifier and behavior can be tested.
1 parent f23dd53 commit 008a835

8 files changed

Lines changed: 126 additions & 95 deletions

File tree

Classes/Domain/Model/TargetContextPath.php

Lines changed: 0 additions & 45 deletions
This file was deleted.

Classes/Driver/AbstractIndexerDriver.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
* source code.
1414
*/
1515

16+
use Flowpack\ElasticSearch\ContentRepositoryAdaptor\Service\DocumentIdentifier\DocumentIdentifierGeneratorInterface;
1617
use Neos\ContentRepository\Domain\Model\NodeInterface;
1718
use Neos\Flow\Annotations as Flow;
1819
use Neos\Flow\Log\Utility\LogEnvironment;
@@ -28,6 +29,12 @@ abstract class AbstractIndexerDriver extends AbstractDriver
2829
*/
2930
protected $nodeTypeMappingBuilder;
3031

32+
/**
33+
* @Flow\Inject
34+
* @var DocumentIdentifierGeneratorInterface
35+
*/
36+
protected $documentIdentifierGenerator;
37+
3138
/**
3239
* Whether the node is configured as fulltext root.
3340
*

Classes/Driver/Version6/IndexerDriver.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@
1313
* source code.
1414
*/
1515

16+
use Neos\Flow\Annotations as Flow;
1617
use Flowpack\ElasticSearch\ContentRepositoryAdaptor\Indexer\NodeIndexer;
1718
use Flowpack\ElasticSearch\ContentRepositoryAdaptor\Driver\AbstractIndexerDriver;
1819
use Flowpack\ElasticSearch\ContentRepositoryAdaptor\Driver\IndexerDriverInterface;
1920
use Flowpack\ElasticSearch\Domain\Model\Document as ElasticSearchDocument;
2021
use Neos\ContentRepository\Domain\Model\NodeInterface;
21-
use Neos\Flow\Annotations as Flow;
2222
use Neos\Flow\Log\Utility\LogEnvironment;
2323

2424
/**
@@ -81,7 +81,10 @@ public function document(string $indexName, NodeInterface $node, ElasticSearchDo
8181

8282
/**
8383
* {@inheritdoc}
84-
* @throws \Neos\Flow\Persistence\Exception\IllegalObjectTypeException
84+
* @param NodeInterface $node
85+
* @param array $fulltextIndexOfNode
86+
* @param string|null $targetWorkspaceName
87+
* @return array
8588
*/
8689
public function fulltext(NodeInterface $node, array $fulltextIndexOfNode, string $targetWorkspaceName = null): array
8790
{
@@ -90,7 +93,7 @@ public function fulltext(NodeInterface $node, array $fulltextIndexOfNode, string
9093
return [];
9194
}
9295

93-
$closestFulltextNodeDocumentIdentifier = NodeIndexer::calculateDocumentIdentifier($closestFulltextNode);
96+
$closestFulltextNodeDocumentIdentifier = $this->documentIdentifierGenerator->generate($closestFulltextNode);
9497

9598
if ($closestFulltextNode->isRemoved()) {
9699
// fulltext root is removed, abort silently...

Classes/Indexer/NodeIndexer.php

Lines changed: 24 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
use Flowpack\ElasticSearch\ContentRepositoryAdaptor\ErrorHandling\ErrorStorageInterface;
2626
use Flowpack\ElasticSearch\ContentRepositoryAdaptor\Exception;
2727
use Flowpack\ElasticSearch\ContentRepositoryAdaptor\Service\DimensionsService;
28+
use Flowpack\ElasticSearch\ContentRepositoryAdaptor\Service\DocumentIdentifier\DocumentIdentifierGeneratorInterface;
2829
use Flowpack\ElasticSearch\ContentRepositoryAdaptor\Service\IndexNameService;
2930
use Flowpack\ElasticSearch\ContentRepositoryAdaptor\Service\NodeTypeIndexingConfiguration;
3031
use Flowpack\ElasticSearch\Domain\Model\Document as ElasticSearchDocument;
@@ -56,13 +57,6 @@ class NodeIndexer extends AbstractNodeIndexer implements BulkNodeIndexerInterfac
5657
*/
5758
protected $nodeTypeMappingBuilder;
5859

59-
/**
60-
* Optional postfix for the index, e.g. to have different indexes by timestamp.
61-
*
62-
* @var string
63-
*/
64-
protected $indexNamePostfix = '';
65-
6660
/**
6761
* @Flow\Inject
6862
* @var ErrorHandlingService
@@ -129,18 +123,6 @@ class NodeIndexer extends AbstractNodeIndexer implements BulkNodeIndexerInterfac
129123
*/
130124
protected $indexConfiguration;
131125

132-
/**
133-
* The current Elasticsearch bulk request, in the format required by http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/docs-bulk.html
134-
*
135-
* @var array
136-
*/
137-
protected $currentBulkRequest = [];
138-
139-
/**
140-
* @var boolean
141-
*/
142-
protected $bulkProcessing = false;
143-
144126
/**
145127
* @Flow\Inject
146128
* @var DimensionsService
@@ -153,12 +135,30 @@ class NodeIndexer extends AbstractNodeIndexer implements BulkNodeIndexerInterfac
153135
*/
154136
protected $nodeTypeIndexingConfiguration;
155137

138+
/**
139+
* @Flow\Inject
140+
* @var DocumentIdentifierGeneratorInterface
141+
*/
142+
protected $documentIdentifierGenerator;
143+
156144
/**
157145
* @Flow\Inject
158146
* @var ErrorStorageInterface
159147
*/
160148
protected $errorStorage;
161149

150+
/**
151+
* The current Elasticsearch bulk request, in the format required by http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/docs-bulk.html
152+
*/
153+
protected array $currentBulkRequest = [];
154+
155+
/**
156+
* Optional postfix for the index, e.g. to have different indexes by timestamp.
157+
*/
158+
protected string $indexNamePostfix = '';
159+
160+
protected bool $bulkProcessing = false;
161+
162162
public function setDimensions(array $dimensionsValues): void
163163
{
164164
$this->searchClient->setDimensions($dimensionsValues);
@@ -243,7 +243,7 @@ public function indexNode(NodeInterface $node, $targetWorkspaceName = null): voi
243243
}
244244
}
245245

246-
$documentIdentifier = NodeIndexer::calculateDocumentIdentifier($node, $targetWorkspaceName);
246+
$documentIdentifier = $this->documentIdentifierGenerator->generate($node, $targetWorkspaceName);
247247
$nodeType = $node->getNodeType();
248248

249249
$mappingType = $this->getIndex()->findType($nodeType->getName());
@@ -274,13 +274,6 @@ public function indexNode(NodeInterface $node, $targetWorkspaceName = null): voi
274274
$handleNode = function (NodeInterface $node, Context $context) use ($targetWorkspaceName, $indexer) {
275275
$nodeFromContext = $context->getNodeByIdentifier($node->getIdentifier());
276276
if ($nodeFromContext instanceof NodeInterface) {
277-
if ($node->getPath() !== $nodeFromContext->getPath()) {
278-
// If the node from context does have a different path, purge the context cache and re-fetch
279-
280-
// TODO: find a better way to handle this
281-
$context->getFirstLevelNodeCache()->flush();
282-
$nodeFromContext = $context->getNodeByIdentifier($node->getIdentifier());
283-
}
284277
$this->searchClient->withDimensions(static function () use ($indexer, $nodeFromContext, $targetWorkspaceName) {
285278
$indexer($nodeFromContext, $targetWorkspaceName);
286279
}, $nodeFromContext->getContext()->getTargetDimensions());
@@ -342,31 +335,14 @@ protected function toBulkRequest(NodeInterface $node, array $requests = null): v
342335
$this->flushIfNeeded();
343336
}
344337

345-
/**
346-
* Returns a stable identifier for the Elasticsearch document representing the node
347-
*
348-
* @param NodeInterface $node
349-
* @param string|null $targetWorkspaceName
350-
* @return string
351-
* @throws IllegalObjectTypeException
352-
*/
353-
public static function calculateDocumentIdentifier(NodeInterface $node, $targetWorkspaceName = null): string
354-
{
355-
$workspaceName = $targetWorkspaceName ?: $node->getWorkspace()->getName();
356-
$nodeIdentifier = $node->getIdentifier();
357-
358-
return sha1($nodeIdentifier . $workspaceName);
359-
}
360-
361338
/**
362339
* Schedule node removal into the current bulk request.
363340
*
364341
* @param NodeInterface $node
365-
* @param string $targetWorkspaceName
342+
* @param string|null $targetWorkspaceName
366343
* @return void
367344
* @throws Exception
368345
* @throws FilesException
369-
* @throws IllegalObjectTypeException
370346
* @throws \Flowpack\ElasticSearch\Exception
371347
*/
372348
public function removeNode(NodeInterface $node, string $targetWorkspaceName = null): void
@@ -384,7 +360,7 @@ public function removeNode(NodeInterface $node, string $targetWorkspaceName = nu
384360
}
385361
}
386362

387-
$documentIdentifier = NodeIndexer::calculateDocumentIdentifier($node, $targetWorkspaceName);
363+
$documentIdentifier = $this->documentIdentifierGenerator->generate($node, $targetWorkspaceName);
388364

389365
$this->toBulkRequest($node, $this->documentDriver->delete($node, $documentIdentifier));
390366
$this->toBulkRequest($node, $this->indexerDriver->fulltext($node, [], $targetWorkspaceName));
@@ -394,8 +370,8 @@ public function removeNode(NodeInterface $node, string $targetWorkspaceName = nu
394370

395371
/**
396372
* @throws Exception
373+
* @throws Exception\ConfigurationException
397374
* @throws \Flowpack\ElasticSearch\Exception
398-
* @throws FilesException
399375
*/
400376
protected function flushIfNeeded(): void
401377
{
@@ -554,6 +530,7 @@ public function updateIndexAlias(): void
554530
* Update the main alias to allow to query all indices at once
555531
* @throws Exception
556532
* @throws Exception\ConfigurationException
533+
* @throws ApiException
557534
*/
558535
public function updateMainAlias(): void
559536
{
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Flowpack\ElasticSearch\ContentRepositoryAdaptor\Service\DocumentIdentifier;
5+
6+
/*
7+
* This file is part of the Flowpack.ElasticSearch.ContentRepositoryAdaptor package.
8+
*
9+
* (c) Contributors of the Neos Project - www.neos.io
10+
*
11+
* This package is Open Source Software. For the full copyright and license
12+
* information, please view the LICENSE file which was distributed with this
13+
* source code.
14+
*/
15+
16+
use Neos\ContentRepository\Domain\Model\NodeInterface;
17+
18+
interface DocumentIdentifierGeneratorInterface
19+
{
20+
/**
21+
* Generates a stable identifier out of the given node
22+
*
23+
* @param NodeInterface $node
24+
* @return string
25+
*/
26+
public function generate(NodeInterface $node, ?string $targetWorkspaceName = null): string;
27+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Flowpack\ElasticSearch\ContentRepositoryAdaptor\Service\DocumentIdentifier;
5+
6+
/*
7+
* This file is part of the Flowpack.ElasticSearch.ContentRepositoryAdaptor package.
8+
*
9+
* (c) Contributors of the Neos Project - www.neos.io
10+
*
11+
* This package is Open Source Software. For the full copyright and license
12+
* information, please view the LICENSE file which was distributed with this
13+
* source code.
14+
*/
15+
16+
use Neos\ContentRepository\Domain\Model\NodeInterface;
17+
18+
class NodeIdentifierBasedDocumentIdentifierGenerator implements DocumentIdentifierGeneratorInterface
19+
{
20+
21+
public function generate(NodeInterface $node, ?string $targetWorkspaceName = null): string
22+
{
23+
$workspaceName = $targetWorkspaceName ?: $node->getWorkspace()->getName();
24+
$nodeIdentifier = $node->getIdentifier();
25+
26+
return sha1($nodeIdentifier . $workspaceName);
27+
}
28+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Flowpack\ElasticSearch\ContentRepositoryAdaptor\Service\DocumentIdentifier;
5+
6+
/*
7+
* This file is part of the Flowpack.ElasticSearch.ContentRepositoryAdaptor package.
8+
*
9+
* (c) Contributors of the Neos Project - www.neos.io
10+
*
11+
* This package is Open Source Software. For the full copyright and license
12+
* information, please view the LICENSE file which was distributed with this
13+
* source code.
14+
*/
15+
16+
use Neos\ContentRepository\Domain\Model\NodeInterface;
17+
18+
class NodePathBasedDocumentIdentifierGenerator implements DocumentIdentifierGeneratorInterface
19+
{
20+
21+
public function generate(NodeInterface $node, ?string $targetWorkspaceName = null): string
22+
{
23+
$contextPath = $node->getContextPath();
24+
25+
if ($targetWorkspaceName !== null) {
26+
$contextPath = str_replace($node->getContext()->getWorkspace()->getName(), $targetWorkspaceName, $contextPath);
27+
}
28+
29+
return sha1($contextPath);
30+
}
31+
}

Configuration/Objects.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ Neos\ContentRepository\Search\Indexer\NodeIndexerInterface:
77
Neos\ContentRepository\Search\AssetExtraction\AssetExtractorInterface:
88
className: 'Flowpack\ElasticSearch\ContentRepositoryAdaptor\AssetExtraction\IngestAttachmentAssetExtractor'
99

10+
'Flowpack\ElasticSearch\ContentRepositoryAdaptor\Service\DocumentIdentifier\DocumentIdentifierGeneratorInterface':
11+
className: 'Flowpack\ElasticSearch\ContentRepositoryAdaptor\Service\DocumentIdentifier\NodePathBasedDocumentIdentifierGenerator'
12+
1013
Flowpack\ElasticSearch\ContentRepositoryAdaptor\Driver\QueryInterface:
1114
scope: prototype
1215
factoryObjectName: 'Flowpack\ElasticSearch\ContentRepositoryAdaptor\Factory\QueryFactory'

0 commit comments

Comments
 (0)