Пример #1
0
 /**
  * if job is sync then we get worker and try execute job
  * else if job is Async then redirect to other queue
  *
  * REMEMBER: Queue name is equal to Worker class name (through all "Cronario")
  *
  * @param AbstractJob|Job $job
  *
  * @throws ResultException
  * @throws WorkerException
  */
 protected function doJob(AbstractJob $job)
 {
     $gatewayClass = $this->analiseGateway($job);
     if ($job->isSync()) {
         $worker = AbstractWorker::factory($gatewayClass);
         return $worker($job);
     }
     if (!$job->hasAttempt()) {
         throw new ResultException(ResultException::FAILURE_MAX_ATTEMPTS);
     }
     // redirect result for new gateway class
     $job->addDebug(['set_gateway' => $gatewayClass]);
     $job->setWorkerClass($gatewayClass)->save();
     throw new ResultException(ResultException::REDIRECT_GATEWAY_CLASS);
 }
Пример #2
0
 /**
  * @param AbstractJob $parentJob
  *
  * @return ResultException|null
  */
 public function __invoke(AbstractJob $parentJob = null)
 {
     if (null !== $parentJob) {
         $this->setParentId($parentJob->getId())->setAuthor($parentJob->getAuthor());
     }
     $this->save();
     try {
         if ($this->isSync()) {
             $worker = AbstractWorker::factory($this->getWorkerClass());
             $worker($this);
         } else {
             $this->setResult(new ResultException(ResultException::R_QUEUED));
             $this->putIntoQueue();
             $this->save();
         }
     } catch (\Exception $ex) {
         $this->setResult($ex);
         $this->save();
     }
     return $this->getResult();
 }
Пример #3
0
 /**
  * @return bool
  */
 public function run()
 {
     $file = $this->getBootstrapFile();
     require_once $file;
     $this->startManagerLive();
     $workerClass = $this->getWorkerClass();
     $managerId = $this->getId();
     $logger = $this->getLogger();
     $queue = $this->getQueue();
     $logger->info("Manager {$managerId} start work {$workerClass}", [__NAMESPACE__]);
     try {
         $worker = AbstractWorker::factory($workerClass);
     } catch (Exception\WorkerException $ex) {
         $queue->stop($workerClass);
         $logger->warning($ex->getMessage(), [__NAMESPACE__]);
         $logger->info("Manager {$managerId} Queue stop {$workerClass}", [__NAMESPACE__]);
         $logger->info("Manager {$managerId} finish work {$workerClass}", [__NAMESPACE__]);
         return false;
     }
     try {
         $waitForJob = $this->getWorkerConfig(AbstractWorker::CONFIG_P_MANAGER_IDLE_DIE_DELAY);
         while ($jobId = $queue->reserveJob($workerClass, $waitForJob)) {
             if ($jobId === false) {
                 $logger->debug("Manager {$managerId} queue is empty so {$workerClass}", [__NAMESPACE__]);
                 break;
             }
             $logger->debug("Manager {$managerId} reserve job {$jobId}", [__NAMESPACE__]);
             $job = null;
             try {
                 /** @var AbstractJob $job */
                 $job = Facade::getStorage($this->getAppId())->find($jobId);
             } catch (JobException $ex) {
                 $logger->warning($ex->getMessage(), [__NAMESPACE__]);
                 $queue->deleteJob($jobId);
                 continue;
             }
             if ($job === null) {
                 $logger->error("Manager {$managerId} job is not instanceof of AbstractJob {$jobId}", [__NAMESPACE__]);
                 $queue->deleteJob($jobId);
                 continue;
             }
             $logger->debug("Manager {$managerId} Worker start working at {$jobId}...", [__NAMESPACE__]);
             // DO JOB!
             /** @var ResultException $result */
             $result = $worker($job);
             $logger->debug("Manager {$managerId}  Worker finish working at {$jobId} : {$result->getGlobalCode()}", [__NAMESPACE__]);
             if ($result instanceof ResultException) {
                 if ($result->isSuccess()) {
                     $queue->deleteJob($jobId);
                     $logger->debug("Manager {$managerId} Job ResultException isSuccess {$jobId}", [__NAMESPACE__]);
                     $this->eventTrigger(self::EVENT_SUCCESS);
                 } elseif ($result->isFailure()) {
                     $queue->deleteJob($jobId);
                     $logger->debug("Manager {$managerId} Job ResultException isFail {$jobId}", [__NAMESPACE__]);
                     $this->eventTrigger(self::EVENT_FAIL);
                 } elseif ($result->isError()) {
                     $queue->buryJob($jobId);
                     $logger->debug("Manager {$managerId} Job ResultException isError {$jobId}", [__NAMESPACE__]);
                     $this->eventTrigger(self::EVENT_ERROR);
                 } elseif ($result->isRetry()) {
                     $logger->debug("Manager {$managerId} Job ResultException isRetry {$jobId}", [__NAMESPACE__]);
                     $job->addAttempts();
                     $job->save();
                     // important this will saved result to job !!!
                     $attemptCount = $job->getAttempts();
                     $attemptDelay = $job->countAttemptQueueDelay();
                     // can be new worker class "like redirect in sms/alpha to sms"
                     $gatewayClass = $job->getWorkerClass();
                     $queue->deleteJob($jobId);
                     if ($job->hasAttempt()) {
                         $logger->debug("job {$jobId} has {$attemptCount} attempts (max:{$job->getAttemptsMax()}) and will be delayed {$attemptDelay}", [__NAMESPACE__]);
                         $queue->putJob($gatewayClass, $jobId, $attemptDelay);
                         $this->eventTrigger(self::EVENT_RETRY);
                     } else {
                         $logger->debug("job {$jobId} has {$attemptCount} attempts (max:{$job->getAttemptsMax()})  and will have bad result", [__NAMESPACE__]);
                         $job->setResult(new ResultException(ResultException::FAILURE_MAX_ATTEMPTS));
                         $job->save();
                         $this->eventTrigger(self::EVENT_FAIL);
                     }
                 } elseif ($result->isRedirect()) {
                     $queue->deleteJob($jobId);
                     $queue->putJob($job->getWorkerClass(), $jobId);
                     $logger->debug("Job ResultException isRedirect {$jobId} to {$job->getWorkerClass()}", [__NAMESPACE__]);
                     $this->eventTrigger(self::EVENT_REDIRECT);
                 } else {
                     $queue->deleteJob($jobId);
                     $logger->error("Undefined result job id : {$jobId}", [__NAMESPACE__]);
                 }
             } else {
                 $logger->error('job result is not type of AbstractResultException', [__NAMESPACE__]);
             }
             if ($job->getSchedule()) {
                 $newJob = clone $job;
                 $newJob();
                 $logger->debug("Manager {$managerId} catch daemon  shutdown, finish listening queue", [__NAMESPACE__]);
             }
             if ($this->isLimitsExceeded() || $this->isProducerShutDown()) {
                 break;
             }
             $this->waitDelay();
         }
     } catch (\Exception $ex) {
         $logger->warning($ex->getMessage());
     }
     $logger->info("Manager {$managerId} finish work {$workerClass}", [__NAMESPACE__]);
     $this->finishManagerLive();
     return true;
 }