locker = $locker; } 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('Command "%s" is already in progress. Skipping.', $lockConfig->lockName()) ); return ExitCodes::EXIT_WARNING; } try { return $this->lockedExecute($input, $output); } finally { $lock->release(); } } abstract protected function lockedExecute(InputInterface $input, OutputInterface $output): int; abstract protected function getLockConfig(): LockedCommandConfig; }