On Symfony 4.4, I am trying to establish a lock in a command and keep it alive until explicitly released. Reading the docs I understand that this should be obtained with the $autoRelease param of Symfony\Component\Lock\LockFactory::createLock(), but it seems that even if I set $autoRelease = false the lock is automatically released when the script ends.
LockCommand
<?php
namespace App\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Lock\LockFactory;
class LockCommand extends Command
{
const LOCK_NAME = "my_lock";
protected static $defaultName = 'app:lock';
private $lockFactory;
public function __construct(LockFactory $lockFactory)
{
$this->lockFactory = $lockFactory;
parent::__construct();
}
protected function configure()
{
$this
->setDescription("Enables/disables the lock.")
->addOption(
'release',
'r',
InputOption::VALUE_NONE,
'Releases the lock'
)
;
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$lock = $this->lockFactory->createLock(self::LOCK_NAME, 300.0, false);
$release = $input->getOption('release');
if ($release) {
$lock->release();
} else {
$lock->acquire();
}
//sleep(300);
return 0;
}
}
LockVerifyCommand
<?php
namespace App\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Lock\LockFactory;
class LockVerifyCommand extends Command
{
protected static $defaultName = 'app:lock-verify';
private $lockFactory;
public function __construct(LockFactory $lockFactory)
{
$this->lockFactory = $lockFactory;
parent::__construct();
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$lock = $this->lockFactory->createLock(LockCommand::LOCK_NAME, 300.0, false);
$status = $lock->acquire() ? "no" : "yes";
$output->writeln("Locked? $status");
return 0;
}
}
I would expect to be able to
- enable the lock
php bin/console app:lock php bin/console app:lock-verifyshould sayLocked? yes- until I release the lock
php bin/console app:lock --release
this happens only while the app:lock command is running.
The most important thing here is the actual implementation of
LockStore. Depending on which one you choose can mean a whole lot of difference.For example, if I am not mistaken, the LockStore is
SemaphoreStoreby default. You can look up the code on GitHub, but the main thing to notice is that it uses PHP'sext-semaphoreextension (that is,sem_*functions). Looking into the PHP's doc page forsem_acquire, it says:In other words, the lock is not persisted after the main process ends.
The same goes for
FileStore, though it is entirely up to OS to release the lock, which can get messy.What you need is some persistent store, like
PdoStore,DoctrineDbalStore,RedisStore, or something else.Just beware that some stores auto-expire locks. You can read more about that in the official docs page: Expiring Locks