Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Yii2 console controller behavior. Prevents double run console command
<?php
namespace console\components;
use Yii;
use yii\base\ActionEvent;
use yii\base\Behavior;
use yii\base\Exception;
use yii\console\Controller;
/**
* yii\console\Controller behavior
* Prevents double run console command
*/
class OneInstance extends Behavior
{
/**
* @var string
*/
protected $lockFileName;
/**
* 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; // 1h
/**
* Start command if there isn't another active instance. Even last run was unsuccessfully completed
* @var bool
*/
public $nonFailureShutdown = false;
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