From e261bd16e45c9fc252d1953b5bfb542ee9a5fb43 Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Mon, 15 Dec 2025 15:01:00 +0100 Subject: [PATCH] Decouple AbstractDatabaseCommand from AbstractLockedCommand --- .../Command/Db/AbstractDatabaseCommand.php | 22 +++++++--- .../Command/Util/AbstractLockedCommand.php | 43 ------------------- .../src/Command/Visit/LocateVisitsCommand.php | 4 +- 3 files changed, 18 insertions(+), 51 deletions(-) delete mode 100644 module/CLI/src/Command/Util/AbstractLockedCommand.php diff --git a/module/CLI/src/Command/Db/AbstractDatabaseCommand.php b/module/CLI/src/Command/Db/AbstractDatabaseCommand.php index 5212cf3b..a38abc72 100644 --- a/module/CLI/src/Command/Db/AbstractDatabaseCommand.php +++ b/module/CLI/src/Command/Db/AbstractDatabaseCommand.php @@ -4,23 +4,26 @@ declare(strict_types=1); namespace Shlinkio\Shlink\CLI\Command\Db; -use Shlinkio\Shlink\CLI\Command\Util\AbstractLockedCommand; +use Shlinkio\Shlink\CLI\Command\Util\CommandUtils; use Shlinkio\Shlink\CLI\Command\Util\LockConfig; use Shlinkio\Shlink\CLI\Util\ProcessRunnerInterface; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Lock\LockFactory; use Symfony\Component\Process\PhpExecutableFinder; -abstract class AbstractDatabaseCommand extends AbstractLockedCommand +abstract class AbstractDatabaseCommand extends Command { private string $phpBinary; public function __construct( - LockFactory $locker, + private readonly LockFactory $locker, private readonly ProcessRunnerInterface $processRunner, PhpExecutableFinder $phpFinder, ) { - parent::__construct($locker); + parent::__construct(); $this->phpBinary = $phpFinder->find(false) ?: 'php'; } @@ -30,8 +33,15 @@ abstract class AbstractDatabaseCommand extends AbstractLockedCommand $this->processRunner->run($output, $command); } - protected function getLockConfig(): LockConfig + final protected function execute(InputInterface $input, OutputInterface $output): int { - return LockConfig::blocking($this->getName() ?? static::class); + return CommandUtils::executeWithLock( + $this->locker, + LockConfig::blocking($this->getName() ?? static::class), + new SymfonyStyle($input, $output), + fn () => $this->lockedExecute($input, $output), + ); } + + abstract protected function lockedExecute(InputInterface $input, OutputInterface $output): int; } diff --git a/module/CLI/src/Command/Util/AbstractLockedCommand.php b/module/CLI/src/Command/Util/AbstractLockedCommand.php deleted file mode 100644 index bf58fb1b..00000000 --- a/module/CLI/src/Command/Util/AbstractLockedCommand.php +++ /dev/null @@ -1,43 +0,0 @@ -getLockConfig(); - $lock = $this->locker->createLock($lockConfig->lockName, $lockConfig->ttl, $lockConfig->isBlocking); - - if (! $lock->acquire($lockConfig->isBlocking)) { - $output->writeln( - sprintf('Command "%s" is already in progress. Skipping.', $lockConfig->lockName), - ); - return self::INVALID; - } - - try { - return $this->lockedExecute($input, $output); - } finally { - $lock->release(); - } - } - - abstract protected function lockedExecute(InputInterface $input, OutputInterface $output): int; - - abstract protected function getLockConfig(): LockConfig; -} diff --git a/module/CLI/src/Command/Visit/LocateVisitsCommand.php b/module/CLI/src/Command/Visit/LocateVisitsCommand.php index f2501a34..fa1b13b4 100644 --- a/module/CLI/src/Command/Visit/LocateVisitsCommand.php +++ b/module/CLI/src/Command/Visit/LocateVisitsCommand.php @@ -104,11 +104,11 @@ class LocateVisitsCommand extends Command implements VisitGeolocationHelperInter $this->locker, LockConfig::nonBlocking(self::NAME), new SymfonyStyle($input, $output), - fn () => $this->runStuff($input), + fn () => $this->locateVisits($input), ); } - private function runStuff(InputInterface $input): int + private function locateVisits(InputInterface $input): int { $retry = $input->getOption('retry'); $all = $retry && $input->getOption('all');