forked from chrisboulton/php-resque
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor forking code into Resque_JobStrategy_Interface
- Loading branch information
1 parent
aae1683
commit e0c115d
Showing
4 changed files
with
205 additions
and
50 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
<?php | ||
/** | ||
* Seperates the job execution environment from the worker via pcntl_fork | ||
* | ||
* @package Resque/JobStrategy | ||
* @author Chris Boulton <chris@bigcommerce.com> | ||
* @author Erik Bernharsdon <bernhardsonerik@gmail.com> | ||
* @license http://www.opensource.org/licenses/mit-license.php | ||
*/ | ||
class Resque_JobStrategy_Fork extends Resque_JobStrategy_InProcess | ||
{ | ||
/** | ||
* @param int|null 0 for the forked child, the PID of the child for the parent, or null if no child. | ||
*/ | ||
protected $child; | ||
|
||
/** | ||
* @param Resque_Worker Instance of Resque_Worker that is starting jobs | ||
*/ | ||
protected $worker; | ||
|
||
/** | ||
* Set the Resque_Worker instance | ||
* | ||
* @param Resque_Worker $worker | ||
*/ | ||
public function setWorker(Resque_Worker $worker) | ||
{ | ||
$this->worker = $worker; | ||
} | ||
|
||
/** | ||
* Seperate the job from the worker via pcntl_fork | ||
* | ||
* @param Resque_Job $job | ||
*/ | ||
public function perform(Resque_Job $job) | ||
{ | ||
$this->child = $this->fork(); | ||
|
||
// Forked and we're the child. Run the job. | ||
if ($this->child === 0) { | ||
parent::perform($job); | ||
exit(0); | ||
} | ||
|
||
// Parent process, sit and wait | ||
if($this->child > 0) { | ||
$status = 'Forked ' . $this->child . ' at ' . strftime('%F %T'); | ||
$this->worker->updateProcLine($status); | ||
$this->worker->log($status, Resque_Worker::LOG_VERBOSE); | ||
|
||
// Wait until the child process finishes before continuing | ||
pcntl_wait($status); | ||
$exitStatus = pcntl_wexitstatus($status); | ||
if($exitStatus !== 0) { | ||
$job->fail(new Resque_Job_DirtyExitException( | ||
'Job exited with exit code ' . $exitStatus | ||
)); | ||
} | ||
} | ||
|
||
$this->child = null; | ||
} | ||
|
||
/** | ||
* Force an immediate shutdown of the worker, killing any child jobs | ||
* currently working | ||
*/ | ||
public function shutdown() | ||
{ | ||
if (!$this->child) { | ||
$this->worker->log('No child to kill.', Resque_Worker::LOG_VERBOSE); | ||
return; | ||
} | ||
|
||
$this->worker->log('Killing child at '.$this->child, Resque_Worker::LOG_VERBOSE); | ||
if(exec('ps -o pid,state -p ' . $this->child, $output, $returnCode) && $returnCode != 1) { | ||
$this->worker->log('Killing child at ' . $this->child, Resque_Worker::LOG_VERBOSE); | ||
posix_kill($this->child, SIGKILL); | ||
$this->child = null; | ||
} | ||
else { | ||
$this->worker->log('Child ' . $this->child . ' not found, restarting.', Resque_Worker::LOG_VERBOSE); | ||
$this->worker->shutdown(); | ||
} | ||
} | ||
|
||
/** | ||
* Attempt to fork a child process from the parent to run a job in. | ||
* | ||
* Return values are those of pcntl_fork(). | ||
* | ||
* @return int 0 for the forked child, or the PID of the child for the parent. | ||
* @throws RuntimeException When pcntl_fork returns -1 | ||
*/ | ||
private function fork() | ||
{ | ||
$pid = pcntl_fork(); | ||
if($pid === -1) { | ||
throw new RuntimeException('Unable to fork child worker.'); | ||
} | ||
|
||
return $pid; | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
<?php | ||
/** | ||
* Runs the job in the same process as Resque_Worker | ||
* | ||
* @package Resque/JobStrategy | ||
* @author Chris Boulton <chris@bigcommerce.com> | ||
* @author Erik Bernharsdon <bernhardsonerik@gmail.com> | ||
* @license http://www.opensource.org/licenses/mit-license.php | ||
*/ | ||
class Resque_JobStrategy_InProcess implements Resque_JobStrategy_Interface | ||
{ | ||
/** | ||
* @param Resque_Worker Instance of Resque_Worker that is starting jobs | ||
*/ | ||
protected $worker; | ||
|
||
/** | ||
* Set the Resque_Worker instance | ||
* | ||
* @param Resque_Worker $worker | ||
*/ | ||
public function setWorker(Resque_Worker $worker) | ||
{ | ||
$this->worker = $worker; | ||
} | ||
|
||
/** | ||
* Run the job in the worker process | ||
* | ||
* @param Resque_Job $job | ||
*/ | ||
public function perform(Resque_Job $job) | ||
{ | ||
$status = 'Processing ' . $job->queue . ' since ' . strftime('%F %T'); | ||
$this->worker->updateProcLine($status); | ||
$this->worker->log($status, Resque_Worker::LOG_VERBOSE); | ||
$this->worker->perform($job); | ||
} | ||
|
||
/** | ||
* Force an immediate shutdown of the worker, killing any child jobs | ||
* currently working | ||
*/ | ||
public function shutdown() | ||
{ | ||
$this->worker->log('No child to kill.', Resque_Worker::LOG_VERBOSE); | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
<?php | ||
/** | ||
* Interface that all job strategy backends should implement. | ||
* | ||
* @package Resque/JobStrategy | ||
* @author Chris Boulton <chris@bigcommerce.com> | ||
* @author Erik Bernharsdon <bernhardsonerik@gmail.com> | ||
* @license http://www.opensource.org/licenses/mit-license.php | ||
*/ | ||
interface Resque_JobStrategy_Interface | ||
{ | ||
/** | ||
* Set the Resque_Worker instance | ||
* | ||
* @param Resque_Worker $worker | ||
*/ | ||
function setWorker(Resque_Worker $worker); | ||
|
||
/** | ||
* Seperates the job execution context from the worker and calls $worker->perform($job). | ||
* | ||
* @param Resque_Job $job | ||
*/ | ||
function perform(Resque_Job $job); | ||
|
||
/** | ||
* Force an immediate shutdown of the worker, killing any child jobs | ||
* currently working | ||
*/ | ||
function shutdown(); | ||
} |
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