<?php
namespace League\Tactician\Plugins;
use League\Tactician\Middleware;
/**
* If another command is already being executed, locks the command bus and
* queues the new incoming commands until the first has completed.
*/
class LockingMiddleware implements Middleware
{
/**
* @var bool
*/
private $isExecuting;
/**
* @var callable[]
*/
private $queue = [];
/**
* Execute the given command... after other running commands are complete.
*
* @param object $command
* @param callable $next
*
* @throws \Exception
*
* @return mixed|void
*/
public function execute($command, callable $next)
{
$this->queue[] = function () use ($command, $next) {
return $next($command);
};
if ($this->isExecuting) {
return;
}
$this->isExecuting = true;
try {
$returnValue = $this->executeQueuedJobs();
} catch (\Exception $e) {
$this->isExecuting = false;
$this->queue = [];
throw $e;
}
$this->isExecuting = false;
return $returnValue;
}
/**
* Process any pending commands in the queue. If multiple, jobs are in the
* queue, only the first return value is given back.
*
* @return mixed
*/
protected function executeQueuedJobs()
{
$returnValues = [];
while ($resumeCommand = array_shift($this->queue)) {
$returnValues[] = $resumeCommand();
}
return array_shift($returnValues);
}
}