/**
  * {@inheritDoc}
  */
 public function statsJob($job)
 {
     if ($this->dispatcher) {
         $this->dispatcher->dispatch(CommandEvent::STATS_JOB, new CommandEvent($this, ['job' => $job]));
     }
     return $this->pheanstalk->statsJob($job);
 }
 /**
  * Delete given job and create new job with old or passed params
  *
  * @param int $jobId
  * @param int $priority
  * @param int $delay
  */
 public function reschedule($jobId, $priority = NULL, $delay = NULL)
 {
     /** @var Job $job */
     $job = $this->pheanstalk->peek($jobId);
     $jobStats = $this->pheanstalk->statsJob($job);
     $this->pheanstalk->useTube($this->tube);
     $priority = NULL === $priority ? $jobStats['pri'] : $priority;
     $delay = NULL === $delay ? $jobStats['delay'] : $delay;
     $newJobId = $this->pheanstalk->put($job->getData(), $priority, $delay, $jobStats['ttr']);
     $this->pheanstalk->delete($job);
     $context = ['job_id' => $newJobId, 'old_job_id' => $jobId, 'text' => $job->getData(), 'priority' => $priority, 'delay' => $delay];
     $this->logger->info(sprintf('Reschedule job (%d => %d): %s', $jobId, $newJobId, $job->getData()), $context);
 }
 /**
  * @param Job $job        The job to process
  * @param int $maxRetries The number of retries for this job
  *
  * @throws AbortException
  *
  * @return bool|mixed The executor result if successful, false otherwise
  */
 public function executeJob(Job $job, $maxRetries = 1)
 {
     $this->dispatcher->dispatch(WorkerEvents::EXECUTE_JOB, new JobEvent($job));
     $stats = $this->pheanstalk->statsJob($job);
     $payload = (array) json_decode($job->getData(), true);
     $releases = intval($stats['releases']);
     $priority = intval($stats['pri']);
     // context for logging
     $context = ['tube' => $stats['tube'], 'payload' => $payload, 'attempt' => $releases + 1];
     try {
         // execute command
         $result = $this->execute($stats['tube'], $payload);
         // delete job if it completed without exceptions
         $this->delete($job);
         return $result;
     } catch (RescheduleException $re) {
         // reschedule the job
         $this->reschedule($job, $re->getRescheduleDate(), $priority);
     } catch (AbortException $e) {
         // abort thrown from executor, rethrow it and let the caller handle it
         throw $e;
     } catch (\Exception $e) {
         // some other exception occured
         $message = sprintf('Exception occurred: %s in %s on line %d', $e->getMessage(), $e->getFile(), $e->getLine());
         $this->logJob($job->getId(), $message, LogLevel::ERROR, $context);
         $this->logJob($job->getId(), $e->getTraceAsString(), LogLevel::DEBUG, $context);
         // see if we have any retries left
         if ($releases > $maxRetries) {
             // no more retries, bury job for manual inspection
             $this->bury($job);
             $this->dispatcher->dispatch(WorkerEvents::JOB_BURIED_EVENT, new JobBuriedEvent($job, $e, $releases));
         } else {
             // try again, regardless of the error
             $this->reschedule($job, new \DateTime('+10 minutes'), $priority);
         }
     }
     return false;
 }