Skip to content

Commit 1a48c80

Browse files
lukmzigbluvulture
andauthored
[Elements]: Add service to update siblings indexes after element update (#362)
* add service to update siblings indexes after element update * update PHP stan version * fix codeception tests * update dependencies * Apply php-cs-fixer changes * fix timing issues * fix: codeception tests * Debug composer contents * Debug composer contents * Set composer version * Cleanup debug * fix: unit tests * codeception * remove BC --------- Co-authored-by: lukmzig <lukmzig@users.noreply.github.com> Co-authored-by: nebojsa.ilic <nebojsa.ilic@pimcore.com>
1 parent 1d6e9c6 commit 1a48c80

File tree

21 files changed

+331
-57
lines changed

21 files changed

+331
-57
lines changed

.github/ci/files/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"pimcore/generic-data-index-bundle": "@dev"
1717
},
1818
"require-dev": {
19-
"codeception/codeception": "^5.0.10",
19+
"codeception/codeception": "^5.3.2",
2020
"codeception/phpunit-wrapper": "^9",
2121
"codeception/module-asserts": "^2",
2222
"codeception/module-symfony": "^3.1.1",

.github/workflows/elastic-search-codeception.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ jobs:
5858

5959
steps:
6060
- name: "Checkout code"
61-
uses: "actions/checkout@v2"
61+
uses: "actions/checkout@v4"
6262
with:
6363
path: "bundles/pimcore/generic-data-index-bundle"
6464

.github/workflows/open-search-codeception.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ jobs:
6161

6262
steps:
6363
- name: "Checkout code"
64-
uses: "actions/checkout@v2"
64+
uses: "actions/checkout@v4"
6565
with:
6666
path: "bundles/pimcore/generic-data-index-bundle"
6767

composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,11 @@
2828
},
2929
"require-dev": {
3030
"roave/security-advisories": "dev-latest",
31-
"codeception/codeception": "^5.0.10",
31+
"codeception/codeception": "^5.3.2",
3232
"codeception/phpunit-wrapper": "^9",
3333
"codeception/module-asserts": "^2",
3434
"codeception/module-symfony": "^3.1.1",
35-
"phpstan/phpstan": "^1.10.5",
35+
"phpstan/phpstan": "1.12.15",
3636
"phpstan/phpstan-symfony": "^1.2.20",
3737
"phpunit/phpunit": "10.2.7",
3838
"nyholm/psr7": "^1",

config/services/search/index.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ services:
1010
Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexEntityServiceInterface:
1111
class: Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexEntityService
1212

13+
Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexElementIndexServiceInterface:
14+
class: Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexElementIndexService
15+
1316
Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexUpdateServiceInterface:
1417
class: Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexUpdateService
1518

src/EventSubscriber/DataObjectIndexUpdateSubscriber.php

Lines changed: 51 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,20 @@
1313

1414
namespace Pimcore\Bundle\GenericDataIndexBundle\EventSubscriber;
1515

16+
use Pimcore\Bundle\GenericDataIndexBundle\Enum\SearchIndex\ElementType;
1617
use Pimcore\Bundle\GenericDataIndexBundle\Enum\SearchIndex\IndexQueueOperation;
1718
use Pimcore\Bundle\GenericDataIndexBundle\Installer;
19+
use Pimcore\Bundle\GenericDataIndexBundle\Service\Search\SearchService\DataObject\SearchHelper;
20+
use Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexElementIndexServiceInterface;
1821
use Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexQueue\QueueMessagesDispatcher;
1922
use Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexQueue\SynchronousProcessingRelatedIdsServiceInterface;
2023
use Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexQueue\SynchronousProcessingServiceInterface;
2124
use Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexQueueServiceInterface;
2225
use Pimcore\Bundle\GenericDataIndexBundle\Traits\LoggerAwareTrait;
26+
use Pimcore\Bundle\StaticResolverBundle\Lib\Cache\RuntimeCacheResolverInterface;
2327
use Pimcore\Event\DataObjectEvents;
2428
use Pimcore\Event\Model\DataObjectEvent;
29+
use Pimcore\Model\DataObject\AbstractObject;
2530
use Pimcore\Model\DataObject\Service;
2631
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
2732

@@ -35,7 +40,9 @@ final class DataObjectIndexUpdateSubscriber implements EventSubscriberInterface
3540
public function __construct(
3641
private readonly Installer $installer,
3742
private readonly IndexQueueServiceInterface $indexQueueService,
43+
private readonly IndexElementIndexServiceInterface $indexElementIndexService,
3844
private readonly QueueMessagesDispatcher $queueMessagesDispatcher,
45+
private readonly RuntimeCacheResolverInterface $runtimeCacheResolver,
3946
private readonly SynchronousProcessingServiceInterface $synchronousProcessing,
4047
private readonly SynchronousProcessingRelatedIdsServiceInterface $synchronousProcessingRelatedIds
4148
) {
@@ -44,57 +51,77 @@ public function __construct(
4451
public static function getSubscribedEvents(): array
4552
{
4653
return [
54+
DataObjectEvents::POST_ADD => 'addDataObject',
4755
DataObjectEvents::POST_UPDATE => 'updateDataObject',
48-
DataObjectEvents::POST_ADD => 'updateDataObject',
4956
DataObjectEvents::POST_DELETE => 'deleteDataObject',
5057
];
5158
}
5259

60+
public function addDataObject(DataObjectEvent $event): void
61+
{
62+
$this->updateData($event);
63+
}
64+
5365
public function updateDataObject(DataObjectEvent $event): void
5466
{
55-
if (!$this->installer->isInstalled()) {
56-
return;
67+
$this->indexElementIndexService->updateSiblings($event->getObject(), ElementType::DATA_OBJECT->value);
68+
if ($event->getObject()->getChildrenSortBy() === AbstractObject::OBJECT_CHILDREN_SORT_BY_INDEX) {
69+
$this->indexElementIndexService->resetChildrenIndexBy($event->getObject());
5770
}
71+
$this->updateData($event);
72+
}
5873

59-
//do not update index when auto save or only saving version
60-
if (
61-
($event->hasArgument('isAutoSave') && $event->getArgument('isAutoSave')) ||
62-
($event->hasArgument('saveVersionOnly') && $event->getArgument('saveVersionOnly'))
63-
) {
74+
public function deleteDataObject(DataObjectEvent $event): void
75+
{
76+
if (!$this->installer->isInstalled()) {
6477
return;
6578
}
6679

6780
$dataObject = $event->getObject();
68-
Service::useInheritedValues(true, fn () =>
69-
$this->indexQueueService
70-
->updateIndexQueue(
71-
$dataObject,
72-
IndexQueueOperation::UPDATE->value,
73-
$this->synchronousProcessing->isEnabled(),
74-
$dataObject->hasChildren(includingUnpublished: true),
75-
$this->synchronousProcessingRelatedIds->isEnabled() === false
76-
)
77-
->commit()
78-
);
79-
81+
$this->indexQueueService
82+
->updateIndexQueue(
83+
$dataObject,
84+
IndexQueueOperation::DELETE->value,
85+
$this->synchronousProcessing->isEnabled(),
86+
$dataObject->hasChildren(includingUnpublished: true)
87+
)
88+
->commit();
8089
$this->queueMessagesDispatcher->dispatchQueueMessages();
8190
}
8291

83-
public function deleteDataObject(DataObjectEvent $event): void
92+
private function updateData(DataObjectEvent $event): void
8493
{
8594
if (!$this->installer->isInstalled()) {
8695
return;
8796
}
8897

98+
//do not update index when auto save or only saving a version
99+
if (
100+
($event->hasArgument('isAutoSave') && $event->getArgument('isAutoSave')) ||
101+
($event->hasArgument('saveVersionOnly') && $event->getArgument('saveVersionOnly'))
102+
) {
103+
return;
104+
}
105+
89106
$dataObject = $event->getObject();
107+
Service::useInheritedValues(true, fn () =>
90108
$this->indexQueueService
91109
->updateIndexQueue(
92110
$dataObject,
93-
IndexQueueOperation::DELETE->value,
111+
IndexQueueOperation::UPDATE->value,
94112
$this->synchronousProcessing->isEnabled(),
95-
$dataObject->hasChildren(includingUnpublished: true)
113+
$dataObject->hasChildren(includingUnpublished: true),
114+
$this->synchronousProcessingRelatedIds->isEnabled() === false
96115
)
97-
->commit();
116+
->commit()
117+
);
118+
98119
$this->queueMessagesDispatcher->dispatchQueueMessages();
120+
121+
//clear runtime cache for this object
122+
$cacheKey = SearchHelper::OBJECT_SEARCH . '_' . $event->getObject()->getId();
123+
if ($this->runtimeCacheResolver->isRegistered($cacheKey)) {
124+
$this->runtimeCacheResolver->set($cacheKey, null);
125+
}
99126
}
100127
}

src/EventSubscriber/DocumentIndexUpdateSubscriber.php

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,16 @@
1313

1414
namespace Pimcore\Bundle\GenericDataIndexBundle\EventSubscriber;
1515

16+
use Pimcore\Bundle\GenericDataIndexBundle\Enum\SearchIndex\ElementType;
1617
use Pimcore\Bundle\GenericDataIndexBundle\Enum\SearchIndex\IndexQueueOperation;
1718
use Pimcore\Bundle\GenericDataIndexBundle\Installer;
19+
use Pimcore\Bundle\GenericDataIndexBundle\Service\Search\SearchService\Document\SearchHelper;
20+
use Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexElementIndexServiceInterface;
1821
use Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexQueue\QueueMessagesDispatcher;
1922
use Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexQueue\SynchronousProcessingRelatedIdsServiceInterface;
2023
use Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexQueue\SynchronousProcessingServiceInterface;
2124
use Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexQueueServiceInterface;
25+
use Pimcore\Bundle\StaticResolverBundle\Lib\Cache\RuntimeCacheResolverInterface;
2226
use Pimcore\Event\DocumentEvents;
2327
use Pimcore\Event\Model\DocumentEvent;
2428
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
@@ -30,8 +34,10 @@
3034
{
3135
public function __construct(
3236
private IndexQueueServiceInterface $indexQueueService,
37+
private IndexElementIndexServiceInterface $indexElementIndexService,
3338
private Installer $installer,
3439
private QueueMessagesDispatcher $queueMessagesDispatcher,
40+
private RuntimeCacheResolverInterface $runtimeCacheResolver,
3541
private SynchronousProcessingServiceInterface $synchronousProcessing,
3642
private SynchronousProcessingRelatedIdsServiceInterface $synchronousProcessingRelatedIds
3743
) {
@@ -40,13 +46,24 @@ public function __construct(
4046
public static function getSubscribedEvents(): array
4147
{
4248
return [
49+
DocumentEvents::POST_ADD => 'addDocument',
4350
DocumentEvents::POST_UPDATE=> 'updateDocument',
44-
DocumentEvents::POST_ADD => 'updateDocument',
4551
DocumentEvents::POST_DELETE => 'deleteDocument',
4652
];
4753
}
4854

55+
public function addDocument(DocumentEvent $event): void
56+
{
57+
$this->updateData($event);
58+
}
59+
4960
public function updateDocument(DocumentEvent $event): void
61+
{
62+
$this->indexElementIndexService->updateSiblings($event->getDocument(), ElementType::DOCUMENT->value);
63+
$this->updateData($event);
64+
}
65+
66+
public function deleteDocument(DocumentEvent $event): void
5067
{
5168
if (!$this->installer->isInstalled()) {
5269
return;
@@ -55,28 +72,33 @@ public function updateDocument(DocumentEvent $event): void
5572
$this->indexQueueService
5673
->updateIndexQueue(
5774
element: $event->getDocument(),
58-
operation: IndexQueueOperation::UPDATE->value,
59-
processSynchronously: $this->synchronousProcessing->isEnabled(),
60-
enqueueRelatedItemsAsync: $this->synchronousProcessingRelatedIds->isEnabled() === false
75+
operation: IndexQueueOperation::DELETE->value,
76+
processSynchronously: $this->synchronousProcessing->isEnabled()
6177
)
6278
->commit();
63-
6479
$this->queueMessagesDispatcher->dispatchQueueMessages();
6580
}
6681

67-
public function deleteDocument(DocumentEvent $event): void
82+
private function updateData(DocumentEvent $event): void
6883
{
6984
if (!$this->installer->isInstalled()) {
7085
return;
7186
}
72-
7387
$this->indexQueueService
7488
->updateIndexQueue(
7589
element: $event->getDocument(),
76-
operation: IndexQueueOperation::DELETE->value,
77-
processSynchronously: $this->synchronousProcessing->isEnabled()
90+
operation: IndexQueueOperation::UPDATE->value,
91+
processSynchronously: $this->synchronousProcessing->isEnabled(),
92+
enqueueRelatedItemsAsync: $this->synchronousProcessingRelatedIds->isEnabled() === false
7893
)
7994
->commit();
95+
8096
$this->queueMessagesDispatcher->dispatchQueueMessages();
97+
98+
//clear runtime cache for this object
99+
$cacheKey = SearchHelper::DOCUMENT_SEARCH . '_' . $event->getDocument()->getId();
100+
if ($this->runtimeCacheResolver->isRegistered($cacheKey)) {
101+
$this->runtimeCacheResolver->set($cacheKey, null);
102+
}
81103
}
82104
}

src/SearchIndexAdapter/BulkOperationServiceInterface.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ public function add(
2727
bool $upsert = true
2828
): void;
2929

30+
public function addUpdate(
31+
string $indexName,
32+
int $id,
33+
array $updateData
34+
): void;
35+
3036
public function addDeletion(
3137
string $indexName,
3238
int $id

src/SearchIndexAdapter/DefaultSearch/BulkOperationService.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,23 @@ public function add(
5353
$this->bulkOperationData[] = $indexData;
5454
}
5555

56+
public function addUpdate(
57+
string $indexName,
58+
int $id,
59+
array $updateData
60+
): void {
61+
$this->bulkOperationData[] = [
62+
'update' => [
63+
'_index' => $indexName,
64+
'_id' => $id,
65+
],
66+
];
67+
68+
$this->bulkOperationData[] = [
69+
'doc' => $updateData,
70+
];
71+
}
72+
5673
public function addDeletion(
5774
string $indexName,
5875
int $id

src/Service/Search/SearchService/Asset/AssetSearchService.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ public function byId(
105105

106106
try {
107107
$searchResult = $this->runtimeCacheResolver->load($cacheKey);
108+
if ($searchResult === null) {
109+
$searchResult = $this->searchAssetById($id, $user);
110+
}
108111
} catch (Exception) {
109112
$searchResult = $this->searchAssetById($id, $user);
110113
}

0 commit comments

Comments
 (0)