-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# Index Queue options | ||
|
||
The indexing queue considers the following options: | ||
|
||
- **worker_count** (default 1): number of messenger workers to process the queue | ||
- **min_batch_size** (default 5): minimum number of items to process in one batch (when using multiple workers) | ||
- **max_batch_size** (default 400): maximum number of items to process in one batch | ||
|
||
Sample configuration: | ||
|
||
```yaml | ||
pimcore_generic_data_index: | ||
index_service: | ||
queue_settings: | ||
worker_count: 1 | ||
min_batch_size: 5 | ||
max_batch_size: 400 | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
<?php | ||
declare(strict_types=1); | ||
|
||
/** | ||
* Pimcore | ||
* | ||
* This source file is available under following license: | ||
* - Pimcore Commercial License (PCL) | ||
* | ||
* @copyright Copyright (c) Pimcore GmbH (http://www.pimcore.org) | ||
* @license http://www.pimcore.org/license PCL | ||
*/ | ||
|
||
namespace Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexQueue; | ||
|
||
use Doctrine\DBAL\Exception; | ||
use Pimcore\Bundle\GenericDataIndexBundle\Message\IndexUpdateQueueMessage; | ||
use Pimcore\Bundle\GenericDataIndexBundle\Repository\IndexQueueRepository; | ||
use Symfony\Component\Messenger\MessageBusInterface; | ||
|
||
/** | ||
* @internal | ||
*/ | ||
final class QueueMessageService implements QueueMessageServiceInterface | ||
{ | ||
public function __construct( | ||
private readonly IndexQueueRepository $indexQueueRepository, | ||
private readonly MessageBusInterface $messageBus | ||
) { | ||
} | ||
|
||
/** | ||
* @throws Exception | ||
*/ | ||
public function handleMessage( | ||
int $entriesCount, | ||
int $maxBatchSize, | ||
array $entries | ||
): void | ||
{ | ||
if ($entriesCount > $maxBatchSize) { | ||
$chunks = array_chunk($entries, $maxBatchSize); | ||
foreach($chunks as $chunk) { | ||
$this->dispatchMessage($chunk, $maxBatchSize); | ||
} | ||
} else { | ||
$this->dispatchMessage($entries, $maxBatchSize); | ||
} | ||
} | ||
|
||
public function getMaxBatchSize( | ||
int $entriesCount, | ||
int $workerCount, | ||
int $minBatchSize, | ||
int $maxBatchSize | ||
): int | ||
{ | ||
if ($workerCount === 1) { | ||
return $maxBatchSize; | ||
} | ||
|
||
$itemsPerWorker = (int)floor($entriesCount / $workerCount); | ||
|
||
return match (true) { | ||
$itemsPerWorker < $minBatchSize => $minBatchSize, | ||
$itemsPerWorker < $maxBatchSize => $itemsPerWorker, | ||
default => $maxBatchSize, | ||
}; | ||
} | ||
|
||
/** | ||
* @throws Exception | ||
*/ | ||
private function dispatchMessage(array $items, int $limit): void | ||
{ | ||
$this->messageBus->dispatch(new IndexUpdateQueueMessage($items)); | ||
$this->indexQueueRepository->dispatchItems($limit); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
<?php | ||
declare(strict_types=1); | ||
|
||
/** | ||
* Pimcore | ||
* | ||
* This source file is available under following license: | ||
* - Pimcore Commercial License (PCL) | ||
* | ||
* @copyright Copyright (c) Pimcore GmbH (http://www.pimcore.org) | ||
* @license http://www.pimcore.org/license PCL | ||
*/ | ||
|
||
namespace Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexQueue; | ||
|
||
use Doctrine\DBAL\Exception; | ||
Check notice on line 16 in src/Service/SearchIndex/IndexQueue/QueueMessageServiceInterface.php GitHub Actions / Qodana for PHPUnused import
Check notice on line 16 in src/Service/SearchIndex/IndexQueue/QueueMessageServiceInterface.php GitHub Actions / Qodana for PHPUnused import
|
||
use Pimcore\Bundle\GenericDataIndexBundle\Exception\EnqueueAssetsException; | ||
Check notice on line 17 in src/Service/SearchIndex/IndexQueue/QueueMessageServiceInterface.php GitHub Actions / Qodana for PHPUnused import
Check notice on line 17 in src/Service/SearchIndex/IndexQueue/QueueMessageServiceInterface.php GitHub Actions / Qodana for PHPUnused import
|
||
use Pimcore\Model\DataObject\ClassDefinition; | ||
Check notice on line 18 in src/Service/SearchIndex/IndexQueue/QueueMessageServiceInterface.php GitHub Actions / Qodana for PHPUnused import
Check notice on line 18 in src/Service/SearchIndex/IndexQueue/QueueMessageServiceInterface.php GitHub Actions / Qodana for PHPUnused import
|
||
use Pimcore\Model\Element\ElementInterface; | ||
Check notice on line 19 in src/Service/SearchIndex/IndexQueue/QueueMessageServiceInterface.php GitHub Actions / Qodana for PHPUnused import
Check notice on line 19 in src/Service/SearchIndex/IndexQueue/QueueMessageServiceInterface.php GitHub Actions / Qodana for PHPUnused import
|
||
use Pimcore\Model\Element\Tag; | ||
Check notice on line 20 in src/Service/SearchIndex/IndexQueue/QueueMessageServiceInterface.php GitHub Actions / Qodana for PHPUnused import
Check notice on line 20 in src/Service/SearchIndex/IndexQueue/QueueMessageServiceInterface.php GitHub Actions / Qodana for PHPUnused import
|
||
|
||
/** | ||
* @internal | ||
*/ | ||
interface QueueMessageServiceInterface | ||
{ | ||
public function handleMessage( | ||
int $entriesCount, | ||
int $maxBatchSize, | ||
array $entries | ||
): void; | ||
|
||
public function getMaxBatchSize( | ||
int $entriesCount, | ||
int $workerCount, | ||
int $minBatchSize, | ||
int $maxBatchSize | ||
): int; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
<?php | ||
declare(strict_types=1); | ||
|
||
/** | ||
* Pimcore | ||
* | ||
* This source file is available under following license: | ||
* - Pimcore Commercial License (PCL) | ||
* | ||
* @copyright Copyright (c) Pimcore GmbH (http://www.pimcore.org) | ||
* @license http://www.pimcore.org/license PCL | ||
*/ | ||
|
||
namespace Pimcore\Bundle\GenericDataIndexBundle\Tests\Unit\Service\SearchIndex\IndexQueue; | ||
|
||
use Codeception\Test\Unit; | ||
use Doctrine\DBAL\Connection; | ||
use Doctrine\ORM\EntityManagerInterface; | ||
use Pimcore\Bundle\GenericDataIndexBundle\Repository\IndexQueueRepository; | ||
use Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexQueue\QueueMessageService; | ||
use Pimcore\Bundle\GenericDataIndexBundle\Service\TimeServiceInterface; | ||
use Symfony\Component\Messenger\MessageBusInterface; | ||
use Symfony\Component\Serializer\Normalizer\DenormalizableInterface; | ||
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; | ||
|
||
/** | ||
* @internal | ||
*/ | ||
final class QueueMessageServiceTest extends Unit | ||
{ | ||
private QueueMessageService $queueMessageService; | ||
|
||
public function _before(): void | ||
{ | ||
$this->queueMessageService = new QueueMessageService( | ||
$this->getEmptyQueueRepository(), | ||
$this->makeEmpty(MessageBusInterface::class) | ||
); | ||
} | ||
|
||
public function testGetMaxBatchSizeWithOneWorker(): void | ||
{ | ||
$this->assertSame( | ||
40, | ||
$this->queueMessageService->getMaxBatchSize( | ||
100, | ||
1, | ||
10, | ||
40 | ||
) | ||
); | ||
} | ||
|
||
public function testGetMaxBatchSizeWithMultipleWorkers(): void | ||
{ | ||
$this->assertSame( | ||
50, | ||
$this->queueMessageService->getMaxBatchSize( | ||
250, | ||
5, | ||
5, | ||
400 | ||
) | ||
); | ||
} | ||
|
||
public function testGetMaxBatchSizeWithOneWorkerAndFewItems(): void | ||
{ | ||
$this->assertSame( | ||
50, | ||
$this->queueMessageService->getMaxBatchSize( | ||
20, | ||
1, | ||
10, | ||
50 | ||
) | ||
); | ||
} | ||
|
||
public function testGetMaxBatchSizeWithMultipleWorkersAndFewItems(): void | ||
{ | ||
$this->assertSame( | ||
10, | ||
$this->queueMessageService->getMaxBatchSize( | ||
20, | ||
2, | ||
5, | ||
500 | ||
) | ||
); | ||
} | ||
|
||
private function getEmptyQueueRepository(): IndexQueueRepository | ||
{ | ||
return new IndexQueueRepository( | ||
$this->makeEmpty(EntityManagerInterface::class), | ||
$this->makeEmpty(TimeServiceInterface::class), | ||
$this->makeEmpty(Connection::class), | ||
$this->makeEmpty(DenormalizerInterface::class) | ||
); | ||
} | ||
} |