在 Symfony 4.4 上,我试图在命令中建立锁定并使其保持活动状态,直到显式释放为止。阅读 the docs 我明白这应该通过
$autoRelease
的 Symfony\Component\Lock\LockFactory::createLock()
参数获得,但似乎即使我设置 $autoRelease = false
,锁也会在脚本结束时自动释放。
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;
}
}
我希望能够
php bin/console app:lock
php bin/console app:lock-verify
应该说Locked? yes
php bin/console app:lock --release
仅当
app:lock
命令运行时才会发生这种情况。
这里最重要的是
LockStore
的实际执行。根据您的选择,可能会带来很大的差异。
举个例子,如果我没记错的话,LockStore默认是
SemaphoreStore
。你可以在 GitHub 上查找代码,但主要要注意的是它使用了 PHP 的 ext-semaphore
扩展(即 sem_*
函数)。查看 PHP 的文档页面 sem_acquire
,它说:
处理完请求后,进程获取但未显式释放的任何信号量都会自动释放,并生成警告。
也就是说,主进程结束后,锁不会被持久化。
同样适用于
FileStore
,尽管释放锁完全取决于操作系统,这可能会变得混乱。
您需要的是一些持久存储,例如
PdoStore
、DoctrineDbalStore
、RedisStore
或其他东西。
请注意,有些商店的锁会自动过期。您可以在官方文档页面中阅读更多相关信息:Expiring Locks