Skip to content

Instantly share code, notes, and snippets.

@mikemadisonweb
Forked from m8rge/CronException.php
Last active December 2, 2016 10:32
Show Gist options
  • Save mikemadisonweb/147d2b30f8d4e560c2f6c1a3d5f17cdd to your computer and use it in GitHub Desktop.
Save mikemadisonweb/147d2b30f8d4e560c2f6c1a3d5f17cdd to your computer and use it in GitHub Desktop.
Yii2 console controller behavior. Prevents double run console command
<?php
namespace console\controllers\behaviors;
use Yii;
use yii\base\ActionEvent;
use yii\base\Behavior;
use yii\base\Exception;
use yii\console\Controller;
/**
* Предотвращает одновременный запуск нескольких инстансов консольной команды
* Class OneInstanceBehavior
* @package console\components
*/
class OneInstanceBehavior extends Behavior
{
/**
* If process executes more than $longRunningTimeout seconds,
* it will be considered as long-running
* and warning message will be logged
* @var int seconds
*/
public $longRunningTimeout = 3600;
/**
* Start command if there isn't another active instance
* @var bool
*/
public $nonFailureShutdown = true;
/**
* @var string
*/
protected $lockFileName;
/**
* @return array
*/
public function events()
{
return [
Controller::EVENT_BEFORE_ACTION => 'checkInstance',
Controller::EVENT_AFTER_ACTION => 'cleanUp',
];
}
/**
* @param ActionEvent $event
* @throws Exception
*/
public function checkInstance($event)
{
$this->lockFileName = Yii::$app->runtimePath . '/' . str_replace('/', '-', $event->action->uniqueId) . '.lock';
if (file_exists($this->lockFileName)) {
$processExists = file_exists('/proc/' . trim(file_get_contents($this->lockFileName)));
if ($processExists) {
$event->isValid = false;
if (filemtime($this->lockFileName) + $this->longRunningTimeout < time()) {
throw new Exception("{$event->action->uniqueId} sleeped since " .
date('r', filemtime($this->lockFileName)));
}
} else {
if ($this->nonFailureShutdown) {
@unlink($this->lockFileName);
} else {
$event->isValid = false;
throw new Exception("{$event->action->uniqueId} failed since " .
date('r', filemtime($this->lockFileName)));
}
}
} else {
if (!file_put_contents($this->lockFileName, posix_getpid())) {
throw new Exception('Can\'t write lock file ' . $this->lockFileName);
}
}
}
/**
* @param ActionEvent $event
*/
public function cleanUp($event)
{
if ($event->result == 0) {
@unlink($this->lockFileName);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment