/** * */ public function run() { $this->shutdown = false; $this->host->start(); $this->logger->info('Host: Started host with ID: ' . $this->host->getId()); $this->logger->info(sprintf('Long poll: %sµs. Short poll: %sµs. Queue failure sleep: %ss', $this->sleepIntervalMicroSecsLongPoll, $this->sleepIntervalMicroSecsShortPoll, $this->sleepIntervalSecsFailed)); while (1) { $sleep = count($this->workers) === 0 ? $this->sleepIntervalMicroSecsLongPoll : $this->sleepIntervalMicroSecsShortPoll; $this->updateHostStatus(); $queueSets = $this->host->getQueueSets(); if (!$this->pause && !$this->shutdown) { if ($this->checkForJobs($queueSets)) { $sleep = 0; } elseif ($this->testing) { $this->shutdown = count($this->workers) === 0; } } if ($this->shutdown) { $this->logger->debug("Waiting for " . count($this->workers) . " workers"); if (count($this->workers) === 0) { // Don't wait for child processes - we know there aren't any $this->spork->zombieOkay(); break; } } foreach ($this->workers as $id => $worker) { if (($status = $worker->getExitStatus()) !== false) { $failed = $status !== 0; $job = $worker->getJob(); try { $this->host->failJob($job, new JobIncompleteException('Job was not marked complete within the process')); $failed = true; $this->logger->warning("Host: Job [ {$job->getId()} ] was not completed in the forked process which exited with status code: [ {$status} ] and was failed in the parent worker"); } catch (JobAlreadyCompleteException $e) { } if ($failed) { $worker->getQueueSet()->sleepFor($this->sleepIntervalSecsFailed); $this->logger->error("Host: Job [ {$job->getId()} ] failed, sleeping worker [ {$id} ] for [ {$this->sleepIntervalSecsFailed} ] microseconds"); } unset($this->workers[$id]); } elseif ($this->terminate || $this->host->shouldBeKilled($worker->getJob()->getId())) { $worker->terminate(); } } $this->logger->debug("Sleeping for {$sleep} µs"); usleep($sleep); } $this->logger->info('Host: Stopped'); $this->host->stop(); }
/** * Sends shutdown to child instances, which run the worker(s) */ protected function shutdownWorkersFromParent() { $this->logger->info("Shutting down all workers"); // send initial signal.. foreach ($this->workers as $worker) { $name = $worker->getName(); if ($this->countRunning($name)) { /** @var Fork $fork **/ foreach ($this->forks[$name] as $fork) { $fork->kill($this->shutdownSignal); } } } // wait for shutdown $tries = $this->shutdownTimeout * 10; for ($try = $tries; $try > 0; $try--) { BuiltIn::doUsleep(100000); $resisting = 0; foreach ($this->workers as $worker) { $name = $worker->getName(); $resisting += $this->countRunning($name); } if (!$resisting) { break; } elseif ($try % 10 === 0) { $this->logger->info("{$resisting} resisting worker(s) still remaining - " . $try / 10 . " seconds till slaughter"); } } // slaughter survivors /** @var Fork[] $forks */ foreach ($this->forks as $name => $forks) { foreach ($forks as $fork) { if ($this->reallyRunning($fork)) { $this->event->dispatch(Event::EVENT_WORKER_KILL, new Event($this->workers[$name]), array($fork)); $fork->kill(SIGKILL); try { $fork->wait(true); } catch (ProcessControlException $e) { // well, it's a SIG KILL.. } } } } $this->manager->zombieOkay(true); }