Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[IndexBundle] process Index Messages async #2106

Merged
merged 4 commits into from
Nov 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions config/packages/test/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ framework:
handler_id: ~
storage_id: session.storage.mock_file
name: MOCKSESSID
messenger:
transports:
coreshop_index: 'sync://'
routing:
'CoreShop\Bundle\IndexBundle\Messenger\IndexMessage': coreshop_index

monolog:
handlers:
Expand Down
1 change: 1 addition & 0 deletions src/CoreShop/Behat/Context/Setup/PimcoreClassContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use Behat\Gherkin\Node\TableNode;
use CoreShop\Behat\Service\ClassStorageInterface;
use CoreShop\Behat\Service\SharedStorageInterface;
use CoreShop\Component\Index\Model\IndexableInterface;
use CoreShop\Component\Pimcore\DataObject\BrickDefinitionUpdate;
use CoreShop\Component\Pimcore\DataObject\ClassUpdate;
use CoreShop\Component\Pimcore\DataObject\ClassUpdateInterface;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,75 +18,48 @@

namespace CoreShop\Bundle\IndexBundle\EventListener;

use CoreShop\Bundle\IndexBundle\Messenger\IndexMessage;
use CoreShop\Component\Index\Model\IndexableInterface;
use CoreShop\Component\Index\Service\IndexUpdaterServiceInterface;
use CoreShop\Component\Pimcore\DataObject\InheritanceHelper;
use Pimcore\Event\Model\DataObjectEvent;
use Pimcore\Event\Model\ElementEventInterface;
use Pimcore\Model\DataObject\AbstractObject;
use Pimcore\Model\DataObject\ClassDefinition;
use Symfony\Component\Messenger\MessageBusInterface;

final class IndexObjectListener
{
private array $validObjectTypes = [AbstractObject::OBJECT_TYPE_OBJECT, AbstractObject::OBJECT_TYPE_VARIANT];

public function __construct(
private IndexUpdaterServiceInterface $indexUpdaterService,
private MessageBusInterface $messageBus,
) {
}

public function onPostUpdate(ElementEventInterface $event): void
{
if ($event instanceof DataObjectEvent) {
$object = $event->getObject();
if (!$event instanceof DataObjectEvent) {
return;
}

if (!$object instanceof IndexableInterface) {
return;
}
$object = $event->getObject();

$isVersionEvent = $event->hasArgument('saveVersionOnly') && true === $event->getArgument('saveVersionOnly');
if (!$object instanceof IndexableInterface) {
return;
}

InheritanceHelper::useInheritedValues(function () use ($object, $isVersionEvent) {
$this->indexUpdaterService->updateIndices($object, $isVersionEvent);
});
$isVersionEvent = $event->hasArgument('saveVersionOnly') && true === $event->getArgument('saveVersionOnly');

$classDefinition = ClassDefinition::getById($object->getClassId());
if ($classDefinition && ($classDefinition->getAllowInherit() || $classDefinition->getAllowVariants())) {
$this->updateInheritableChildren($object, $isVersionEvent);
}
}
$this->messageBus->dispatch(new IndexMessage($object->getId(), $isVersionEvent));
}

private function updateInheritableChildren(AbstractObject $object, bool $isVersionChange): void
public function onPreDelete(ElementEventInterface $event): void
{
if (!$object->hasChildren($this->validObjectTypes)) {
if (!$event instanceof DataObjectEvent) {
return;
}

$children = $object->getChildren($this->validObjectTypes);
/** @var AbstractObject $child */
foreach ($children as $child) {
if ($child instanceof IndexableInterface && $child::class === $object::class) {
InheritanceHelper::useInheritedValues(function () use ($child, $isVersionChange) {
$this->indexUpdaterService->updateIndices($child, $isVersionChange);
});
$this->updateInheritableChildren($child, $isVersionChange);
}
}
}

public function onPostDelete(ElementEventInterface $event): void
{
if ($event instanceof DataObjectEvent) {
$object = $event->getObject();
$object = $event->getObject();

if (!$object instanceof IndexableInterface) {
return;
}

InheritanceHelper::useInheritedValues(function () use ($object) {
$this->indexUpdaterService->removeIndices($object);
});
if (!$object instanceof IndexableInterface) {
return;
}

$this->messageBus->dispatch(new IndexMessage($object->getId(), false, true));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?php

declare(strict_types=1);

/*
* CoreShop
*
* This source file is available under two different licenses:
* - GNU General Public License version 3 (GPLv3)
* - CoreShop Commercial License (CCL)
* Full copyright and license information is available in
* LICENSE.md which is distributed with this source code.
*
* @copyright Copyright (c) CoreShop GmbH (https://www.coreshop.org)
* @license https://www.coreshop.org/license GPLv3 and CCL
*
*/

namespace CoreShop\Bundle\IndexBundle\Messenger\Handler;

use CoreShop\Bundle\IndexBundle\Messenger\IndexMessage;
use CoreShop\Component\Index\Model\IndexableInterface;
use CoreShop\Component\Index\Service\IndexUpdaterServiceInterface;
use CoreShop\Component\Pimcore\DataObject\InheritanceHelper;
use Pimcore\Model\DataObject\AbstractObject;
use Pimcore\Model\DataObject\ClassDefinition;
use Pimcore\Model\DataObject\Concrete;
use Symfony\Component\Messenger\Exception\UnrecoverableMessageHandlingException;
use Symfony\Component\Messenger\Handler\MessageHandlerInterface;
use Symfony\Component\Messenger\MessageBusInterface;

class IndexMessageHandler implements MessageHandlerInterface
{
private array $validObjectTypes = [AbstractObject::OBJECT_TYPE_OBJECT, AbstractObject::OBJECT_TYPE_VARIANT];

public function __construct(
private IndexUpdaterServiceInterface $indexUpdaterService,
private MessageBusInterface $messageBus,
) {
}

public function __invoke(IndexMessage $indexMessage)
{
$indexable = Concrete::getById($indexMessage->getIndexableId());

if (!$indexable instanceof IndexableInterface) {
throw new UnrecoverableMessageHandlingException('Indexable given does not implement IndexableInterface');
}

InheritanceHelper::useInheritedValues(function () use ($indexable, $indexMessage) {
if ($indexMessage->isDelete()) {
$this->indexUpdaterService->removeIndices($indexable);
return;
}

$this->indexUpdaterService->updateIndices($indexable, $indexMessage->isSaveVersionOnly());
});

$classDefinition = ClassDefinition::getById($indexable->getClassId());

if ($classDefinition && ($classDefinition->getAllowInherit() || $classDefinition->getAllowVariants())) {
$this->updateInheritableChildren($indexable, $indexMessage->isSaveVersionOnly());
}
}

private function updateInheritableChildren(AbstractObject $object, bool $isVersionChange): void
{
if (!$object->hasChildren($this->validObjectTypes)) {
return;
}

$children = $object->getChildren($this->validObjectTypes);

foreach ($children as $child) {
if ($child instanceof IndexableInterface && $child::class === $object::class) {
$this->messageBus->dispatch(new IndexMessage($child->getId(), $isVersionChange));
}
}
}
}
45 changes: 45 additions & 0 deletions src/CoreShop/Bundle/IndexBundle/Messenger/IndexMessage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

declare(strict_types=1);

/*
* CoreShop
*
* This source file is available under two different licenses:
* - GNU General Public License version 3 (GPLv3)
* - CoreShop Commercial License (CCL)
* Full copyright and license information is available in
* LICENSE.md which is distributed with this source code.
*
* @copyright Copyright (c) CoreShop GmbH (https://www.coreshop.org)
* @license https://www.coreshop.org/license GPLv3 and CCL
*
*/

namespace CoreShop\Bundle\IndexBundle\Messenger;

class IndexMessage
{
public function __construct(
protected int $indexableId,
protected bool $saveVersionOnly = false,
protected bool $isDelete = false,
)
{
}

public function getIndexableId(): int
{
return $this->indexableId;
}

public function isSaveVersionOnly(): bool
{
return $this->saveVersionOnly;
}

public function isDelete(): bool
{
return $this->isDelete;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
imports:
- { resource: admin.yml }
- { resource: messenger.yml }

pimcore:
objects:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
framework:
messenger:
transports:
coreshop_index:
dsn: "doctrine://default?queue_name=coreshop_index"
routing:
'CoreShop\Bundle\IndexBundle\Messenger\IndexMessage': coreshop_index
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ imports:
- { resource: services/pimcore.yml }
- { resource: services/condition_renderer.yml }
- { resource: services/order_renderer.yml }
- { resource: services/messenger.yml }

services:
_defaults:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ services:

CoreShop\Bundle\IndexBundle\EventListener\IndexObjectListener:
arguments:
- '@CoreShop\Component\Index\Service\IndexUpdaterService'
- '@messenger.default_bus'
tags:
- { name: kernel.event_listener, event: pimcore.dataobject.postAdd, method: onPostUpdate }
- { name: kernel.event_listener, event: pimcore.dataobject.postUpdate, method: onPostUpdate }
- { name: kernel.event_listener, event: pimcore.dataobject.postDelete, method: onPostDelete }
- { name: kernel.event_listener, event: pimcore.dataobject.preDelete, method: onPreDelete }

CoreShop\Bundle\IndexBundle\EventListener\UpdateIndexListener:
arguments:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
services:
_defaults:
autoconfigure: false

CoreShop\Bundle\IndexBundle\Messenger\Handler\IndexMessageHandler:
arguments:
- '@CoreShop\Component\Index\Service\IndexUpdaterServiceInterface'
- '@messenger.default_bus'
tags:
- { name: messenger.message_handler }