/** * Starts the event loop in the Forked process that will listen for messages * Note: Runs only in the worker (forked) process * @return void */ public function start() { // Define automatic restart intervals. We want to add some entropy to avoid having all worker processes // in a pool restart at the same time. Use a very crude technique to create a random number along a normal distribution. $entropy = round((mt_rand(-1000, 1000) + mt_rand(-1000, 1000) + mt_rand(-1000, 1000)) / 100, 0); $recycle = false; while (!Core_Daemon::is('parent') && !Core_Daemon::is('shutdown') && !$recycle) { // Give the CPU a break - Sleep for 1/20 a second. usleep(50000); if ($this->auto_restart) { $max_jobs = $this->call_count++ >= 25 + $entropy; $min_runtime = $this->daemon->runtime() >= 60 * 5; $max_runtime = $this->daemon->runtime() >= 60 * 30 + $entropy * 10; $recycle = $max_runtime || $min_runtime && $max_jobs; } if (mt_rand(1, 5) == 1) { $this->garbage_collector(); } if ($call = $this->via->get(self::WORKER_CALL, true)) { try { // If the current via supports it, calls can be cancelled while they are enqueued if ($call->status == self::CANCELLED) { $this->log("Call {$call->id} Cancelled By Mediator -- Skipping..."); continue; } $alias = $this instanceof Core_Worker_ObjectMediator ? $call->method : $this->alias; if (!$this->breakpoint(sprintf('[Call %s] Calling method in worker', $call->id, $alias), $call->id)) { $call->cancelled(); continue; } $call->running(); if (!$this->via->put($call)) { $this->log("Call {$call->id} Could Not Ack Running."); } $call->returned(call_user_func_array($this->get_callback($call->method), $call->args)); if (!$this->via->put($call)) { $this->log("Call {$call->id} Could Not Ack Complete."); } } catch (Exception $e) { $this->error($e->getMessage()); } } } $this->log("Recycling Worker..."); }