CacheCommandMutex.php
TLDR
This file contains the implementation of the CacheCommandMutex
class in the Illuminate\Console
namespace. This class is responsible for creating, checking the existence, and releasing mutexes for console commands using a cache store.
Methods
create
This method attempts to obtain a command mutex for the given command. It uses the cache store specified in the class to create a lock or add a cache entry with a true value and expiration time. If the cache store supports locks, it uses the lock() method to create a lock and returns the result. Otherwise, it adds a cache entry using the add() method and returns the result.
exists
This method determines if a command mutex exists for the given command. It uses the cache store specified in the class to check if a cache entry with the command mutex name exists. If the cache store supports locks, it creates a lock and checks if it exists. If it exists, it releases the lock before returning the opposite result.
forget
This method releases the mutex for the given command. It uses the cache store specified in the class to either release the lock or forget the cache entry with the command mutex name. If the cache store supports locks, it uses the forceRelease() method to release the lock and returns the result. Otherwise, it uses the forget() method and returns the result.
commandMutexName
This method returns the isolatable command mutex name for the given command. It constructs the base name with the format 'framework/command-' + command name
. If the command has a method isolatableId()
, it appends '-'+ command->isolatableId()
to the base name. Finally, it returns the constructed name.
useStore
This method specifies the cache store that should be used. It sets the store
property of the class with the given store parameter and returns $this
.
shouldUseLocks
This method determines if the given cache store should use locks for command mutexes. It checks if the store is an instance of LockProvider
and not an instance of DynamoDbStore
. It returns the result.
<?php
namespace Illuminate\Console;
use Carbon\CarbonInterval;
use Illuminate\Cache\DynamoDbStore;
use Illuminate\Contracts\Cache\Factory as Cache;
use Illuminate\Contracts\Cache\LockProvider;
use Illuminate\Support\InteractsWithTime;
class CacheCommandMutex implements CommandMutex
{
use InteractsWithTime;
/**
* The cache factory implementation.
*
* @var \Illuminate\Contracts\Cache\Factory
*/
public $cache;
/**
* The cache store that should be used.
*
* @var string|null
*/
public $store = null;
/**
* Create a new command mutex.
*
* @param \Illuminate\Contracts\Cache\Factory $cache
*/
public function __construct(Cache $cache)
{
$this->cache = $cache;
}
/**
* Attempt to obtain a command mutex for the given command.
*
* @param \Illuminate\Console\Command $command
* @return bool
*/
public function create($command)
{
$store = $this->cache->store($this->store);
$expiresAt = method_exists($command, 'isolationLockExpiresAt')
? $command->isolationLockExpiresAt()
: CarbonInterval::hour();
if ($this->shouldUseLocks($store->getStore())) {
return $store->getStore()->lock(
$this->commandMutexName($command),
$this->secondsUntil($expiresAt)
)->get();
}
return $store->add($this->commandMutexName($command), true, $expiresAt);
}
/**
* Determine if a command mutex exists for the given command.
*
* @param \Illuminate\Console\Command $command
* @return bool
*/
public function exists($command)
{
$store = $this->cache->store($this->store);
if ($this->shouldUseLocks($store->getStore())) {
$lock = $store->getStore()->lock($this->commandMutexName($command));
return tap(! $lock->get(), function ($exists) use ($lock) {
if ($exists) {
$lock->release();
}
});
}
return $this->cache->store($this->store)->has($this->commandMutexName($command));
}
/**
* Release the mutex for the given command.
*
* @param \Illuminate\Console\Command $command
* @return bool
*/
public function forget($command)
{
$store = $this->cache->store($this->store);
if ($this->shouldUseLocks($store->getStore())) {
return $store->getStore()->lock($this->commandMutexName($command))->forceRelease();
}
return $this->cache->store($this->store)->forget($this->commandMutexName($command));
}
/**
* Get the isolatable command mutex name.
*
* @param \Illuminate\Console\Command $command
* @return string
*/
protected function commandMutexName($command)
{
$baseName = 'framework'.DIRECTORY_SEPARATOR.'command-'.$command->getName();
return method_exists($command, 'isolatableId')
? $baseName.'-'.$command->isolatableId()
: $baseName;
}
/**
* Specify the cache store that should be used.
*
* @param string|null $store
* @return $this
*/
public function useStore($store)
{
$this->store = $store;
return $this;
}
/**
* Determine if the given store should use locks for command mutexes.
*
* @param \Illuminate\Contracts\Cache\Store $store
* @return bool
*/
protected function shouldUseLocks($store)
{
return $store instanceof LockProvider && ! $store instanceof DynamoDbStore;
}
}