protected function setUp()
 {
     $this->logger = $this->getMockBuilder(LoggerInterface::class)->setMethods(['info', 'warning'])->getMockForAbstractClass();
     $this->connection = $this->getMockBuilder(Connection::class)->disableOriginalConstructor()->setMethods(['isServiceListening'])->getMock();
     $this->pheanstalk = $this->getMockBuilder(PheanstalkInterface::class)->setMethods(['getConnection'])->getMockForAbstractClass();
     $this->pheanstalk->expects($this->any())->method('getConnection')->will($this->returnValue($this->connection));
 }
Example #2
0
 /**
  * {@inheritdoc}
  */
 public function dequeue(SerializerInterface $serializer)
 {
     $job = $this->client->reserve();
     if ($job) {
         return new BeanstalkdJob($this->client, $job, $serializer);
     }
     return null;
 }
 private function doClear($tubeName, $state)
 {
     try {
         while ($item = $this->pheanstalk->{'peek' . $state}($tubeName)) {
             $this->pheanstalk->delete($item);
         }
     } catch (ServerException $e) {
     }
 }
 public function testDone()
 {
     $jobId = 12345;
     $this->pheanstalkMock->expects($this->once())->method('delete')->with($this->callback(function (Job $job) use($jobId) {
         return $job->getId() === $jobId;
     }));
     $this->pheanstalkMock->expects($this->any())->method('peek')->with($jobId)->willReturn(new Job($jobId, 'asdf'));
     $this->loggerMock->expects($this->once())->method('info')->with('Done job (12345): asdf');
     $this->sut->done($jobId);
 }
Example #5
0
 /**
  * Initializes the queue object
  *
  * @param \Pheanstalk\PheanstalkInterface $client Client object
  * @param string $queue Message queue name
  * @throws \Aimeos\MW\MQueue\Exception
  */
 public function __construct(\Pheanstalk\PheanstalkInterface $client, $queue, $timeout = null)
 {
     try {
         $client->useTube($queue)->watch($queue);
     } catch (\Exception $e) {
         throw new \Aimeos\MW\MQueue\Exception($e->getMessage());
     }
     $this->client = $client;
     $this->queue = $queue;
     $this->timeout = $timeout;
 }
 private function writeTubeStats(PheanstalkInterface $conn, $tube, OutputInterface $out)
 {
     try {
         $stats = $conn->statsTube($tube);
         $out->writeln("<info>{$tube} Stats</info>");
         $this->writeStats($stats, $out);
     } catch (ServerException $e) {
         if (false !== stripos($e->getMessage(), 'NOT_FOUND')) {
             return $out->writeln(sprintf('<error>Tube "%s" not found</error>', $tube));
         }
         throw $e;
     }
 }
Example #7
0
 /**
  * {@inheritdoc}
  */
 public function fail($queueName, Envelope $env)
 {
     try {
         $this->conn->bury($this->assurePheanstalkEnvelope($env)->getJob(), $this->options['fail-priority']);
     } catch (\Pheanstalk\Exception $e) {
         throw PheanstalkError::fromException($e);
     }
 }
 /**
  * {@inheritDoc}
  */
 public function watchOnly($tube)
 {
     if ($this->dispatcher) {
         $this->dispatcher->dispatch(CommandEvent::WATCH_ONLY, new CommandEvent($this, ['tube' => $tube]));
     }
     $this->pheanstalk->watchOnly($tube);
     return $this;
 }
 /**
  * Watch for jobs on the given tube
  *
  * @return void
  */
 public function watchForJobs()
 {
     // Time the worker will retire
     $retireTime = time() + $this->ttl;
     if (null !== $this->tube) {
         $this->pheanstalk->watchOnly($this->tube);
     }
     // Watch the Queue
     while (!$this->isTerminated()) {
         $job = $this->pheanstalk->reserve(5);
         if ($job) {
             // Let everyone know we just grabbed a job off the queue
             $this->output->writeln('<comment>Found Job ID: ' . $job->getId() . '</comment>');
             // Check the data is valid for us to process a job
             if (!$this->isValid($job)) {
                 $this->output->writeln('<comment>Invalid Job, skipping.</comment>');
                 $outcome = self::ACTION_BURY;
             } else {
                 // Output to let anyone watching know that we're starting a worker
                 $this->output->writeln('<comment>' . $this->getStartMessage($job) . '</comment>');
                 try {
                     // Process the job
                     $outcome = $this->processJob($job);
                 } catch (\Exception $e) {
                     // Output error
                     $this->output->writeln('<error>Fatal Error: ' . $e->getMessage() . '</error>');
                     // Bury the job
                     $this->pheanstalk->bury($job);
                     // Break out of while loop
                     break;
                 }
                 // Let the folks know we've completed it
                 $this->output->writeln('<comment>Job Processed.</comment>');
             }
             switch ($outcome) {
                 case self::ACTION_DELETE:
                     // Remove the job from the queue
                     $this->pheanstalk->delete($job);
                     break;
                 case self::ACTION_BURY:
                     // Remove the job from the queue
                     $this->pheanstalk->bury($job);
                     break;
                 case self::ACTION_RELEASE:
                     // Remove the job from the queue
                     $this->pheanstalk->release($job);
                     break;
             }
             $this->output->writeln('<info>Waiting for next job...</info>');
         }
         // Check if it's time to retire the worker
         if (0 !== $this->ttl && time() > $retireTime) {
             $this->retire();
         }
     }
     $this->output->writeln('<info>Exiting.</info>');
 }
Example #10
0
 public function getTubeStats()
 {
     $result = [];
     $tubes = $this->pheanstalk->listTubes();
     foreach ($tubes as $tubeName) {
         $stats = $this->pheanstalk->statsTube($tubeName);
         $result[] = ['name' => $tubeName, 'buried' => $stats['current-jobs-buried'], 'delayed' => $stats['current-jobs-delayed'], 'ready' => $stats['current-jobs-ready'], 'reserved' => $stats['current-jobs-reserved'], 'urgent' => $stats['current-jobs-urgent'], 'waiting' => $stats['current-waiting'], 'total' => $stats['total-jobs']];
     }
     return $result;
 }
Example #11
0
 /**
  * {@inheritdoc}
  */
 public function fail($queueName, Envelope $env)
 {
     if (!$env instanceof PheanstalkEnvelope) {
         throw new InvalidEnvelope(sprintf('%s requires that envelopes be instances of "%s", got "%s"', __CLASS__, PheanstalkEnvelope::class, get_class($env)));
     }
     try {
         $this->conn->bury($env->getJob(), $this->options['fail-priority']);
     } catch (\Pheanstalk\Exception $e) {
         throw PheanstalkError::fromException($e);
     }
 }
Example #12
0
 /**
  * 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);
 }
 public function testExecuteJobAndNoMoreRetries()
 {
     $action = 'test';
     $executor = $this->getMockForAbstractClass(ExecutorInterface::class);
     $executor->expects($this->any())->method('getName')->will($this->returnValue($action));
     $this->manager->addExecutor($executor);
     $data = [];
     $job = new Job(1234, json_encode($data));
     $stats = ['tube' => $action, 'releases' => 2, 'pri' => PheanstalkInterface::DEFAULT_PRIORITY];
     $this->pheanstalk->expects($this->once())->method('statsJob')->with($job)->will($this->returnValue($stats));
     $this->pheanstalk->expects($this->once())->method('bury')->with($job);
     $executor->expects($this->once())->method('execute')->will($this->throwException(new \Exception('oh noes!')));
     $this->manager->executeJob($job);
 }
 /**
  * @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;
 }
Example #15
0
 /**
  * {@inheritdoc}
  */
 public function delete()
 {
     return $this->client->delete($this->job);
 }
 /**
  * Get the next job ready and buried in the specified tube and connection.
  *
  * @param PheanstalkInterface $pheanstalk
  * @param string              $tubeName
  */
 private function fetchJobs(PheanstalkInterface $pheanstalk, $tubeName)
 {
     try {
         $nextJobReady = $pheanstalk->peekReady($tubeName);
         $this->data['jobs'][$tubeName]['ready'] = ['id' => $nextJobReady->getId(), 'data' => $nextJobReady->getData()];
     } catch (ServerException $e) {
     }
     try {
         $nextJobBuried = $pheanstalk->peekBuried($tubeName);
         $this->data['jobs'][$tubeName]['buried'] = ['id' => $nextJobBuried->getId(), 'data' => $nextJobBuried->getData()];
     } catch (ServerException $e) {
     }
 }
Example #17
0
 public function buryJob($queueName, JobInterface $job)
 {
     $this->pheanstalk->bury(new Job($job->getData()['_beanstalk_id'], []));
 }
 public function put(CommandInterface $command)
 {
     $this->pheanstalk->put(serialize($command));
 }
Example #19
0
 /**
  * {@inheritdoc}
  *
  * @param integer|null $priority
  */
 public function release(ManagerInterface $manager, $delay = 0, $priority = PheanstalkInterface::DEFAULT_PRIORITY)
 {
     $this->pheanstalk->release($manager->getPheanstalkJob(), $priority, $delay);
     return true;
 }
 /**
  * Mark a job as failed
  *
  * @access public
  * @param  Job $job
  * @return $this
  */
 public function failed(Job $job)
 {
     $beanstalkJob = new BeanstalkJob($job->getId(), $job->serialize());
     $this->beanstalk->bury($beanstalkJob);
     return $this;
 }