Пример #1
0
 /**
  * starts worker
  */
 public function run()
 {
     declare (ticks=1);
     $this->startup();
     $this->who = 'master:' . $this->workerName;
     $this->logContext = ['type' => $this->who, 'job.identifier' => null];
     $this->logger->info('{type}: Worker started', $this->logContext);
     $this->logger->info('{type}: monitoring the following queues (in order), {queues}', ['type' => $this->who, 'queues' => implode(', ', $this->queues)]);
     $did_work = false;
     while (true) {
         if ($this->shutdown) {
             $this->logger->info('{type}: Shutting down', $this->logContext);
             break;
         }
         while ($this->paused) {
             usleep(250000);
         }
         if ($did_work) {
             $this->logger->debug('{type}: Looking for work', $this->logContext);
             $this->updateProcLine('Waiting for ' . implode(',', $this->queues) . ' with interval ' . $this->interval);
             $did_work = false;
         }
         $job = $this->reserve();
         if (!$job) {
             if ($this->interval == 0) {
                 break;
             }
             usleep($this->interval * 1000000);
             continue;
         }
         $this->job = $job;
         $this->logContext['job.identifier'] = $job->getId();
         // fork processes
         $this->childStart();
         $this->watchdogStart();
         // Parent process, sit and wait
         $proc_line = 'Forked ' . $this->childPID . ' at ' . strftime('%F %T');
         $this->updateProcLine($proc_line);
         $this->logger->info($proc_line, $this->logContext);
         while ($this->childProcesses > 0) {
             $status = null;
             $pid = pcntl_wait($status, WUNTRACED);
             if ($pid > 0) {
                 if ($pid === $this->childPID) {
                     $exited = $this->childProcessStatus($status);
                 } else {
                     if ($pid === $this->watchdogPID) {
                         $exited = $this->watchdogProcessStatus($status);
                     } else {
                         // unexpected?
                         $this->logger->info(sprintf("master received status for unknown PID %d; exiting\n", $pid));
                         exit(1);
                     }
                 }
                 if ($exited) {
                     --$this->childProcesses;
                     switch ($pid) {
                         case $this->childPID:
                             $this->childPID = null;
                             if ($this->watchdogPID) {
                                 // shutdown watchdog immediately if child has exited
                                 posix_kill($this->watchdogPID, SIGKILL);
                             }
                             break;
                         case $this->watchdogPID:
                             $this->watchdogPID = null;
                             break;
                     }
                 }
             }
         }
         foreach ($this->sockets as $socket) {
             socket_close($socket);
         }
         $this->sockets = [];
         $this->job = null;
         $this->logContext['job.identifier'] = null;
         $did_work = true;
         /**
          * We need to reconnect due to bug in Redis library that always sends QUIT on destruction of \Redis
          * rather than just leaving socket around. This call will sometimes generate a broken pipe notice
          */
         $old = error_reporting();
         error_reporting($old & ~E_NOTICE);
         try {
             $this->client->reconnect();
         } finally {
             error_reporting($old);
         }
     }
 }