Skip to content

Commit 4799700

Browse files
committed
Add SettingsUpdater service
1 parent 5bd8b3c commit 4799700

File tree

10 files changed

+328
-113
lines changed

10 files changed

+328
-113
lines changed

config/services.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,13 @@
4444
</service>
4545
<service id="Meilisearch\Bundle\SearchService" alias="meilisearch.service" />
4646

47+
<service id="meilisearch.settings_updater" class="Meilisearch\Bundle\Services\SettingsUpdater">
48+
<argument type="service" id="meilisearch.service" />
49+
<argument type="service" id="meilisearch.client" />
50+
<argument type="service" id="event_dispatcher" />
51+
</service>
52+
<service id="Meilisearch\Bundle\Services\SettingsUpdater" alias="meilisearch.settings_updater" />
53+
4754
<service id="Meilisearch\Bundle\Command\MeilisearchClearCommand">
4855
<argument type="service" id="meilisearch.service" />
4956
<tag name="console.command" />
@@ -52,6 +59,8 @@
5259
<service id="Meilisearch\Bundle\Command\MeilisearchCreateCommand">
5360
<argument type="service" id="meilisearch.service" />
5461
<argument type="service" id="meilisearch.client" />
62+
<argument type="service" id="meilisearch.settings_updater" />
63+
<argument type="service" id="event_dispatcher" />
5564
<tag name="console.command" />
5665
</service>
5766

@@ -64,6 +73,8 @@
6473
<argument type="service" id="meilisearch.service" />
6574
<argument type="service" id="doctrine" />
6675
<argument type="service" id="meilisearch.client" />
76+
<argument type="service" id="meilisearch.settings_updater" />
77+
<argument type="service" id="event_dispatcher" />
6778
<tag name="console.command" />
6879
</service>
6980

src/Command/IndexCommand.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,12 @@
1212

