Skip to content
This repository has been archived by the owner on Mar 3, 2023. It is now read-only.

Commit

Permalink
Merge pull request #53 from digiaonline/improve-reindex-settings
Browse files Browse the repository at this point in the history
Improve re-indexing speed
  • Loading branch information
Jalle19 committed Nov 7, 2017
2 parents bdcd741 + e0fe352 commit c796db5
Show file tree
Hide file tree
Showing 17 changed files with 376 additions and 163 deletions.
4 changes: 4 additions & 0 deletions src/Console/ApplyMigrationCommand.php
Expand Up @@ -8,6 +8,8 @@
use Nord\Lumen\Elasticsearch\Pipelines\Stages\CheckIndexExistsStage;
use Nord\Lumen\Elasticsearch\Pipelines\Stages\CreateIndexStage;
use Nord\Lumen\Elasticsearch\Pipelines\Stages\DetermineTargetVersionStage;
use Nord\Lumen\Elasticsearch\Pipelines\Stages\ReIndexStage;
use Nord\Lumen\Elasticsearch\Pipelines\Stages\StoreIndexSettingsStage;
use Nord\Lumen\Elasticsearch\Pipelines\Stages\UpdateIndexAliasStage;

/**
Expand Down Expand Up @@ -48,6 +50,8 @@ public function handle()
new DetermineTargetVersionStage(),
new CheckIndexExistsStage($this->elasticsearchService),
new CreateIndexStage($this->elasticsearchService),
new StoreIndexSettingsStage($this->elasticsearchService),
new ReIndexStage($this->elasticsearchService),
new UpdateIndexAliasStage($this->elasticsearchService),
]);

Expand Down
21 changes: 21 additions & 0 deletions src/Pipelines/Payloads/ApplyMigrationPayload.php
Expand Up @@ -19,6 +19,11 @@ class ApplyMigrationPayload extends MigrationPayload
*/
private $batchSize;

/**
* @var int
*/
private $numberOfReplicas;

/**
* ApplyMigrationPayload constructor.
*
Expand Down Expand Up @@ -71,4 +76,20 @@ public function getBatchSize()
{
return $this->batchSize;
}

/**
* @return int
*/
public function getNumberOfReplicas()
{
return $this->numberOfReplicas;
}

/**
* @param int $numberOfReplicas
*/
public function setNumberOfReplicas($numberOfReplicas)
{
$this->numberOfReplicas = $numberOfReplicas;
}
}
15 changes: 0 additions & 15 deletions src/Pipelines/Stages/CreateIndexStage.php
Expand Up @@ -37,21 +37,6 @@ public function __invoke($payload)
// Create the new index
$this->elasticsearchService->indices()->create($payload->getTargetConfiguration());

// Reindex data from the old index to the new, but only if the old index exists (not true on brand new setups)
if ($this->elasticsearchService->indices()->exists(['index' => $payload->getIndexName()])) {
$this->elasticsearchService->reindex([
'body' => [
'source' => [
'index' => $payload->getIndexName(),
'size' => $payload->getBatchSize(),
],
'dest' => [
'index' => $payload->getTargetVersionName(),
],
],
]);
}

return $payload;
}
}
61 changes: 61 additions & 0 deletions src/Pipelines/Stages/ReIndexStage.php
@@ -0,0 +1,61 @@
<?php

namespace Nord\Lumen\Elasticsearch\Pipelines\Stages;

use League\Pipeline\StageInterface;
use Nord\Lumen\Elasticsearch\Contracts\ElasticsearchServiceContract;

/**
* Class ReIndexStage
* @package Nord\Lumen\Elasticsearch\Pipelines\Stages
*/
class ReIndexStage implements StageInterface
{

/**
* @var ElasticsearchServiceContract
*/
private $elasticsearchService;

/**
* CheckIndexExistsStage constructor.
*
* @param ElasticsearchServiceContract $elasticsearchService
*/
public function __construct(ElasticsearchServiceContract $elasticsearchService)
{
$this->elasticsearchService = $elasticsearchService;
}

/**
* @inheritdoc
*/
public function __invoke($payload)
{
// Reindex data from the old index to the new, but only if the old index exists (not true on brand new setups)
if ($this->elasticsearchService->indices()->exists(['index' => $payload->getIndexName()])) {
// Temporarily change some index settings to speed up the process
$this->elasticsearchService->indices()->putSettings([
'index' => $payload->getTargetVersionName(),
'body' => [
'refresh_interval' => -1,
'number_of_replicas' => 0,
],
]);

$this->elasticsearchService->reindex([
'body' => [
'source' => [
'index' => $payload->getIndexName(),
'size' => $payload->getBatchSize(),
],
'dest' => [
'index' => $payload->getTargetVersionName(),
],
],
]);
}

return $payload;
}
}
48 changes: 48 additions & 0 deletions src/Pipelines/Stages/StoreIndexSettingsStage.php
@@ -0,0 +1,48 @@
<?php

namespace Nord\Lumen\Elasticsearch\Pipelines\Stages;

use League\Pipeline\StageInterface;
use Nord\Lumen\Elasticsearch\Contracts\ElasticsearchServiceContract;
use Nord\Lumen\Elasticsearch\Pipelines\Payloads\ApplyMigrationPayload;

