Skip to content

Commit

Permalink
Fix for correct full rebuilding of search index.
Browse files Browse the repository at this point in the history
Remove index directory after each test.
  • Loading branch information
nqxcode committed Feb 21, 2020
1 parent b1f6935 commit deaeefb
Show file tree
Hide file tree
Showing 9 changed files with 130 additions and 56 deletions.
51 changes: 25 additions & 26 deletions src/Nqxcode/LuceneSearch/Console/RebuildCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Illuminate\Console\Command;
use Nqxcode\LuceneSearch\Locker\Locker;
use Nqxcode\LuceneSearch\Search;
use Nqxcode\LuceneSearch\Support\SearchIndexRotator;
use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\NullOutput;
Expand All @@ -21,6 +22,11 @@ class RebuildCommand extends Command
*/
private $search;

/**
* @var SearchIndexRotator
*/
private $searchIndexRotator;

protected function getOptions()
{
return [
Expand All @@ -34,7 +40,7 @@ public function fire()
$this->output = new NullOutput;
}

$lockFilePath = sys_get_temp_dir() . '/laravel-lucene-search/rebuild.lock';
$lockFilePath = storage_path('laravel-lucene-search/rebuild.lock');

$locker = new Locker($lockFilePath);

Expand All @@ -44,10 +50,11 @@ public function fire()

$locker->doLocked(function () {
if ($this->option('force')) {
$this->forceRebuild();
$this->call('search:clear');
$this->rebuild();

} else {
$this->softRebuild();
$this->rebuild();
}
});
}
Expand All @@ -57,6 +64,10 @@ private function rebuild()
/** @var Search $search */
$this->search = App::make('search');

$this->searchIndexRotator = App::make('search.index.rotator');
$queue = Config::get('laravel-lucene-search::queue');
$indexPath = Config::get('laravel-lucene-search::index.path');

$modelRepositories = $this->search->config()->repositories();

