Skip to content

Commit 559665f

Browse files
authored
Indexing lock (#4)
1 parent 79ddf6e commit 559665f

12 files changed

+77
-103
lines changed

.codecov.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ coverage:
22
status:
33
patch:
44
default:
5-
target: 90%
5+
target: 80%

phpstan-baseline.neon

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@ parameters:
1616
path: src/LaravelElasticaBridgeServiceProvider.php
1717

1818
-
19-
message: "#^Parameter \\#2 \\$model of method Limenet\\\\LaravelElasticaBridge\\\\Services\\\\ModelEvent\\:\\:handle\\(\\) expects Illuminate\\\\Database\\\\Eloquent\\\\Model&Limenet\\\\LaravelElasticaBridge\\\\Model\\\\ElasticsearchableInterface, Illuminate\\\\Database\\\\Eloquent\\\\Model given\\.$#"
19+
message: "#^Parameter \\#2 \\$model of method Limenet\\\\LaravelElasticaBridge\\\\Services\\\\ModelEventListener\\:\\:handle\\(\\) expects Illuminate\\\\Database\\\\Eloquent\\\\Model&Limenet\\\\LaravelElasticaBridge\\\\Model\\\\ElasticsearchableInterface, Illuminate\\\\Database\\\\Eloquent\\\\Model given\\.$#"
2020
count: 1
2121
path: src/LaravelElasticaBridgeServiceProvider.php

src/Commands/IndexCommand.php

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -14,36 +14,18 @@
1414

1515
class IndexCommand extends Command
1616
{
17-
/**
18-
* The name and signature of the console command.
19-
*
20-
* @var string
21-
*/
22-
protected $signature = 'elastica-bridge:index {index?*} {--delete}';
17+
protected $signature = 'elastica-bridge:index {index?*} {--delete} {--force}';
2318

24-
/**
25-
* The console command description.
26-
*
27-
* @var string
28-
*/
2919
protected $description = 'Re-create the ES index and populate with data';
3020

31-
/**
32-
* Create a new command instance.
33-
*
34-
* @return void
35-
*/
36-
public function __construct(protected ElasticaClient $elastica, protected IndexRepository $indexRepository)
37-
{
21+
public function __construct(
22+
protected ElasticaClient $elastica,
23+
protected IndexRepository $indexRepository
24+
) {
3825
parent::__construct();
3926
}
4027

41-
/**
42-
* Execute the console command.
43-
*
44-
* @return int
45-
*/
46-
public function handle()
28+
public function handle(): int
4729
{
4830
foreach ($this->indexRepository->all() as $indexConfig) {
4931
if (
@@ -55,19 +37,35 @@ public function handle()
5537

5638
$this->info(sprintf('Indexing %s', $indexConfig->getName()));
5739

40+
$lock = $indexConfig->indexingLock();
41+
42+
if ((bool) $this->option('force')) {
43+
$lock->forceRelease();
44+
}
45+
46+
if (!$lock->get()) {
47+
$this->warn('Not indexing as another job is still running.');
48+
continue;
49+
}
50+
5851
Bus::batch([
59-
[new SetupIndex($indexConfig, (bool) $this->option('delete'))],
60-
[new PopulateIndex($indexConfig)],
52+
[
53+
new SetupIndex($indexConfig, (bool) $this->option('delete')),
54+
new PopulateIndex($indexConfig),
55+
],
6156
])
6257
->onConnection(config('elastica-bridge.connection'))
6358
->then(function () use ($indexConfig): void {
6459
ActivateIndex::dispatch($indexConfig)
6560
->onConnection(config('elastica-bridge.connection'));
6661
})
62+
->finally(function () use ($indexConfig): void {
63+
$indexConfig->indexingLock()->forceRelease();
64+
})
6765
->name('ES index: '.$indexConfig->getName())
6866
->dispatch();
6967
}
7068

71-
return 0;
69+
return self::SUCCESS;
7270
}
7371
}

src/Commands/StatusCommand.php

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,36 +12,18 @@
1212

1313
class StatusCommand extends Command
1414
{
15-
/**
16-
* The name and signature of the console command.
17-
*
18-
* @var string
19-
*/
2015
protected $signature = 'elastica-bridge:status';
2116

22-
/**
23-
* The console command description.
24-
*
25-
* @var string
26-
*/
2717
protected $description = 'Displays the status of the configured Elasticsearch indices';
2818

29-
/**
30-
* Create a new command instance.
31-
*
32-
* @return void
33-
*/
34-
public function __construct(protected ElasticaClient $elastica, protected IndexRepository $indexRepository)
35-
{
19+
public function __construct(
20+
protected ElasticaClient $elastica,
21+
protected IndexRepository $indexRepository
22+
) {
3623
parent::__construct();
3724
}
3825

39-
/**
40-
* Execute the console command.
41-
*
42-
* @return int
43-
*/
44-
public function handle()
26+
public function handle(): int
4527
{
4628
$table = new Table($this->output);
4729
$table
@@ -100,7 +82,7 @@ public function handle()
10082
->setHeaderTitle('Indices');
10183
$table->render();
10284

103-
return 0;
85+
return self::SUCCESS;
10486
}
10587

10688
protected function formatBoolean(bool $val): string

src/Index/AbstractIndex.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
use Elastica\Index;
1010
use Elastica\Query;
1111
use Elastica\ResultSet;
12+
use Illuminate\Contracts\Cache\Lock;
1213
use Illuminate\Database\Eloquent\Model;
14+
use Illuminate\Support\Facades\Cache;
1315
use Limenet\LaravelElasticaBridge\Client\ElasticaClient;
1416
use Limenet\LaravelElasticaBridge\Exception\Index\BlueGreenIndicesIncorrectlySetupException;
1517
use Limenet\LaravelElasticaBridge\Model\ElasticsearchableInterface;
@@ -168,4 +170,9 @@ final public function getBlueGreenInactiveElasticaIndex(): Index
168170
{
169171
return $this->client->getIndex($this->getName().$this->getBlueGreenInactiveSuffix());
170172
}
173+
174+
final public function indexingLock(): Lock
175+
{
176+
return Cache::lock(__CLASS__.$this->getName());
177+
}
171178
}

src/Index/IndexInterface.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use Elastica\Document;
88
use Elastica\Index;
9+
use Illuminate\Contracts\Cache\Lock;
910
use Illuminate\Database\Eloquent\Model;
1011
use Limenet\LaravelElasticaBridge\Exception\Index\BlueGreenIndicesIncorrectlySetupException;
1112
use Limenet\LaravelElasticaBridge\Model\ElasticsearchableInterface;
@@ -139,4 +140,6 @@ public function getModelInstance(Document $document): Model;
139140
* @return Document
140141
*/
141142
public function getDocumentInstance(Model|ElasticsearchableInterface $model): ?Document;
143+
144+
public function indexingLock(): Lock;
142145
}

src/Jobs/ActivateIndex.php

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,10 @@
88

99
class ActivateIndex extends AbstractIndexJob
1010
{
11-
/**
12-
* Create a new job instance.
13-
*
14-
* @return void
15-
*/
1611
public function __construct(protected IndexInterface $indexConfig)
1712
{
18-
//
1913
}
2014

21-
/**
22-
* Execute the job.
23-
*/
2415
public function handle(): void
2516
{
2617
$oldIndex = $this->indexConfig->getBlueGreenActiveElasticaIndex();

src/Jobs/PopulateBatchIndex.php

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,15 @@ class PopulateBatchIndex implements ShouldQueue
2222
use Queueable;
2323
use SerializesModels;
2424

25-
/**
26-
* Create a new job instance.
27-
*
28-
* @return void
29-
*/
30-
public function __construct(protected Index $index, protected IndexInterface $indexConfig, protected string $indexDocument, protected int $limit, protected int $offset)
31-
{
32-
//
25+
public function __construct(
26+
protected Index $index,
27+
protected IndexInterface $indexConfig,
28+
protected string $indexDocument,
29+
protected int $limit,
30+
protected int $offset
31+
) {
3332
}
3433

35-
/**
36-
* Execute the job.
37-
*/
3834
public function handle(): void
3935
{
4036
if ($this->batch()?->cancelled()) {

src/Jobs/PopulateIndex.php

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,10 @@ class PopulateIndex extends AbstractIndexJob
1111
{
1212
use Batchable;
1313

14-
/**
15-
* Create a new job instance.
16-
*
17-
* @return void
18-
*/
1914
public function __construct(protected IndexInterface $indexConfig)
2015
{
21-
//
2216
}
2317

24-
/**
25-
* Execute the job.
26-
*/
2718
public function handle(): void
2819
{
2920
if ($this->batch()?->cancelled()) {
@@ -41,7 +32,13 @@ public function handle(): void
4132
$modelCount = $indexDocument::count();
4233

4334
for ($batchNumber = 0; $batchNumber < ceil($modelCount / $this->indexConfig->getBatchSize()); $batchNumber++) {
44-
$jobs[] = new PopulateBatchIndex($index, $this->indexConfig, $indexDocument, $this->indexConfig->getBatchSize(), $batchNumber * $this->indexConfig->getBatchSize());
35+
$jobs[] = new PopulateBatchIndex(
36+
$index,
37+
$this->indexConfig,
38+
$indexDocument,
39+
$this->indexConfig->getBatchSize(),
40+
$batchNumber * $this->indexConfig->getBatchSize()
41+
);
4542
}
4643
}
4744

src/Jobs/SetupIndex.php

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,12 @@ class SetupIndex extends AbstractIndexJob
1313
{
1414
use Batchable;
1515

16-
/**
17-
* Create a new job instance.
18-
*
19-
* @return void
20-
*/
21-
public function __construct(protected IndexInterface $indexConfig, protected bool $deleteExisting)
22-
{
23-
//
16+
public function __construct(
17+
protected IndexInterface $indexConfig,
18+
protected bool $deleteExisting
19+
) {
2420
}
2521

26-
/**
27-
* Execute the job.
28-
*/
2922
public function handle(ElasticaClient $elastica): void
3023
{
3124
if ($this->batch()?->cancelled()) {

src/LaravelElasticaBridgeServiceProvider.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
use Limenet\LaravelElasticaBridge\Commands\IndexCommand;
1212
use Limenet\LaravelElasticaBridge\Commands\StatusCommand;
1313
use Limenet\LaravelElasticaBridge\Repository\IndexRepository;
14-
use Limenet\LaravelElasticaBridge\Services\ModelEvent;
14+
use Limenet\LaravelElasticaBridge\Services\ModelEventListener;
1515
use Spatie\LaravelPackageTools\Package;
1616
use Spatie\LaravelPackageTools\PackageServiceProvider;
1717

@@ -33,7 +33,7 @@ public function configurePackage(Package $package): void
3333
public function packageRegistered(): void
3434
{
3535
$this->app->singleton(ElasticaClient::class);
36-
$this->app->bind(ModelEvent::class);
36+
$this->app->bind(ModelEventListener::class);
3737
$this->app->tag(config('elastica-bridge.indices'), 'elasticaBridgeIndices');
3838

3939
$this->app->when(IndexRepository::class)
@@ -43,16 +43,16 @@ public function packageRegistered(): void
4343

4444
public function packageBooted(): void
4545
{
46-
foreach (ModelEvent::EVENTS as $name) {
46+
foreach (ModelEventListener::EVENTS as $name) {
4747
Event::listen(
4848
sprintf('eloquent.%s:*', $name),
4949
queueable(function (string $event, array $models) use ($name): void {
5050
if (!resolve(ElasticaClient::class)->listensToEvents()) {
5151
return;
5252
}
5353

54-
$modelEvent = resolve(ModelEvent::class);
55-
collect($models)->each(fn (Model $model) => $modelEvent->handle($name, $model));
54+
$modelEventListener = resolve(ModelEventListener::class);
55+
collect($models)->each(fn (Model $model) => $modelEventListener->handle($name, $model));
5656
})->onConnection(config('elastica-bridge.connection'))
5757
);
5858
}

src/Services/ModelEvent.php renamed to src/Services/ModelEventListener.php

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,20 @@
1010
use Limenet\LaravelElasticaBridge\Model\ElasticsearchableInterface;
1111
use Limenet\LaravelElasticaBridge\Repository\IndexRepository;
1212

13-
class ModelEvent
13+
class ModelEventListener
1414
{
1515
public const EVENT_CREATED = 'created';
1616
public const EVENT_UPDATED = 'updated';
1717
public const EVENT_SAVED = 'saved';
1818
public const EVENT_RESTORED = 'restored';
1919
public const EVENT_DELETED = 'deleted';
20-
public const EVENTS = [self::EVENT_CREATED, self::EVENT_UPDATED, self::EVENT_SAVED, self::EVENT_RESTORED, self::EVENT_DELETED];
20+
public const EVENTS = [
21+
self::EVENT_CREATED,
22+
self::EVENT_UPDATED,
23+
self::EVENT_SAVED,
24+
self::EVENT_RESTORED,
25+
self::EVENT_DELETED,
26+
];
2127

2228
public function __construct(protected IndexRepository $indexRepository)
2329
{
@@ -37,7 +43,9 @@ public function handle(string $event, Model $model): void
3743
$shouldBePresent = false;
3844
}
3945

40-
$shouldBePresent ? $this->ensureModelPresentInIndex($index, $model) : $this->ensureModelMissingFromIndex($index, $model);
46+
$shouldBePresent
47+
? $this->ensureModelPresentInIndex($index, $model)
48+
: $this->ensureModelMissingFromIndex($index, $model);
4149
}
4250
}
4351

@@ -53,7 +61,6 @@ protected function ensureModelMissingFromIndex(IndexInterface $index, Model $mod
5361
try {
5462
$index->getElasticaIndex()->deleteById($model->getElasticsearchId());
5563
} catch (NotFoundException) {
56-
//
5764
}
5865
}
5966

0 commit comments

Comments
 (0)