Last active
April 4, 2018 07:30
-
-
Save Ellrion/c01867e98fa94a65db5d8e10c0018e83 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Console; | |
use Illuminate\Console\Command; | |
use Symfony\Component\Console\Input\InputInterface; | |
use Symfony\Component\Console\Output\OutputInterface; | |
trait OverlappingControlled | |
{ | |
/** | |
* Дескриптор файла блокировки. | |
* | |
* @var resource | |
*/ | |
protected $lockHandle; | |
/** | |
* Возвращает путь к файлу блокировки. | |
* По-умолчанию, это "storage/lock/(имя команды).lock". | |
* | |
* @return string | |
*/ | |
protected function getLockPath() | |
{ | |
return storage_path('lock/' . snake_case($this->name) . '.lock'); | |
} | |
/** | |
* Возвращает флаги для захвата блокировки. | |
* | |
* @return int | |
*/ | |
protected function getLockFlags() | |
{ | |
return empty($this->withoutOverlapping) ? LOCK_UN : LOCK_EX | LOCK_NB; | |
} | |
/** | |
* Захват блокировки. | |
* | |
* @return bool | |
*/ | |
protected function lock() | |
{ | |
if (is_resource($this->lockHandle)) { | |
$this->free(); | |
} | |
$this->lockHandle = fopen($this->getLockPath(), 'c'); | |
$lock = false !== $this->lockHandle && flock($this->lockHandle, $this->getLockFlags()); | |
if (false === $lock) { | |
$this->lockHandle = null; | |
} | |
return $lock; | |
} | |
/** | |
* Освобождение блокировки. | |
* | |
* @return bool | |
*/ | |
protected function free() | |
{ | |
if (!is_resource($this->lockHandle)) { | |
return false; | |
} | |
fflush($this->lockHandle); | |
flock($this->lockHandle, LOCK_UN); | |
fclose($this->lockHandle); | |
return $this->removeLockFile(); | |
} | |
/** | |
* Удаление файла блокировки | |
* | |
* @return bool | |
*/ | |
protected function removeLockFile() | |
{ | |
try { | |
$file = $this->getLockPath(); | |
if (is_file($file) && !is_link($file)) { | |
if (@unlink($file) === false) { | |
throw new \Exception(sprintf('Failed to remove lock file "%s".', $file)); | |
} | |
} else { | |
return false; | |
} | |
return true; | |
} catch (\Exception $e) { | |
return false; | |
} | |
} | |
/** | |
* Проверяет, используется ли блокировка в управлении запуском. | |
* | |
* @return bool | |
*/ | |
protected function isUsedLock() | |
{ | |
return !empty($this->withoutOverlapping) && !$this->option('force'); | |
} | |
/** | |
* Execute the console command. | |
* | |
* @param \Symfony\Component\Console\Input\InputInterface $input | |
* @param \Symfony\Component\Console\Output\OutputInterface $output | |
* @return mixed | |
*/ | |
protected function execute(InputInterface $input, OutputInterface $output) | |
{ | |
if (!$this->isUsedLock() || $this->lock()) { | |
$result = parent::execute($input, $output); | |
} | |
$this->free(); | |
return $result; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
return storage_path() . '/lock/' . strtolower(str_replace(':', '_', $this->name)) . '.lock';
Имхо, будет красивее заменив строчку на:
return storage_path('lock/' . snake_case($this->name) . '.lock');