Skip to content

Commit

Permalink
Merge branch 'master' into 6.x
Browse files Browse the repository at this point in the history
  • Loading branch information
dmitry-ivanov committed Feb 27, 2020
2 parents c4287c0 + 9a7c650 commit ccd665f
Show file tree
Hide file tree
Showing 10 changed files with 271 additions and 92 deletions.
92 changes: 63 additions & 29 deletions src/Mutex.php
Expand Up @@ -2,39 +2,70 @@

namespace Illuminated\Console;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Redis as RedisFacade;
use NinjaMutex\Lock\FlockLock;
use NinjaMutex\Lock\MemcachedLock;
use NinjaMutex\Lock\MySqlLock;
use NinjaMutex\Mutex as Ninja;
use Illuminate\Console\Command;
use NinjaMutex\Lock\PhpRedisLock;
use NinjaMutex\Lock\MemcachedLock;
use NinjaMutex\Lock\PredisRedisLock;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Redis as RedisFacade;
use NinjaMutex\Mutex as NinjaMutex;

/**
* @mixin Ninja
* @mixin \NinjaMutex\Mutex
*/
class Mutex
{
/**
* The console command.
*
* @var \Illuminate\Console\Command
*/
private $command;
private $strategy;
private $ninja;

/**
* The ninja mutex.
*
* @var \NinjaMutex\Mutex
*/
private $ninjaMutex;

/**
* The ninja mutex lock.
*
* @var \NinjaMutex\Lock\LockAbstract
*/
private $ninjaMutexLock;

/**
* Create a new instance of the mutex.
*
* @param \Illuminate\Console\Command|\Illuminated\Console\WithoutOverlapping $command
* @return void
*/
public function __construct(Command $command)
{
$this->command = $command;
$this->strategy = $this->getStrategy();
$this->ninja = new Ninja($command->getMutexName(), $this->strategy);

$mutexName = $command->getMutexName();
$this->ninjaMutexLock = $this->getNinjaMutexLock();
$this->ninjaMutex = new NinjaMutex($mutexName, $this->ninjaMutexLock);
}

public function getStrategy()
/**
* Get the ninja mutex lock.
*
* @return \NinjaMutex\Lock\LockAbstract
*/
public function getNinjaMutexLock()
{
if (!empty($this->strategy)) {
return $this->strategy;
if (!empty($this->ninjaMutexLock)) {
return $this->ninjaMutexLock;
}

switch ($this->command->getMutexStrategy()) {
$strategy = $this->command->getMutexStrategy();
switch ($strategy) {
case 'mysql':
return new MySqlLock(
config('database.connections.mysql.username'),
Expand All @@ -55,27 +86,30 @@ public function getStrategy()
}
}

/**
* Get the redis lock.
*
* @param string $client
* @return \NinjaMutex\Lock\LockAbstract
*/
private function getRedisLock($client)
{
if ($client === 'phpredis') {
return new PhpRedisLock($this->getPhpRedisClient());
}

return new PredisRedisLock($this->getPredisClient());
}
$redis = RedisFacade::connection()->client();

public function getPhpRedisClient()
{
return RedisFacade::connection()->client();
}

public function getPredisClient()
{
return RedisFacade::connection()->client();
return $client === 'phpredis'
? new PhpRedisLock($redis)
: new PredisRedisLock($redis);
}

/**
* Forward method calls to ninja mutex.
*
* @param string $method
* @param mixed $parameters
* @return mixed
*/
public function __call($method, $parameters)
{
return call_user_func_array([$this->ninja, $method], $parameters);
return call_user_func_array([$this->ninjaMutex, $method], $parameters);
}
}
83 changes: 78 additions & 5 deletions src/WithoutOverlapping.php
Expand Up @@ -7,55 +7,128 @@

trait WithoutOverlapping
{
/**
* Overwrite the console command initialization.
*
* @param \Symfony\Component\Console\Input\InputInterface $input
* @param \Symfony\Component\Console\Output\OutputInterface $output
* @return void
*/
protected function initialize(InputInterface $input, OutputInterface $output)
{
$this->initializeMutex();

parent::initialize($input, $output);
}

/**
* Initialize the mutex.
*
* @return void
*/
protected function initializeMutex()
{
$mutex = new Mutex($this);
if (!$mutex->acquireLock($this->getMutexTimeout())) {

$timeout = $this->getMutexTimeout();
if (!$mutex->acquireLock($timeout)) {
throw new MutexRuntimeException('Command is running now!');
}

register_shutdown_function([$this, 'releaseMutexLock'], $mutex);
}

/**
* Get the mutex strategy.
*
* Currently supported: "file", "mysql", "redis" and "memcached".
*
* @return string
*/
public function getMutexStrategy()
{
return property_exists($this, 'mutexStrategy') ? $this->mutexStrategy : 'file';
return property_exists($this, 'mutexStrategy')
? $this->mutexStrategy
: 'file';
}

/**
* Set the mutex strategy.
*
* Currently supported: "file", "mysql", "redis" and "memcached".
*
* @param string $strategy
* @return void
*/
public function setMutexStrategy($strategy)
{
$this->mutexStrategy = $strategy;
}

/**
* Get the mutex timeout in milliseconds.
*
* Possible values:
* `0` - check without waiting;
* `{milliseconds}` - check, and wait for a maximum of milliseconds specified;
* `null` - wait, till running command finish its execution;
*
* @return int|null
*/
public function getMutexTimeout()
{
return property_exists($this, 'mutexTimeout') ? $this->mutexTimeout : 0;
return property_exists($this, 'mutexTimeout')
? $this->mutexTimeout
: 0;
}

/**
* Set the mutex timeout in milliseconds.
*
* Possible values:
* `0` - check without waiting;
* `{milliseconds}` - check, and wait for a maximum of milliseconds specified;
* `null` - wait, till running command finish its execution;
*
* @param int|null $timeout
* @return void
*/
public function setMutexTimeout($timeout)
{
$this->mutexTimeout = $timeout;
}

/**
* Get the mutex name.
*
* @return string
*/
public function getMutexName()
{
$name = $this->getName();
$arguments = json_encode($this->argument());
return "icmutex-{$name}-" . md5($arguments);
$argumentsHash = md5(json_encode($this->argument()));

return "icmutex-{$name}-{$argumentsHash}";
}

/**
* Get the mutex file storage path.
*
* @return string
*/
public function getMutexFileStorage()
{
return storage_path('app');
}

/**
* Release the mutex lock.
*
* Called automatically, because it's registered as a shutdown function.
*
* @param \Illuminated\Console\Mutex $mutex
* @return void
*/
public function releaseMutexLock(Mutex $mutex)
{
$mutex->releaseLock();
Expand Down

0 comments on commit ccd665f

Please sign in to comment.