diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 67730d0..59d213d 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -7,16 +7,16 @@ jobs: # not self-hosted, because it's a public repo runs-on: ubuntu-latest - # we want to run it on combination of PHP 8.1+ and Laravel 9.1+ + # we want to run it on combination of PHP and Laravel versions strategy: fail-fast: false matrix: - php: ['8.2', '8.3'] - laravel: ['^10.0', '^11.0'] + php: ['8.2', '8.3', '8.4'] + laravel: ['^10.0', '^11.0', '^12.0'] steps: - name: Checkout the repo - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Setup PHP uses: shivammathur/setup-php@v2 diff --git a/composer.json b/composer.json index 39b7d81..45ad95d 100644 --- a/composer.json +++ b/composer.json @@ -21,14 +21,14 @@ ], "require": { "php": "^8.2", - "illuminate/contracts": "^10.0|^11.0", - "illuminate/console": "^10.0|^11.0", - "illuminate/database": "^10.0|^11.0", - "illuminate/support": "^10.0|^11.0" + "illuminate/contracts": "^10.0 | ^11.0 | ^12.0", + "illuminate/console": "^10.0 | ^11.0 | ^12.0", + "illuminate/database": "^10.0 | ^11.0 | ^12.0", + "illuminate/support": "^10.0 | ^11.0 | ^12.0" }, "require-dev": { - "orchestra/testbench": "^8.0|^9.0", - "spatie/fork": "^1.1" + "orchestra/testbench": "^8.0 | ^9.0 | ^10.0", + "spatie/fork": "^1.2" }, "autoload": { "psr-4": { @@ -43,7 +43,8 @@ "extra": { "laravel": { "providers": [ - "Netsells\\LaravelMutexMigrations\\ServiceProvider" + "Netsells\\LaravelMutexMigrations\\DependencyBindingProvider", + "Netsells\\LaravelMutexMigrations\\PackageProvider" ] } }, diff --git a/src/MigrateCommandExtension.php b/src/Commands/MigrateCommandExtension.php similarity index 52% rename from src/MigrateCommandExtension.php rename to src/Commands/MigrateCommandExtension.php index a8560a5..579d27d 100644 --- a/src/MigrateCommandExtension.php +++ b/src/Commands/MigrateCommandExtension.php @@ -1,6 +1,8 @@ option(MutexMigrateCommand::OPTION_MUTEX)) { + if ($this->shouldUseMutex()) { try { return $this->call(MutexMigrateCommand::class, $this->getCommandOptions()); } catch (DatabaseCacheTableNotFoundException $e) { - $this->components->warn('Falling back to a standard migration'); + if ($this->option(MutexMigrateCommand::OPTION_MUTEX)) { + return $this->options('graceful') ? self::SUCCESS : self::FAILURE; + } elseif ($this->option(MutexMigrateCommand::OPTION_MUTEX_GRACEFUL)) { + $this->components->warn('Falling back to a standard migration'); + } } } return parent::handle(); } + private function shouldUseMutex(): bool + { + return $this->option(MutexMigrateCommand::OPTION_MUTEX) + || $this->option(MutexMigrateCommand::OPTION_MUTEX_GRACEFUL); + } + private function getCommandOptions(): array { return Collection::make($this->options()) - ->reject(fn ($value, $key) => $key === MutexMigrateCommand::OPTION_MUTEX) + ->reject(fn ($value, $key) => \in_array($key, [ + MutexMigrateCommand::OPTION_MUTEX, + MutexMigrateCommand::OPTION_MUTEX_GRACEFUL, + ])) ->mapWithKeys(fn ($value, $key) => ["--$key" => $value]) ->all(); } diff --git a/src/MutexMigrateCommand.php b/src/Commands/MutexMigrateCommand.php similarity index 78% rename from src/MutexMigrateCommand.php rename to src/Commands/MutexMigrateCommand.php index c289bef..6096762 100644 --- a/src/MutexMigrateCommand.php +++ b/src/Commands/MutexMigrateCommand.php @@ -1,6 +1,8 @@ + */ + public function provides(): array + { + return [ + MigrateCommand::class, + Commands\MutexMigrateCommand::class, + Mutex\MutexRelay::class, + ]; + } + + /** + * Register any application services. + */ + public function register(): void + { + $this->app->bind(MigrateCommand::class, Commands\MigrateCommandExtension::class); + + $this->app->when([Commands\MigrateCommandExtension::class, Commands\MutexMigrateCommand::class]) + ->needs(Migrator::class) + ->give(function ($app) { + return $app['migrator']; + }); + + $this->app->bind(Mutex\MutexRelay::class, function ($app) { + $store = Config::get('mutex-migrations.lock.store'); + + return new Mutex\MutexRelay( + cache: Cache::store($store), + lockDurationSeconds: Config::get('mutex-migrations.lock.ttl_seconds') + ?? Mutex\MutexRelay::DEFAULT_TTL_SECONDS, + lockTable: Config::get("cache.stores.{$store}.lock_table") + ?? Mutex\MutexRelay::DEFAULT_LOCK_TABLE, + ); + }); + } + + /** + * Bootstrap any package services. + */ + public function boot(): void + { + // + } +} diff --git a/src/Mutex/DatabaseCacheTableNotFoundException.php b/src/Mutex/DatabaseCacheTableNotFoundException.php index ced1fd9..17251b5 100644 --- a/src/Mutex/DatabaseCacheTableNotFoundException.php +++ b/src/Mutex/DatabaseCacheTableNotFoundException.php @@ -1,5 +1,7 @@ getCode() === '42S02' && Str::contains($th->getMessage(), $this->lockTable); + return Str::contains($th->getMessage(), $this->lockTable) && \in_array($th->getCode(), [ + '42S02', // mysql + 'HY000', // sqlite + ], true); } } diff --git a/src/Mutex/MutexRelayInterface.php b/src/Mutex/MutexRelayInterface.php index acf494c..e032b6b 100644 --- a/src/Mutex/MutexRelayInterface.php +++ b/src/Mutex/MutexRelayInterface.php @@ -1,5 +1,7 @@ app->runningInConsole()) { + return; + } + + $this->mergeConfigFrom(__DIR__.'/../config/mutex-migrations.php', 'mutex-migrations'); + } + + /** + * Bootstrap any package services. + */ + public function boot(): void + { + if (! $this->app->runningInConsole()) { + return; + } + + $this->publishes([ + __DIR__.'/../config/mutex-migrations.php' => config_path('mutex-migrations.php'), + ], 'mutex-migrations-config'); + } +} diff --git a/src/Processors/MigrationProcessorFactory.php b/src/Processors/MigrationProcessorFactory.php index 1462049..4373286 100644 --- a/src/Processors/MigrationProcessorFactory.php +++ b/src/Processors/MigrationProcessorFactory.php @@ -1,5 +1,7 @@ app->runningInConsole()) { - return; - } - - $this->mergeConfigFrom(__DIR__.'/../config/mutex-migrations.php', 'mutex-migrations'); - - $this->app->bind(MigrateCommand::class, MigrateCommandExtension::class); - - $this->app->when([MigrateCommandExtension::class, MutexMigrateCommand::class]) - ->needs(Migrator::class) - ->give(function ($app) { - return $app['migrator']; - }); - - $this->app->bind(MutexRelay::class, function ($app) { - $store = Config::get('mutex-migrations.lock.store'); - - return new MutexRelay( - Cache::store($store), - Config::get('mutex-migrations.lock.ttl_seconds'), - Config::get("cache.stores.{$store}.lock_table", MutexRelay::DEFAULT_LOCK_TABLE), - ); - }); - } - - /** - * Bootstrap any package services. - * - * @return void - */ - public function boot() - { - if (! $this->app->runningInConsole()) { - return; - } - - $this->publishes([ - __DIR__.'/../config/mutex-migrations.php' => config_path('mutex-migrations.php'), - ], 'mutex-migrations-config'); - } - - /** - * Get the services provided by the provider. - * - * @return array - */ - public function provides() - { - return [ - MigrateCommand::class, - MutexMigrateCommand::class, - MutexRelay::class, - ]; - } -} diff --git a/tests/Integration/AbstractIntegrationTestCase.php b/tests/Integration/AbstractIntegrationTestCase.php index ad2f97b..fca4e93 100644 --- a/tests/Integration/AbstractIntegrationTestCase.php +++ b/tests/Integration/AbstractIntegrationTestCase.php @@ -1,8 +1,10 @@