-
-
Save s00d/554a0ce5a485f714f4341d510e2eced1 to your computer and use it in GitHub Desktop.
This file contains hidden or 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/' . strtolower(str_replace(':', '_', $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