Skip to content
2 changes: 1 addition & 1 deletion .github/ci/files/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"pimcore/generic-data-index-bundle": "@dev"
},
"require-dev": {
"codeception/codeception": "^5.0.10",
"codeception/codeception": "^5.3.2",
"codeception/phpunit-wrapper": "^9",
"codeception/module-asserts": "^2",
"codeception/module-symfony": "^3.1.1",
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/elastic-search-codeception.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ jobs:

steps:
- name: "Checkout code"
uses: "actions/checkout@v2"
uses: "actions/checkout@v4"
with:
path: "bundles/pimcore/generic-data-index-bundle"

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/open-search-codeception.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ jobs:

steps:
- name: "Checkout code"
uses: "actions/checkout@v2"
uses: "actions/checkout@v4"
with:
path: "bundles/pimcore/generic-data-index-bundle"

Expand Down
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@
},
"require-dev": {
"roave/security-advisories": "dev-latest",
"codeception/codeception": "^5.0.10",
"codeception/codeception": "^5.3.2",
"codeception/phpunit-wrapper": "^9",
"codeception/module-asserts": "^2",
"codeception/module-symfony": "^3.1.1",
"phpstan/phpstan": "^1.10.5",
"phpstan/phpstan": "1.12.15",
"phpstan/phpstan-symfony": "^1.2.20",
"phpunit/phpunit": "10.2.7",
"nyholm/psr7": "^1",
Expand Down
3 changes: 3 additions & 0 deletions config/services/search/index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ services:
Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexEntityServiceInterface:
class: Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexEntityService

Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexElementIndexServiceInterface:
class: Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexElementIndexService

Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexUpdateServiceInterface:
class: Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexUpdateService

Expand Down
75 changes: 51 additions & 24 deletions src/EventSubscriber/DataObjectIndexUpdateSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,20 @@

namespace Pimcore\Bundle\GenericDataIndexBundle\EventSubscriber;

use Pimcore\Bundle\GenericDataIndexBundle\Enum\SearchIndex\ElementType;
use Pimcore\Bundle\GenericDataIndexBundle\Enum\SearchIndex\IndexQueueOperation;
use Pimcore\Bundle\GenericDataIndexBundle\Installer;
use Pimcore\Bundle\GenericDataIndexBundle\Service\Search\SearchService\DataObject\SearchHelper;
use Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexElementIndexServiceInterface;
use Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexQueue\QueueMessagesDispatcher;
use Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexQueue\SynchronousProcessingRelatedIdsServiceInterface;
use Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexQueue\SynchronousProcessingServiceInterface;
use Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexQueueServiceInterface;
use Pimcore\Bundle\GenericDataIndexBundle\Traits\LoggerAwareTrait;
use Pimcore\Bundle\StaticResolverBundle\Lib\Cache\RuntimeCacheResolverInterface;
use Pimcore\Event\DataObjectEvents;
use Pimcore\Event\Model\DataObjectEvent;
use Pimcore\Model\DataObject\AbstractObject;
use Pimcore\Model\DataObject\Service;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

Expand All @@ -35,7 +40,9 @@ final class DataObjectIndexUpdateSubscriber implements EventSubscriberInterface
public function __construct(
private readonly Installer $installer,
private readonly IndexQueueServiceInterface $indexQueueService,
private readonly IndexElementIndexServiceInterface $indexElementIndexService,
private readonly QueueMessagesDispatcher $queueMessagesDispatcher,
private readonly RuntimeCacheResolverInterface $runtimeCacheResolver,
private readonly SynchronousProcessingServiceInterface $synchronousProcessing,
private readonly SynchronousProcessingRelatedIdsServiceInterface $synchronousProcessingRelatedIds
) {
Expand All @@ -44,57 +51,77 @@ public function __construct(
public static function getSubscribedEvents(): array
{
return [
DataObjectEvents::POST_ADD => 'addDataObject',
DataObjectEvents::POST_UPDATE => 'updateDataObject',
DataObjectEvents::POST_ADD => 'updateDataObject',
DataObjectEvents::POST_DELETE => 'deleteDataObject',
];
}

public function addDataObject(DataObjectEvent $event): void
{
$this->updateData($event);
}

public function updateDataObject(DataObjectEvent $event): void
{
if (!$this->installer->isInstalled()) {
return;
$this->indexElementIndexService->updateSiblings($event->getObject(), ElementType::DATA_OBJECT->value);
if ($event->getObject()->getChildrenSortBy() === AbstractObject::OBJECT_CHILDREN_SORT_BY_INDEX) {
$this->indexElementIndexService->resetChildrenIndexBy($event->getObject());
}
$this->updateData($event);
}

//do not update index when auto save or only saving version
if (
($event->hasArgument('isAutoSave') && $event->getArgument('isAutoSave')) ||
($event->hasArgument('saveVersionOnly') && $event->getArgument('saveVersionOnly'))
) {
public function deleteDataObject(DataObjectEvent $event): void
{
if (!$this->installer->isInstalled()) {
return;
}

$dataObject = $event->getObject();
Service::useInheritedValues(true, fn () =>
$this->indexQueueService
->updateIndexQueue(
$dataObject,
IndexQueueOperation::UPDATE->value,
$this->synchronousProcessing->isEnabled(),
$dataObject->hasChildren(includingUnpublished: true),
$this->synchronousProcessingRelatedIds->isEnabled() === false
)
->commit()
);

$this->indexQueueService
->updateIndexQueue(
$dataObject,
IndexQueueOperation::DELETE->value,
$this->synchronousProcessing->isEnabled(),
$dataObject->hasChildren(includingUnpublished: true)
)
->commit();
$this->queueMessagesDispatcher->dispatchQueueMessages();
}

public function deleteDataObject(DataObjectEvent $event): void
private function updateData(DataObjectEvent $event): void
{
if (!$this->installer->isInstalled()) {
return;
}

//do not update index when auto save or only saving a version
if (
($event->hasArgument('isAutoSave') && $event->getArgument('isAutoSave')) ||
($event->hasArgument('saveVersionOnly') && $event->getArgument('saveVersionOnly'))
) {
return;
}

$dataObject = $event->getObject();
Service::useInheritedValues(true, fn () =>
$this->indexQueueService
->updateIndexQueue(
$dataObject,
IndexQueueOperation::DELETE->value,
IndexQueueOperation::UPDATE->value,
$this->synchronousProcessing->isEnabled(),
$dataObject->hasChildren(includingUnpublished: true)
$dataObject->hasChildren(includingUnpublished: true),
$this->synchronousProcessingRelatedIds->isEnabled() === false
)
->commit();
->commit()
);

$this->queueMessagesDispatcher->dispatchQueueMessages();

//clear runtime cache for this object
$cacheKey = SearchHelper::OBJECT_SEARCH . '_' . $event->getObject()->getId();
if ($this->runtimeCacheResolver->isRegistered($cacheKey)) {
$this->runtimeCacheResolver->set($cacheKey, null);
}
}
}
40 changes: 31 additions & 9 deletions src/EventSubscriber/DocumentIndexUpdateSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,16 @@

namespace Pimcore\Bundle\GenericDataIndexBundle\EventSubscriber;

use Pimcore\Bundle\GenericDataIndexBundle\Enum\SearchIndex\ElementType;
use Pimcore\Bundle\GenericDataIndexBundle\Enum\SearchIndex\IndexQueueOperation;
use Pimcore\Bundle\GenericDataIndexBundle\Installer;
use Pimcore\Bundle\GenericDataIndexBundle\Service\Search\SearchService\Document\SearchHelper;
use Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexElementIndexServiceInterface;
use Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexQueue\QueueMessagesDispatcher;
use Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexQueue\SynchronousProcessingRelatedIdsServiceInterface;
use Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexQueue\SynchronousProcessingServiceInterface;
use Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexQueueServiceInterface;
use Pimcore\Bundle\StaticResolverBundle\Lib\Cache\RuntimeCacheResolverInterface;
use Pimcore\Event\DocumentEvents;
use Pimcore\Event\Model\DocumentEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
Expand All @@ -30,8 +34,10 @@
{
public function __construct(
private IndexQueueServiceInterface $indexQueueService,
private IndexElementIndexServiceInterface $indexElementIndexService,
private Installer $installer,
private QueueMessagesDispatcher $queueMessagesDispatcher,
private RuntimeCacheResolverInterface $runtimeCacheResolver,
private SynchronousProcessingServiceInterface $synchronousProcessing,
private SynchronousProcessingRelatedIdsServiceInterface $synchronousProcessingRelatedIds
) {
Expand All @@ -40,13 +46,24 @@ public function __construct(
public static function getSubscribedEvents(): array
{
return [
DocumentEvents::POST_ADD => 'addDocument',
DocumentEvents::POST_UPDATE=> 'updateDocument',
DocumentEvents::POST_ADD => 'updateDocument',
DocumentEvents::POST_DELETE => 'deleteDocument',
];
}

public function addDocument(DocumentEvent $event): void
{
$this->updateData($event);
}

public function updateDocument(DocumentEvent $event): void
{
$this->indexElementIndexService->updateSiblings($event->getDocument(), ElementType::DOCUMENT->value);
$this->updateData($event);
}

public function deleteDocument(DocumentEvent $event): void
{
if (!$this->installer->isInstalled()) {
return;
Expand All @@ -55,28 +72,33 @@ public function updateDocument(DocumentEvent $event): void
$this->indexQueueService
->updateIndexQueue(
element: $event->getDocument(),
operation: IndexQueueOperation::UPDATE->value,
processSynchronously: $this->synchronousProcessing->isEnabled(),
enqueueRelatedItemsAsync: $this->synchronousProcessingRelatedIds->isEnabled() === false
operation: IndexQueueOperation::DELETE->value,
processSynchronously: $this->synchronousProcessing->isEnabled()
)
->commit();

$this->queueMessagesDispatcher->dispatchQueueMessages();
}

public function deleteDocument(DocumentEvent $event): void
private function updateData(DocumentEvent $event): void
{
if (!$this->installer->isInstalled()) {
return;
}

$this->indexQueueService
->updateIndexQueue(
element: $event->getDocument(),
operation: IndexQueueOperation::DELETE->value,
processSynchronously: $this->synchronousProcessing->isEnabled()
operation: IndexQueueOperation::UPDATE->value,
processSynchronously: $this->synchronousProcessing->isEnabled(),
enqueueRelatedItemsAsync: $this->synchronousProcessingRelatedIds->isEnabled() === false
)
->commit();

$this->queueMessagesDispatcher->dispatchQueueMessages();

//clear runtime cache for this object
$cacheKey = SearchHelper::DOCUMENT_SEARCH . '_' . $event->getDocument()->getId();
if ($this->runtimeCacheResolver->isRegistered($cacheKey)) {
$this->runtimeCacheResolver->set($cacheKey, null);
}
}
}
6 changes: 6 additions & 0 deletions src/SearchIndexAdapter/BulkOperationServiceInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ public function add(
bool $upsert = true
): void;

public function addUpdate(
string $indexName,
int $id,
array $updateData
): void;

public function addDeletion(
string $indexName,
int $id
Expand Down
17 changes: 17 additions & 0 deletions src/SearchIndexAdapter/DefaultSearch/BulkOperationService.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,23 @@ public function add(
$this->bulkOperationData[] = $indexData;
}

public function addUpdate(
string $indexName,
int $id,
array $updateData
): void {
$this->bulkOperationData[] = [
'update' => [
'_index' => $indexName,
'_id' => $id,
],
];

$this->bulkOperationData[] = [
'doc' => $updateData,
];
}

public function addDeletion(
string $indexName,
int $id
Expand Down
3 changes: 3 additions & 0 deletions src/Service/Search/SearchService/Asset/AssetSearchService.php
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ public function byId(

try {
$searchResult = $this->runtimeCacheResolver->load($cacheKey);
if ($searchResult === null) {
$searchResult = $this->searchAssetById($id, $user);
}
} catch (Exception) {
$searchResult = $this->searchAssetById($id, $user);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ public function byId(

try {
$searchResult = $this->runtimeCacheResolver->load($cacheKey);
if ($searchResult === null) {
$searchResult = $this->searchObjectById($id, $user);
}
} catch (Exception) {
$searchResult = $this->searchObjectById($id, $user);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ public function byId(

try {
$searchResult = $this->runtimeCacheResolver->load($cacheKey);
if ($searchResult === null) {
$searchResult = $this->searchDocumentById($id, $user);
}
} catch (Exception) {
$searchResult = $this->searchDocumentById($id, $user);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,11 @@ public function search(
}
}

public function byId(ElementType $elementType, int $id, ?User $user = null): ?ElementSearchResultItemInterface
{
public function byId(
ElementType $elementType,
int $id,
?User $user = null
): ?ElementSearchResultItemInterface {
try {
return match ($elementType) {
ElementType::DOCUMENT => $this->documentSearchService->byId($id, $user),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,9 @@ public function search(
/**
* @throws ElementSearchException
*/
public function byId(ElementType $elementType, int $id, ?User $user = null): ?ElementSearchResultItemInterface;
public function byId(
ElementType $elementType,
int $id,
?User $user = null
): ?ElementSearchResultItemInterface;
}
Loading