1313
abstract class IndexCommand extends Command
1414
{
15-
private string $prefix;
15+
protected const DEFAULT_RESPONSE_TIMEOUT = 5000;
16+
1617
protected SearchService $searchService;
1718

19+
private string $prefix;
20+
1821
public function __construct(SearchService $searchService)
1922
{
2023
$this->searchService = $searchService;

src/Command/MeilisearchCreateCommand.php

Lines changed: 53 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,30 @@
55
namespace Meilisearch\Bundle\Command;
66

77
use Meilisearch\Bundle\Collection;
8-
use Meilisearch\Bundle\Exception\InvalidSettingName;
9-
use Meilisearch\Bundle\Exception\TaskException;
8+
use Meilisearch\Bundle\EventListener\ConsoleOutputSubscriber;
109
use Meilisearch\Bundle\Model\Aggregator;
1110
use Meilisearch\Bundle\SearchService;
12-
use Meilisearch\Bundle\SettingsProvider;
11+
use Meilisearch\Bundle\Services\SettingsUpdater;
1312
use Meilisearch\Client;
1413
use Symfony\Component\Console\Input\InputInterface;
1514
use Symfony\Component\Console\Input\InputOption;
1615
use Symfony\Component\Console\Output\OutputInterface;
16+
use Symfony\Component\Console\Style\SymfonyStyle;
17+
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
1718

1819
final class MeilisearchCreateCommand extends IndexCommand
1920
{
2021
private Client $searchClient;
22+
private SettingsUpdater $settingsUpdater;
23+
private EventDispatcherInterface $eventDispatcher;
2124

22-
public function __construct(SearchService $searchService, Client $searchClient)
25+
public function __construct(SearchService $searchService, Client $searchClient, SettingsUpdater $settingsUpdater, EventDispatcherInterface $eventDispatcher)
2326
{
2427
parent::__construct($searchService);
2528

2629
$this->searchClient = $searchClient;
30+
$this->settingsUpdater = $settingsUpdater;
31+
$this->eventDispatcher = $eventDispatcher;
2732
}
2833

2934
public static function getDefaultName(): string
@@ -40,33 +45,32 @@ protected function configure(): void
4045
{
4146
$this
4247
->setDescription(self::getDefaultDescription())
43-
->addOption('indices', 'i', InputOption::VALUE_OPTIONAL, 'Comma-separated list of index names');
44-
}
45-
46-
private function entitiesToIndex($indexes): array
47-
{
48-
foreach ($indexes as $key => $index) {
49-
$entityClassName = $index['class'];
50-
if (is_subclass_of($entityClassName, Aggregator::class)) {
51-
$indexes->forget($key);
52-
53-
$indexes = new Collection(array_merge(
54-
$indexes->all(),
55-
array_map(
56-
static fn ($entity) => ['name' => $index['name'], 'class' => $entity],
57-
$entityClassName::getEntities()
58-
)
59-
));
60-
}
61-
}
62-
63-
return array_unique($indexes->all(), SORT_REGULAR);
48+
->addOption('indices', 'i', InputOption::VALUE_OPTIONAL, 'Comma-separated list of index names')
49+
->addOption(
50+
'update-settings',
51+
null,
52+
InputOption::VALUE_NEGATABLE,
53+
'Update settings related to indices to the search engine',
54+
true
55+
)
56+
->addOption(
57+
'response-timeout',
58+
't',
59+
InputOption::VALUE_REQUIRED,
60+
'Timeout (in ms) to get response from the search engine',
61+
self::DEFAULT_RESPONSE_TIMEOUT
62+
)
63+
;
6464
}
6565

6666
protected function execute(InputInterface $input, OutputInterface $output): int
6767
{
68+
$this->eventDispatcher->addSubscriber(new ConsoleOutputSubscriber(new SymfonyStyle($input, $output)));
69+
6870
$indexes = $this->getEntitiesFromArgs($input, $output);
6971
$entitiesToIndex = $this->entitiesToIndex($indexes);
72+
$updateSettings = $input->getOption('update-settings');
73+
$responseTimeout = ((int) $input->getOption('response-timeout')) ?: self::DEFAULT_RESPONSE_TIMEOUT;
7074

7175
/** @var array $index */
7276
foreach ($entitiesToIndex as $index) {
@@ -79,41 +83,38 @@ protected function execute(InputInterface $input, OutputInterface $output): int
7983
$output->writeln('<info>Creating index '.$index['name'].' for '.$entityClassName.'</info>');
8084

8185
$task = $this->searchClient->createIndex($index['name']);
82-
$this->searchClient->waitForTask($task['taskUid']);
83-
$indexInstance = $this->searchClient->index($index['name']);
86+
$this->searchClient->waitForTask($task['taskUid'], $responseTimeout);
8487

85-
if (isset($index['settings']) && is_array($index['settings'])) {
86-
foreach ($index['settings'] as $variable => $value) {
87-
$method = sprintf('update%s', ucfirst($variable));
88+
if ($updateSettings) {
89+
$this->settingsUpdater->update($index['name'], $responseTimeout);
90+
}
91+
}
8892

89-
if (!method_exists($indexInstance, $method)) {
90-
throw new InvalidSettingName(sprintf('Invalid setting name: "%s"', $variable));
91-
}
93+
$output->writeln('<info>Done!</info>');
9294

93-
if (isset($value['_service']) && $value['_service'] instanceof SettingsProvider) {
94-
$value = $value['_service']();
95-
} elseif ('distinctAttribute' === $variable && is_array($value)) {
96-
$value = $value[0] ?? null;
97-
}
95+
return 0;
96+
}
9897

99-
// Update
100-
$task = $indexInstance->{$method}($value);
98+
private function entitiesToIndex($indexes): array
99+
{
100+
foreach ($indexes as $key => $index) {
101+
$entityClassName = $index['class'];
101102

102-
// Get task information using uid
103-
$indexInstance->waitForTask($task['taskUid']);
104-
$task = $indexInstance->getTask($task['taskUid']);
103+
if (!is_subclass_of($entityClassName, Aggregator::class)) {
104+
continue;
105+
}
105106

106-
if ('failed' === $task['status']) {
107-
throw new TaskException($task['error']);
108-
}
107+
$indexes->forget($key);
109108

110-
$output->writeln('<info>Settings updated of "'.$index['name'].'".</info>');
111-
}
112-
}
109+
$indexes = new Collection(array_merge(
110+
$indexes->all(),
111+
array_map(
112+
static fn ($entity) => ['name' => $index['name'], 'prefixed_name' => $index['prefixed_name'], 'class' => $entity],
113+
$entityClassName::getEntities()
114+
)
115+
));
113116
}
114117

115-
$output->writeln('<info>Done!</info>');
116-
117-
return 0;
118+
return array_unique($indexes->all(), SORT_REGULAR);
118119
}
119120
}

src/Command/MeilisearchImportCommand.php

Lines changed: 44 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -6,30 +6,34 @@
66

77
use Doctrine\Persistence\ManagerRegistry;
88
use Meilisearch\Bundle\Collection;
9-
use Meilisearch\Bundle\Exception\InvalidSettingName;
9+
use Meilisearch\Bundle\EventListener\ConsoleOutputSubscriber;
1010
use Meilisearch\Bundle\Exception\TaskException;
1111
use Meilisearch\Bundle\Model\Aggregator;
1212
use Meilisearch\Bundle\SearchService;
13-
use Meilisearch\Bundle\SettingsProvider;
13+
use Meilisearch\Bundle\Services\SettingsUpdater;
1414
use Meilisearch\Client;
1515
use Meilisearch\Exceptions\TimeOutException;
1616
use Symfony\Component\Console\Input\InputInterface;
1717
use Symfony\Component\Console\Input\InputOption;
1818
use Symfony\Component\Console\Output\OutputInterface;
19+
use Symfony\Component\Console\Style\SymfonyStyle;
20+
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
1921

2022
final class MeilisearchImportCommand extends IndexCommand
2123
{
22-
private const DEFAULT_RESPONSE_TIMEOUT = 5000;
24+
private Client $searchClient;
25+
private ManagerRegistry $managerRegistry;
26+
private SettingsUpdater $settingsUpdater;
27+
private EventDispatcherInterface $eventDispatcher;
2328

24-
protected Client $searchClient;
25-
protected ManagerRegistry $managerRegistry;
26-
27-
public function __construct(SearchService $searchService, ManagerRegistry $managerRegistry, Client $searchClient)
29+
public function __construct(SearchService $searchService, ManagerRegistry $managerRegistry, Client $searchClient, SettingsUpdater $settingsUpdater, EventDispatcherInterface $eventDispatcher)
2830
{
2931
parent::__construct($searchService);
3032

3133
$this->managerRegistry = $managerRegistry;
3234
$this->searchClient = $searchClient;
35+
$this->settingsUpdater = $settingsUpdater;
36+
$this->eventDispatcher = $eventDispatcher;
3337
}
3438

3539
public static function getDefaultName(): string
@@ -50,8 +54,9 @@ protected function configure(): void
5054
->addOption(
5155
'update-settings',
5256
null,
53-
InputOption::VALUE_NONE,
54-
'Update settings related to indices to the search engine'
57+
InputOption::VALUE_NEGATABLE,
58+
'Update settings related to indices to the search engine',
59+
true
5560
)
5661
->addOption('batch-size', null, InputOption::VALUE_REQUIRED)
5762
->addOption(
@@ -73,32 +78,20 @@ protected function configure(): void
7378

7479
protected function execute(InputInterface $input, OutputInterface $output): int
7580
{
81+
$this->eventDispatcher->addSubscriber(new ConsoleOutputSubscriber(new SymfonyStyle($input, $output)));
82+
7683
$indexes = $this->getEntitiesFromArgs($input, $output);
84+
$entitiesToIndex = $this->entitiesToIndex($indexes);
7785
$config = $this->searchService->getConfiguration();
78-
79-
foreach ($indexes as $key => $index) {
80-
$entityClassName = $index['class'];
81-
if (is_subclass_of($entityClassName, Aggregator::class)) {
82-
$indexes->forget($key);
83-
84-
$indexes = new Collection(array_merge(
85-
$indexes->all(),
86-
array_map(
87-
fn ($entity) => ['class' => $entity],
88-
$entityClassName::getEntities()
89-
)
90-
));
91-
}
92-
}
93-
94-
$entitiesToIndex = array_unique($indexes->all(), SORT_REGULAR);
86+
$updateSettings = $input->getOption('update-settings');
9587
$batchSize = $input->getOption('batch-size') ?? '';
9688
$batchSize = ctype_digit($batchSize) ? (int) $batchSize : $config->get('batchSize');
9789
$responseTimeout = ((int) $input->getOption('response-timeout')) ?: self::DEFAULT_RESPONSE_TIMEOUT;
9890

9991
/** @var array $index */
10092
foreach ($entitiesToIndex as $index) {
10193
$entityClassName = $index['class'];
94+
10295
if (!$this->searchService->isSearchable($entityClassName)) {
10396
continue;
10497
}
@@ -148,36 +141,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int
148141
);
149142
}
150143

151-
if (isset($index['settings'])
152-
&& is_array($index['settings'])
153-
&& count($index['settings']) > 0) {
154-
$indexInstance = $this->searchClient->index($index['name']);
155-
foreach ($index['settings'] as $variable => $value) {
156-
$method = sprintf('update%s', ucfirst($variable));
157-
158-
if (!method_exists($indexInstance, $method)) {
159-
throw new InvalidSettingName(sprintf('Invalid setting name: "%s"', $variable));
160-
}
161-
162-
if (isset($value['_service']) && $value['_service'] instanceof SettingsProvider) {
163-
$value = $value['_service']();
164-
} elseif ('distinctAttribute' === $variable && is_array($value)) {
165-
$value = $value[0] ?? null;
166-
}
167-
168-
// Update
169-
$task = $indexInstance->{$method}($value);
170-
171-
// Get task information using uid
172-
$indexInstance->waitForTask($task['taskUid'], $responseTimeout);
173-
$task = $indexInstance->getTask($task['taskUid']);
174-
175-
if ('failed' === $task['status']) {
176-
throw new TaskException($task['error']);
177-
}
178-
179-
$output->writeln('<info>Settings updated of "'.$index['name'].'".</info>');
180-
}
144+
if ($updateSettings) {
145+
$this->settingsUpdater->update($index['prefixed_name'], $responseTimeout);
181146
}
182147

183148
++$page;
@@ -220,4 +185,27 @@ private function formatIndexingResponse(array $batch, int $responseTimeout): arr
220185

221186
return $formattedResponse;
222187
}
188+
189+
private function entitiesToIndex($indexes): array
190+
{
191+
foreach ($indexes as $key => $index) {
192+
$entityClassName = $index['class'];
193+
194+
if (!is_subclass_of($entityClassName, Aggregator::class)) {
195+
continue;
196+
}
197+
198+
$indexes->forget($key);
199+
200+
$indexes = new Collection(array_merge(
201+
$indexes->all(),
202+
array_map(
203+
static fn ($entity) => ['name' => $index['name'], 'prefixed_name' => $index['prefixed_name'], 'class' => $entity],
204+
$entityClassName::getEntities()
205+
)
206+
));
207+
}
208+
209+
return array_unique($indexes->all(), SORT_REGULAR);
210+
}
223211
}

src/DependencyInjection/MeilisearchExtension.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ public function load(array $configs, ContainerBuilder $container): void
2626
}
2727

2828
foreach ($config['indices'] as $index => $indice) {
29+
$config['indices'][$index]['prefixed_name'] = $config['prefix'].$indice['name'];
2930
$config['indices'][$index]['settings'] = $this->findReferences($config['indices'][$index]['settings']);
3031
}
3132

0 commit comments

Comments
 (0)