Skip to content

Instantly share code, notes, and snippets.

@jippi
Created September 13, 2012 20:37
Show Gist options
  • Select an option

  • Save jippi/3717456 to your computer and use it in GitHub Desktop.

Select an option

Save jippi/3717456 to your computer and use it in GitHub Desktop.
<?php
App::uses('WorkerTask', 'Console/Command');
/**
* ProccessManagement Task
*
* Helps with CLI handling of mutex and signals
*
* IMPORTANT:
*
* Remember to add the following code at the top of Config/bootstrap.php
* if you do not, signal handling will fail silently
*
* ```
* if (php_sapi_name() === 'cli') {
* declare(ticks = 1);
* }
* ```
*/
class ProccessManagementTask extends AppShell {
/**
* We need our lock file to be stored as a class property so it
* won't get free()'d because there is no reference to it.
*
* That would free the lock on the file too :)
*
* @var resource
*/
protected $_lockHandle;
/**
* Make sure to get exclusive right to run this process, based on a file
*
* Should be used together with ProccessManagement->getLockFile()
*
* @param string $lockFile
* @return void
*/
public function mutex($lockFile) {
$this->log(sprintf('Using lock file: %s', $lockFile), 'info');
$this->_lockHandle = fopen($lockFile, 'w+');
if (!flock($this->_lockHandle, LOCK_EX | LOCK_NB)) {
$this->log(sprintf('Could not get exclusive lock, other process must be running'), 'warning');
$this->_stop(-1);
}
}
/**
* Get a lock file based on Nodes best practices
*
* The identifier should be something unique and static for each process
*
* @param Object $class The primary invoked Shell
* @param string $identifier A unique identifier
* @return string
*/
public function getLockFile(Object $class, $identifier) {
return $lockFile = sprintf('/tmp/%s_%s_%s.lock', Nodes\Environment::getProjectName(), get_class($class), $identifier);
}
/**
* Register signals and when they are triggered, write a Signal.shutdown property
*
* REMEMBER TO HAVE declare(ticks = 1); in the top of your Config/bootstrap.php file
*
* @return void
*/
public function signals() {
Configure::write('Signal.shutdown', false);
$this->log('Installing signal handlers', 'info');
pcntl_signal(SIGTERM, array($this, "sig_handler"));
pcntl_signal(SIGHUP, array($this, "sig_handler"));
pcntl_signal(SIGUSR1, array($this, "sig_handler"));
pcntl_signal(SIGUSR2, array($this, "sig_handler"));
}
/**
* Simply set a Signal flag and do nothing more
*
* @param integer $signo
* @return void
*/
public function sig_handler($signo) {
Configure::write('Signal.shutdown', true);
}
}
/**
* Starts a Gearman worker long-living process
*
* @return void
**/
public function server() {
$identifier = isset($this->params['process_id']) ? $this->params['process_id'] : 'cli';
$this->ProccessManagement->mutex($this->ProccessManagement->getLockFile($this, $identifier));
$this->ProccessManagement->signals();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment