diff --git a/examples/02-decide-action.php b/examples/02-decide-action.php new file mode 100644 index 0000000..cd32b45 --- /dev/null +++ b/examples/02-decide-action.php @@ -0,0 +1,55 @@ + 5, + 'trap_signals' => array( + SIGHUP => SIGTERM, + SIGTERM => SIGTERM, + ), + 'decide_action' => function($current_worker, $max_worker) use($start_time, &$prev_workers) { + $current_time = time(); + $max_worker = $max_worker + (int)(($current_time - $start_time) / 6); + if ( $max_worker > 10 ) { + $max_worker = 10; + } + if ( $max_worker !== $prev_workers ) { + echo "===> max worker: $prev_workers => $max_worker\n"; + $prev_workers = $max_worker; + } + return $current_worker < $max_worker; + }, + )); + while ($pp->signalReceived() !== SIGTERM) { + loadConfig(); + if ($pp->start()) { + continue; + } + workChildren(); + $pp->finish(); + } + $pp->waitAllChildren(); +} + +function loadConfig() +{ + echo "Load configuration\n"; +} + +function workChildren() +{ + for ($i = 1; $i <= 3; $i++) { + echo "Sleep $i seconds\n"; + sleep($i); + } +} diff --git a/lib/Prefork.php b/lib/Prefork.php index 3f99fcf..2b61ddd 100644 --- a/lib/Prefork.php +++ b/lib/Prefork.php @@ -27,10 +27,15 @@ class Prefork public $err_respawn_interval = 1; /** - * @var callable lamda function that is called when a child is reaped + * @var callable lambda function that is called when a child is reaped */ public $on_child_reap = null; + /** + * callable lambda fuction that decide action + */ + private $decide_action = null; + private $signal_received = null; private $manager_pid = null; private $in_child = false; @@ -43,6 +48,11 @@ function __construct(array $args = array()) ? $args['max_workers'] : $this->max_workers; $this->trap_signals = isset($args['trap_signals']) ? $args['trap_signals'] : $this->trap_signals; + $this->decide_action = isset($args['decide_action']) + ? $args['decide_action'] : null; + if ( isset($this->decide_action) && !is_callable($this->decide_action) ){ + die("decide_action should be callable\n"); + } foreach (array_keys($this->trap_signals) as $sig) { pcntl_signal($sig, array($this, '_signalHandler'), false); @@ -75,7 +85,16 @@ public function start() // main loop while ($this->signal_received === null) { $pid = null; - if (count(array_keys($this->worker_pids)) < $this->max_workers) { + $currect_workers = count(array_keys($this->worker_pids)); + $should_fork = $currect_workers < $this->max_workers; + if ( is_callable($this->decide_action) ) { + try { + $should_fork = call_user_func_array($this->decide_action,array($currect_workers, $this->max_workers)); + } catch ( \Exception $e ) { + printf("Exception. Use default action: %s\n",$e->getMessage()); + } + } + if ($should_fork) { $pid = pcntl_fork(); if ($pid === -1) { echo "fork failed!\n"; @@ -164,16 +183,16 @@ private function generation() return $this->generation; } - // PHP 5.2.x don't have lamda function private function _runChildReapCb($exit_pid, $status) { $cb = $this->on_child_reap; - if ($cb) { -/* + if (is_callable($cb)) { try { - $cb->($exit_pid, $status); - } -*/ + call_user_func_array($cb, array($exit_pid, $status)); + } catch (\Exception $e) { + // ignore + printf("Ignore Exception: %s\n",$e->getMessage()); + }; } } }