Reputation: 577
I have a service which I use both from a custom command and an HTML page. I want to prevent multiple executions of the the service in parallel. For the command there is the Lock component that does that. But is it possible to achieve the same thing for a controller method ?
The lock component doesn't work if the service is called from a controller:
$store = new FlockStore(sys_get_temp_dir());
$factory = new Factory($store);
$lock = $factory->createLock('MY_SERVICE');
I wanted to avoid calling the command from the controller (that's why I created a service) mainly because the service doesn't have the same output for the HTML page and the CLI.
Upvotes: 1
Views: 1223
Reputation: 906
Inject the lock Factory into your service directly instead of creating the lock in the command AND in the controller.
First you have to install Lock Component:
composer require symfony/lock
Then, for example, you can declare your service like this:
use Symfony\Component\Lock\Factory as LockFactory;
class MyService {
private $lock;
public function __construct(LockFactory $lockFactory) {
$this->lock = $lockFactory->createLock('LOCK_KEY');
}
public function doWork() {
$this->lock->acquire();
try {
// DO THINGS
} finally {
$this->lock->release();
}
}
}
Upvotes: 5
Reputation: 577
I said:
The lock component doesn't work if the service is called from a controller:
Actually the issue I had was the Symfony built-in dev server which is single-threaded, so requests can't be executed in parallel, while the CLI PHP is multi-threaded. I couldn't run the script in parallel through the dev server, request were queued, service script was never locked.
The lock component is working the same whether it's called from a command or a controller.
Using the lock like this in the service works fine:
use Symfony\Component\Lock\Factory;
use Symfony\Component\Lock\Store\FlockStore;
$store = new FlockStore(sys_get_temp_dir());
$factory = new Factory($store);
$lock = $factory->createLock('LOCK_KEY');
if ($lock->acquire()) {
//some locked code
$lock->release();
}
Upvotes: 1