if (count($modelRepositories) > 0) {
Expand All @@ -74,19 +85,21 @@ private function rebuild()
$progress = new ProgressBar($this->getOutput(), $count / $chunkCount);
$progress->start();

$modelRepository->chunk($chunkCount, function ($chunk) use ($progress) {
$queue = Config::get('laravel-lucene-search::queue');
$modelRepository->chunk($chunkCount, function ($chunk) use ($progress, $queue) {
$newIndexPath = $this->searchIndexRotator->getNewIndexPath();

if ($queue) {
Queue::push(
'Nqxcode\LuceneSearch\Job\MassUpdateSearchIndex',
[
'modelClass' => get_class($chunk[0]),
'modelKeys' => $chunk->lists($chunk[0]->getKeyName()),
'indexPath' => Config::get('laravel-lucene-search::index.path'),
'indexPath' => $newIndexPath,
],
$queue);

} else {
Config::set('laravel-lucene-search::index.path', $newIndexPath);
foreach ($chunk as $model) {
$this->search->update($model);
}
Expand All @@ -102,30 +115,16 @@ private function rebuild()
} else {
$this->error('No models found in config.php file..');
}
}

private function softRebuild()
{
$oldIndexPath = Config::get('laravel-lucene-search::index.path');
$newIndexPath = sys_get_temp_dir() . '/laravel-lucene-search/' . uniqid('index-', true);

Config::set('laravel-lucene-search::index.path', $newIndexPath);

$this->rebuild();

$this->search->destroyConnection();

File::cleanDirectory($oldIndexPath);
File::copyDirectory($newIndexPath, $oldIndexPath);
File::cleanDirectory($newIndexPath);
if ($queue) {
Queue::push('Nqxcode\LuceneSearch\Job\RotateSearchIndex', $queue);

Config::set('laravel-lucene-search::index.path', $oldIndexPath);

}
} else {
$this->searchIndexRotator->rotate();
}

private function forceRebuild()
{
$this->call('search:clear');
$this->rebuild();
Config::set('laravel-lucene-search::index.path', $indexPath);
}
}
5 changes: 4 additions & 1 deletion src/Nqxcode/LuceneSearch/Job/MassUpdateSearchIndex.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php namespace Nqxcode\LuceneSearch\Job;

use App\Models\CatalogProduct;
use Config;

/**
* Class MassUpdateSearchIndex
Expand All @@ -13,10 +14,12 @@ public function fire($job, array $jobData)
$modelKeys = $jobData['modelKeys'];
$indexPath = $jobData['indexPath'];

Config::set('laravel-lucene-search::index.path', $indexPath);

foreach ($modelKeys as $modelKey) {
$model = $modelClass::find($modelKey);
if (!is_null($model)) {
app('search')->useIndexPath($indexPath)->update($model);
app('search')->update($model);
}
}

Expand Down
18 changes: 18 additions & 0 deletions src/Nqxcode/LuceneSearch/Job/RotateSearchIndex.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php namespace Nqxcode\LuceneSearch\Job;

use File;
use Nqxcode\LuceneSearch\Support\SearchIndexRotator;

/**
* Class RotateSearchIndex
* @package Nqxcode\LuceneSearch\Job
*/
class RotateSearchIndex
{
public function fire($job, array $jobData)
{
app('search.index.rotator')->rotate();

$job->delete();
}
}
22 changes: 2 additions & 20 deletions src/Nqxcode/LuceneSearch/Search.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,6 @@ class Search
*/
protected $connection;

/**
* @var string
*/
protected $indexPath;

/**
* Get descriptor for open index.
*
Expand All @@ -43,19 +38,6 @@ public function index()
return $this->makeConnection()->getIndex();
}

/**
* Use index path for connection.
*
* @param $indexPath
* @return $this
*/
public function useIndexPath($indexPath)
{
$this->indexPath = $indexPath;

return $this;
}

/**
* Model configurator.
*
Expand Down Expand Up @@ -96,8 +78,8 @@ public function __destruct()
*/
private function makeConnection()
{
if (null === $this->connection) {
$this->connection = call_user_func($this->connectionBuilder, $this->indexPath);
if (!isset($this->connection)) {
$this->connection = call_user_func($this->connectionBuilder);
}

return $this->connection;
Expand Down
15 changes: 12 additions & 3 deletions src/Nqxcode/LuceneSearch/ServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Nqxcode\LuceneSearch\Index\Connection;
use Nqxcode\LuceneSearch\Model\Config as ModelsConfig;
use Nqxcode\LuceneSearch\Model\SearchObserver;
use Nqxcode\LuceneSearch\Support\SearchIndexRotator;
use ZendSearch\Lucene\Analysis\Analyzer\Common\Utf8Num\CaseInsensitive;
use ZendSearch\Lucene\Search\QueryParser;

Expand Down Expand Up @@ -51,9 +52,9 @@ public function register()
QueryParser::setDefaultEncoding('utf-8');

return new Search(
function ($indexPath = null) {
function () {
return new Connection(
$indexPath ?: $this->app['search.index.path'],
$this->app['search.index.path'],
$this->app->make('Nqxcode\LuceneSearch\Analyzer\Config')
);
},
Expand All @@ -73,7 +74,7 @@ function ($indexPath = null) {
);
});

$this->app->bindShared('search.index.path', function () {
$this->app->bind('search.index.path', function () {
return Config::get('laravel-lucene-search::index.path');
});

Expand All @@ -85,6 +86,14 @@ function ($indexPath = null) {
);
});

$this->app->bindShared('search.index.rotator', function () {
return new SearchIndexRotator(
$this->app['search.index.path'],
storage_path('laravel-lucene-search/index.new'),
storage_path('laravel-lucene-search/index.preview')
);
});

$this->app->bindShared('command.search.rebuild', function () {
return new Console\RebuildCommand;
});
Expand Down
40 changes: 40 additions & 0 deletions src/Nqxcode/LuceneSearch/Support/SearchIndexRotator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php namespace Nqxcode\LuceneSearch\Support;

use File;

/**
* Class SearchIndexRotator
* @package Nqxcode\LuceneSearch\Support
*/
class SearchIndexRotator
{
private $currentIndexPath;
private $newIndexPath;
private $previewIndexPath;

public function __construct($currentPath, $newPath, $previewPath)
{
$this->currentIndexPath = $currentPath;
$this->newIndexPath = $newPath;
$this->previewIndexPath = $previewPath;
}

/**
* @return mixed
*/
public function getNewIndexPath()
{
return $this->newIndexPath;
}

public function rotate()
{
File::deleteDirectory($this->previewIndexPath);

File::copyDirectory($this->currentIndexPath, $this->previewIndexPath);
File::cleanDirectory($this->currentIndexPath);

File::copyDirectory($this->newIndexPath, $this->currentIndexPath);
File::deleteDirectory($this->newIndexPath);
}
}
2 changes: 1 addition & 1 deletion src/config/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
*/
'index' => [

'path' => storage_path() . '/lucene-search/index',
'path' => storage_path('lucene-search/index'),

'models' => [
// Add models descriptions here.
Expand Down
17 changes: 15 additions & 2 deletions tests/functional/BaseTestCase.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?php namespace tests\functional;

use File;
use tests\TestCase;
use Config;

Expand All @@ -9,9 +10,12 @@
*/
abstract class BaseTestCase extends TestCase
{
private $indexPath;

public function setUp()
{
parent::setUp();

$this->configure();

$artisan = $this->app->make('artisan');
Expand All @@ -23,10 +27,19 @@ public function setUp()
$artisan->call('search:rebuild', ['--force' => true]);
}

public function tearDown()
{
parent::tearDown();

app('search')->destroyConnection();

File::deleteDirectory($this->indexPath);
}

protected function configure()
{
Config::set('laravel-lucene-search::index.path',
sys_get_temp_dir() . '/laravel-lucene-search/index' . uniqid('index-', true));
$this->indexPath = sys_get_temp_dir() . '/laravel-lucene-search/' . uniqid('index-', true);
Config::set('laravel-lucene-search::index.path', $this->indexPath);
Config::set(
'laravel-lucene-search::index.models',
[
Expand Down
16 changes: 13 additions & 3 deletions tests/functional/Console/RebuildCommandTest.php
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
<?php namespace tests\functional\Console;

use Config;
use File;
use Illuminate\Console\Application;
use Symfony\Component\Console\Output\BufferedOutput;
use tests\TestCase;
use Config;

/**
* Class RebuildCommandTest
Expand All @@ -23,8 +24,17 @@ public function setUp()
// Call migrations specific to our tests, e.g. to seed the db.
$this->artisan->call('migrate', ['--database' => 'testbench', '--path' => '../tests/migrations']);

Config::set('laravel-lucene-search::index.path',
sys_get_temp_dir() . '/laravel-lucene-search/index' . uniqid('index-', true));
Config::set(
'laravel-lucene-search::index.path',
sys_get_temp_dir() . '/laravel-lucene-search/' . uniqid('index-', true)
);
}

public function tearDown()
{
parent::tearDown();

File::deleteDirectory(Config::get('laravel-lucene-search::index.path'));
}

/**
Expand Down

0 comments on commit deaeefb

Please sign in to comment.