Decouple AbstractDatabaseCommand from AbstractLockedCommand

This commit is contained in:
Alejandro Celaya
2025-12-15 15:01:00 +01:00
parent 96d122bcbf
commit e261bd16e4
3 changed files with 18 additions and 51 deletions

View File

@@ -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;
}

View File

@@ -1,43 +0,0 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Util;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Lock\LockFactory;
use function sprintf;
abstract class AbstractLockedCommand extends Command
{
public function __construct(private readonly LockFactory $locker)
{
parent::__construct();
}
final protected function execute(InputInterface $input, OutputInterface $output): int
{
$lockConfig = $this->getLockConfig();
$lock = $this->locker->createLock($lockConfig->lockName, $lockConfig->ttl, $lockConfig->isBlocking);
if (! $lock->acquire($lockConfig->isBlocking)) {
$output->writeln(
sprintf('<comment>Command "%s" is already in progress. Skipping.</comment>', $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;
}

View File

@@ -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');