/**
* Class StoreIndexSettingsStage
* @package Nord\Lumen\Elasticsearch\Pipelines\Stages
*/
class StoreIndexSettingsStage implements StageInterface
{

/**
* @var ElasticsearchServiceContract
*/
private $elasticsearchService;

/**
* CheckIndexExistsStage constructor.
*
* @param ElasticsearchServiceContract $elasticsearchService
*/
public function __construct(ElasticsearchServiceContract $elasticsearchService)
{
$this->elasticsearchService = $elasticsearchService;
}

/**
* @inheritdoc
*/
public function __invoke($payload)
{
/** @var ApplyMigrationPayload $payload */

// Store the current number_of_replicas setting value in the payload
$settings = $this->elasticsearchService->indices()->getSettings([
'index' => $payload->getTargetVersionName(),
]);

$indexSettings = $settings[$payload->getTargetVersionName()]['settings']['index'];
$payload->setNumberOfReplicas($indexSettings['number_of_replicas']);

return $payload;
}
}
9 changes: 9 additions & 0 deletions src/Pipelines/Stages/UpdateIndexAliasStage.php
Expand Up @@ -54,6 +54,15 @@ public function __invoke($payload)
}
}

// Revert temporary index settings
$indices->putSettings([
'index' => $payload->getTargetVersionName(),
'body' => [
'refresh_interval' => '1s',
'number_of_replicas' => $payload->getNumberOfReplicas(),
],
]);

// Update the alias definition
$indices->updateAliases([
'body' => [
Expand Down
4 changes: 4 additions & 0 deletions tests/Pipelines/Payloads/ApplyMigrationPayloadTest.php
Expand Up @@ -26,5 +26,9 @@ public function testGettersSetters()
$this->assertTrue(is_array($payload->getTargetConfiguration()));
$this->assertEquals('content_7', $payload->getTargetVersionName());
$this->assertEquals(100, $payload->getBatchSize());

// Test number of replicas
$payload->setNumberOfReplicas(5);
$this->assertEquals(5, $payload->getNumberOfReplicas());
}
}
45 changes: 45 additions & 0 deletions tests/Pipelines/Stages/AbstractStageTestCase.php
@@ -0,0 +1,45 @@
<?php

namespace Nord\Lumen\Elasticsearch\Tests\Pipelines\Stages;

use Elasticsearch\Namespaces\IndicesNamespace;
use Nord\Lumen\Elasticsearch\Contracts\ElasticsearchServiceContract;
use Nord\Lumen\Elasticsearch\Tests\TestCase;

/**
* Class AbstractStageTestCase
* @package Nord\Lumen\Elasticsearch\Tests\Pipelines\Stages;
*/
abstract class AbstractStageTestCase extends TestCase
{

/**
* @param array $methods
*
* @return IndicesNamespace|\PHPUnit_Framework_MockObject_MockObject
*/
protected function getMockedIndices($methods = [])
{
return $this->getMockBuilder(IndicesNamespace::class)
->disableOriginalConstructor()
->setMethods($methods)
->getMock();
}

/**
* @param IndicesNamespace|\PHPUnit_Framework_MockObject_MockObject $mockedIndices
*
* @return ElasticsearchServiceContract|\PHPUnit_Framework_MockObject_MockObject
*/
protected function getMockedSearchService($mockedIndices)
{
$searchService = $this->getMockBuilder(ElasticsearchServiceContract::class)
->setMethods(['indices'])
->getMockForAbstractClass();

$searchService->method('indices')
->willReturn($mockedIndices);

return $searchService;
}
}
24 changes: 5 additions & 19 deletions tests/Pipelines/Stages/CheckIndexExistsStageTest.php
@@ -1,44 +1,30 @@
<?php

namespace Nord\Lumen\Elasticsearch\Tests\Unit\Search\Pipelines\Stages;
namespace Nord\Lumen\Elasticsearch\Tests\Pipelines\Stages;

use Elasticsearch\Namespaces\IndicesNamespace;
use Nord\Lumen\Elasticsearch\Contracts\ElasticsearchServiceContract;
use Nord\Lumen\Elasticsearch\Pipelines\Payloads\ApplyMigrationPayload;
use Nord\Lumen\Elasticsearch\Pipelines\Stages\CheckIndexExistsStage;
use Nord\Lumen\Elasticsearch\Tests\TestCase;

/**
* Class CheckIndexExistsStageTest
* @package Nord\Lumen\Elasticsearch\Tests\Unit\Search\Pipelines\Stages
* @package Nord\Lumen\Elasticsearch\Tests\Pipelines\Stages
*/
class CheckIndexExistsStageTest extends TestCase
class CheckIndexExistsStageTest extends AbstractStageTestCase
{

/**
* @expectedException \Nord\Lumen\Elasticsearch\Exceptions\IndexExistsException
*/
public function testStage()
{
/** @var IndicesNamespace|\PHPUnit_Framework_MockObject_MockObject $indices */
$indices = $this->getMockBuilder(IndicesNamespace::class)
->disableOriginalConstructor()
->setMethods(['exists'])
->getMock();
$indices = $this->getMockedIndices(['exists']);

$indices->expects($this->once())
->method('exists')
->with(['index' => 'content_1'])
->willReturn(true);

/** @var ElasticsearchServiceContract|\PHPUnit_Framework_MockObject_MockObject $service */
$service = $this->getMockBuilder(ElasticsearchServiceContract::class)
->setMethods(['indices'])
->getMockForAbstractClass();

$service->expects($this->once())
->method('indices')
->willReturn($indices);
$service = $this->getMockedSearchService($indices);

$payload = new ApplyMigrationPayload($this->getResourcesBasePath() . '/content.php', 100);
$payload->setTargetVersionFile('1.php');
Expand Down

0 comments on commit c796db5

Please sign in to comment.