Symfony,在一个命令中设置一个锁来锁定另一个命令

问题描述 投票:0回答:1

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

我希望能够

  1. 启用锁定
    php bin/console app:lock
  2. php bin/console app:lock-verify
    应该说
    Locked? yes
  3. 直到我松开锁
    php bin/console app:lock --release

仅当

app:lock
命令运行时才会发生这种情况。

php symfony locking symfony4
1个回答
2
投票

这里最重要的是

LockStore
的实际执行。根据您的选择,可能会带来很大的差异。

举个例子,如果我没记错的话,LockStore默认是

SemaphoreStore
。你可以在 GitHub 上查找代码,但主要要注意的是它使用了 PHP 的
ext-semaphore
扩展(即
sem_*
函数)。查看 PHP 的文档页面
sem_acquire
,它说:

处理完请求后,进程获取但未显式释放的任何信号量都会自动释放,并生成警告。

也就是说,主进程结束后,锁不会被持久化。

同样适用于

FileStore
,尽管释放锁完全取决于操作系统,这可能会变得混乱。

您需要的是一些持久存储,例如

PdoStore
DoctrineDbalStore
RedisStore
或其他东西。

请注意,有些商店的锁会自动过期。您可以在官方文档页面中阅读更多相关信息:Expiring Locks

© www.soinside.com 2019 - 2024. All rights reserved.