Skip to content

Commit a69f847

Browse files
authored
Merge pull request #7 from netsells/3.x
3.x
2 parents e1fe03a + 3c715be commit a69f847

15 files changed

+168
-97
lines changed

.github/workflows/tests.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,16 @@ jobs:
77
# not self-hosted, because it's a public repo
88
runs-on: ubuntu-latest
99

10-
# we want to run it on combination of PHP 8.1+ and Laravel 9.1+
10+
# we want to run it on combination of PHP and Laravel versions
1111
strategy:
1212
fail-fast: false
1313
matrix:
14-
php: ['8.2', '8.3']
15-
laravel: ['^10.0', '^11.0']
14+
php: ['8.2', '8.3', '8.4']
15+
laravel: ['^10.0', '^11.0', '^12.0']
1616

1717
steps:
1818
- name: Checkout the repo
19-
uses: actions/checkout@v2
19+
uses: actions/checkout@v3
2020

2121
- name: Setup PHP
2222
uses: shivammathur/setup-php@v2

composer.json

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,14 @@
2121
],
2222
"require": {
2323
"php": "^8.2",
24-
"illuminate/contracts": "^10.0|^11.0",
25-
"illuminate/console": "^10.0|^11.0",
26-
"illuminate/database": "^10.0|^11.0",
27-
"illuminate/support": "^10.0|^11.0"
24+
"illuminate/contracts": "^10.0 | ^11.0 | ^12.0",
25+
"illuminate/console": "^10.0 | ^11.0 | ^12.0",
26+
"illuminate/database": "^10.0 | ^11.0 | ^12.0",
27+
"illuminate/support": "^10.0 | ^11.0 | ^12.0"
2828
},
2929
"require-dev": {
30-
"orchestra/testbench": "^8.0|^9.0",
31-
"spatie/fork": "^1.1"
30+
"orchestra/testbench": "^8.0 | ^9.0 | ^10.0",
31+
"spatie/fork": "^1.2"
3232
},
3333
"autoload": {
3434
"psr-4": {
@@ -43,7 +43,8 @@
4343
"extra": {
4444
"laravel": {
4545
"providers": [
46-
"Netsells\\LaravelMutexMigrations\\ServiceProvider"
46+
"Netsells\\LaravelMutexMigrations\\DependencyBindingProvider",
47+
"Netsells\\LaravelMutexMigrations\\PackageProvider"
4748
]
4849
}
4950
},

src/MigrateCommandExtension.php renamed to src/Commands/MigrateCommandExtension.php

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
<?php
22

3-
namespace Netsells\LaravelMutexMigrations;
3+
declare(strict_types=1);
4+
5+
namespace Netsells\LaravelMutexMigrations\Commands;
46

57
use Illuminate\Contracts\Events\Dispatcher;
68
use Illuminate\Database\Console\Migrations\MigrateCommand;
@@ -15,25 +17,39 @@ public function __construct(Migrator $migrator, Dispatcher $dispatcher)
1517
parent::__construct($migrator, $dispatcher);
1618

1719
parent::addOption(...MutexMigrateCommand::getMutexOption());
20+
parent::addOption(...MutexMigrateCommand::getMutexGracefulOption());
1821
}
1922

2023
public function handle(): int
2124
{
22-
if ($this->option(MutexMigrateCommand::OPTION_MUTEX)) {
25+
if ($this->shouldUseMutex()) {
2326
try {
2427
return $this->call(MutexMigrateCommand::class, $this->getCommandOptions());
2528
} catch (DatabaseCacheTableNotFoundException $e) {
26-
$this->components->warn('Falling back to a standard migration');
29+
if ($this->option(MutexMigrateCommand::OPTION_MUTEX)) {
30+
return $this->options('graceful') ? self::SUCCESS : self::FAILURE;
31+
} elseif ($this->option(MutexMigrateCommand::OPTION_MUTEX_GRACEFUL)) {
32+
$this->components->warn('Falling back to a standard migration');
33+
}
2734
}
2835
}
2936

3037
return parent::handle();
3138
}
3239

40+
private function shouldUseMutex(): bool
41+
{
42+
return $this->option(MutexMigrateCommand::OPTION_MUTEX)
43+
|| $this->option(MutexMigrateCommand::OPTION_MUTEX_GRACEFUL);
44+
}
45+
3346
private function getCommandOptions(): array
3447
{
3548
return Collection::make($this->options())
36-
->reject(fn ($value, $key) => $key === MutexMigrateCommand::OPTION_MUTEX)
49+
->reject(fn ($value, $key) => \in_array($key, [
50+
MutexMigrateCommand::OPTION_MUTEX,
51+
MutexMigrateCommand::OPTION_MUTEX_GRACEFUL,
52+
]))
3753
->mapWithKeys(fn ($value, $key) => ["--$key" => $value])
3854
->all();
3955
}

src/MutexMigrateCommand.php renamed to src/Commands/MutexMigrateCommand.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
<?php
22

3-
namespace Netsells\LaravelMutexMigrations;
3+
declare(strict_types=1);
4+
5+
namespace Netsells\LaravelMutexMigrations\Commands;
46

57
use Illuminate\Contracts\Events\Dispatcher;
68
use Illuminate\Database\Console\Migrations\MigrateCommand;
@@ -14,13 +16,20 @@ class MutexMigrateCommand extends MigrateCommand
1416
{
1517
public const OPTION_MUTEX = 'mutex';
1618

19+
public const OPTION_MUTEX_GRACEFUL = 'mutex-graceful';
20+
1721
private MigrationProcessorInterface $processor;
1822

1923
public static function getMutexOption(): array
2024
{
2125
return [self::OPTION_MUTEX, null, InputOption::VALUE_NONE, 'Run a mutually exclusive migration'];
2226
}
2327

28+
public static function getMutexGracefulOption(): array
29+
{
30+
return [self::OPTION_MUTEX_GRACEFUL, null, InputOption::VALUE_NONE, 'Run a mutually exclusive migration and gracefully failover to a standard migration if the application does not contain the required lock table'];
31+
}
32+
2433
public function __construct(
2534
Migrator $migrator,
2635
Dispatcher $dispatcher,

src/DependencyBindingProvider.php

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Netsells\LaravelMutexMigrations;
6+
7+
use Illuminate\Contracts\Support\DeferrableProvider;
8+
use Illuminate\Database\Console\Migrations\MigrateCommand;
9+
use Illuminate\Database\Migrations\Migrator;
10+
use Illuminate\Support\Facades\Cache;
11+
use Illuminate\Support\Facades\Config;
12+
use Illuminate\Support\ServiceProvider as BaseServiceProvider;
13+
use Netsells\LaravelMutexMigrations\Commands;
14+
use Netsells\LaravelMutexMigrations\Mutex;
15+
16+
class DependencyBindingProvider extends BaseServiceProvider implements DeferrableProvider
17+
{
18+
/**
19+
* Get the services provided by the provider.
20+
*
21+
* @return list<class-string>
22+
*/
23+
public function provides(): array
24+
{
25+
return [
26+
MigrateCommand::class,
27+
Commands\MutexMigrateCommand::class,
28+
Mutex\MutexRelay::class,
29+
];
30+
}
31+
32+
/**
33+
* Register any application services.
34+
*/
35+
public function register(): void
36+
{
37+
$this->app->bind(MigrateCommand::class, Commands\MigrateCommandExtension::class);
38+
39+
$this->app->when([Commands\MigrateCommandExtension::class, Commands\MutexMigrateCommand::class])
40+
->needs(Migrator::class)
41+
->give(function ($app) {
42+
return $app['migrator'];
43+
});
44+
45+
$this->app->bind(Mutex\MutexRelay::class, function ($app) {
46+
$store = Config::get('mutex-migrations.lock.store');
47+
48+
return new Mutex\MutexRelay(
49+
cache: Cache::store($store),
50+
lockDurationSeconds: Config::get('mutex-migrations.lock.ttl_seconds')
51+
?? Mutex\MutexRelay::DEFAULT_TTL_SECONDS,
52+
lockTable: Config::get("cache.stores.{$store}.lock_table")
53+
?? Mutex\MutexRelay::DEFAULT_LOCK_TABLE,
54+
);
55+
});
56+
}
57+
58+
/**
59+
* Bootstrap any package services.
60+
*/
61+
public function boot(): void
62+
{
63+
//
64+
}
65+
}

src/Mutex/DatabaseCacheTableNotFoundException.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22

3+
declare(strict_types=1);
4+
35
namespace Netsells\LaravelMutexMigrations\Mutex;
46

57
class DatabaseCacheTableNotFoundException extends \Exception

src/Mutex/MutexRelay.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22

3+
declare(strict_types=1);
4+
35
namespace Netsells\LaravelMutexMigrations\Mutex;
46

57
use Illuminate\Contracts\Cache\Lock;
@@ -11,13 +13,15 @@ class MutexRelay implements MutexRelayInterface
1113
{
1214
public const DEFAULT_LOCK_TABLE = 'cache_locks';
1315

16+
public const DEFAULT_TTL_SECONDS = 60;
17+
1418
public const KEY = 'laravel-mutex-migrations';
1519

1620
private ?Lock $lock = null;
1721

1822
public function __construct(
1923
private readonly Repository $cache,
20-
private readonly int $lockDurationSeconds = 60,
24+
private readonly int $lockDurationSeconds = self::DEFAULT_TTL_SECONDS,
2125
private readonly string $lockTable = self::DEFAULT_LOCK_TABLE,
2226
) {
2327
//
@@ -59,6 +63,9 @@ private function isCacheTableNotFoundException(\Throwable $th): bool
5963
return false;
6064
}
6165

62-
return $th->getCode() === '42S02' && Str::contains($th->getMessage(), $this->lockTable);
66+
return Str::contains($th->getMessage(), $this->lockTable) && \in_array($th->getCode(), [
67+
'42S02', // mysql
68+
'HY000', // sqlite
69+
], true);
6370
}
6471
}

src/Mutex/MutexRelayInterface.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22

3+
declare(strict_types=1);
4+
35
namespace Netsells\LaravelMutexMigrations\Mutex;
46

57
interface MutexRelayInterface

src/Mutex/NullRelay.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22

3+
declare(strict_types=1);
4+
35
namespace Netsells\LaravelMutexMigrations\Mutex;
46

57
class NullRelay implements MutexRelayInterface

src/PackageProvider.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Netsells\LaravelMutexMigrations;
6+
7+
use Illuminate\Support\ServiceProvider as BaseServiceProvider;
8+
9+
class PackageProvider extends BaseServiceProvider
10+
{
11+
/**
12+
* Register any application services.
13+
*/
14+
public function register(): void
15+
{
16+
if (! $this->app->runningInConsole()) {
17+
return;
18+
}
19+
20+
$this->mergeConfigFrom(__DIR__.'/../config/mutex-migrations.php', 'mutex-migrations');
21+
}
22+
23+
/**
24+
* Bootstrap any package services.
25+
*/
26+
public function boot(): void
27+
{
28+
if (! $this->app->runningInConsole()) {
29+
return;
30+
}
31+
32+
$this->publishes([
33+
__DIR__.'/../config/mutex-migrations.php' => config_path('mutex-migrations.php'),
34+
], 'mutex-migrations-config');
35+
}
36+
}

0 commit comments

Comments
 (0)