public function scheduleNextRetry(Job $originalJob)
 {
     return new \DateTime('+' . pow($this->base, count($originalJob->getRetryJobs())) . ' seconds');
 }
예제 #2
0
 public function getJobStatistics(Job $job)
 {
     $statisticData = array();
     $dataPerCharacteristic = array();
     $statistics = $this->em->getConnection()->query("SELECT * FROM jms_job_statistics WHERE job_id = " . $job->getId());
     foreach ($statistics as $row) {
         $dataPerCharacteristic[$row['characteristic']][] = array($row['createdAt'], $row['charValue']);
     }
     if ($dataPerCharacteristic) {
         $statisticData = array(array_merge(array('Time'), $chars = array_keys($dataPerCharacteristic)));
         $startTime = strtotime($dataPerCharacteristic[$chars[0]][0][0]);
         $endTime = strtotime($dataPerCharacteristic[$chars[0]][count($dataPerCharacteristic[$chars[0]]) - 1][0]);
         $scaleFactor = $endTime - $startTime > 300 ? 1 / 60 : 1;
         // This assumes that we have the same number of rows for each characteristic.
         for ($i = 0, $c = count(reset($dataPerCharacteristic)); $i < $c; $i++) {
             $row = array((strtotime($dataPerCharacteristic[$chars[0]][$i][0]) - $startTime) * $scaleFactor);
             foreach ($chars as $name) {
                 $value = (double) $dataPerCharacteristic[$name][$i][1];
                 switch ($name) {
                     case 'memory':
                         $value /= 1024 * 1024;
                         break;
                 }
                 $row[] = $value;
             }
             $statisticData[] = $row;
         }
     }
     return $statisticData;
 }
예제 #3
0
 public function getJobStatistics(Job $job)
 {
     $statisticData = array();
     $dataPerCharacteristic = array();
     $stmt = $this->em->getConnection()->prepare('SELECT * FROM jms_job_statistics WHERE job_id = :jobId');
     $stmt->execute(array('jobId' => $job->getId()));
     $statistics = $stmt->fetchAll();
     $propertyAccess = PropertyAccess::createPropertyAccessor();
     foreach ($statistics as $row) {
         $dataPerCharacteristic[$propertyAccess->getValue($row, '[characteristic]')][] = array($propertyAccess->getValue($row, '[createdAt]'), $propertyAccess->getValue($row, '[charValue]'));
     }
     if ($dataPerCharacteristic) {
         $statisticData = array(array_merge(array('Time'), $chars = array_keys($dataPerCharacteristic)));
         $startTime = strtotime($dataPerCharacteristic[$chars[0]][0][0]);
         $endTime = strtotime($dataPerCharacteristic[$chars[0]][count($dataPerCharacteristic[$chars[0]]) - 1][0]);
         $scaleFactor = $endTime - $startTime > 300 ? 1 / 60 : 1;
         // This assumes that we have the same number of rows for each characteristic.
         for ($i = 0, $c = count(reset($dataPerCharacteristic)); $i < $c; $i++) {
             $row = array((strtotime($dataPerCharacteristic[$chars[0]][$i][0]) - $startTime) * $scaleFactor);
             foreach ($chars as $name) {
                 $value = (double) $dataPerCharacteristic[$name][$i][1];
                 switch ($name) {
                     case 'memory':
                         $value /= 1024 * 1024;
                         break;
                 }
                 $row[] = $value;
             }
             $statisticData[] = $row;
         }
     }
     return $statisticData;
 }
예제 #4
0
 public function testGetRelatedEntities()
 {
     $relEntity = new Schedule();
     $this->assertInternalType('array', $this->object->getRelatedEntities($this->job));
     $this->assertEmpty($this->object->getRelatedEntities($this->job));
     $this->job->addRelatedEntity($relEntity);
     $this->assertNotEmpty($this->object->getRelatedEntities($this->job));
 }
 public function __construct(Job $job, $newState, array $allowedStates = array())
 {
     $msg = sprintf('The Job(id = %d) cannot change from "%s" to "%s". Allowed transitions: ', $job->getId(), $job->getState(), $newState);
     $msg .= count($allowedStates) > 0 ? '"' . implode('", "', $allowedStates) . '"' : '#none#';
     parent::__construct($msg);
     $this->job = $job;
     $this->newState = $newState;
     $this->allowedStates = $allowedStates;
 }
 public function createCronJob(\DateTime $_)
 {
     if (!$this instanceof Command) {
         throw new \LogicException('This trait must be used in Symfony console commands only.');
     }
     $job = new Job($this->getName());
     $job->setMaxRuntime((int) min(300, $this->getScheduleInterval()));
     return $job;
 }
 public function testJobIsTerminatedIfMaxRuntimeIsExceeded()
 {
     $this->markTestSkipped('Requires a patched Process class (see symfony/symfony#5030).');
     $job = new Job('jms-job-queue:never-ending');
     $job->setMaxRuntime(1);
     $this->em->persist($job);
     $this->em->flush($job);
     $this->doRun(array('--max-runtime' => 1));
     $this->assertEquals('terminated', $job->getState());
 }
예제 #8
0
 /**
  * @param Job $job
  * @return \Symfony\Component\Process\Process
  */
 public function runJob(Job $job)
 {
     $pb = $this->getCommandProcessBuilder();
     $pb->add($job->getCommand())->add('--jms-job-id=' . $job->getId());
     foreach ($job->getArgs() as $arg) {
         $pb->add($arg);
     }
     $proc = $pb->getProcess();
     $proc->start();
     return $proc;
 }
예제 #9
0
 /**
  * {@inheritdoc}
  */
 public function load(ObjectManager $manager)
 {
     foreach ($this->data as $data) {
         $entity = new Job($data['command'], $data['args'], $data['confirmed']);
         foreach ($data['state'] as $state) {
             $entity->setState($state);
         }
         $this->setReference($data['reference'], $entity);
         $manager->persist($entity);
     }
     $manager->flush();
 }
예제 #10
0
 private function resolveDependencies(EntityManager $em, Job $job)
 {
     // If this job has failed, or has otherwise not succeeded, we need to set the
     // incoming dependencies to failed if that has not been done already.
     if (!$job->isFinished()) {
         /** @var JobRepository $repository */
         $repository = $em->getRepository('JMS\\JobQueueBundle\\Entity\\Job');
         foreach ($repository->findIncomingDependencies($job) as $incomingDep) {
             if ($incomingDep->isInFinalState()) {
                 continue;
             }
             $finalState = Job::STATE_CANCELED;
             if ($job->isRunning()) {
                 $finalState = Job::STATE_FAILED;
             }
             $repository->closeJob($incomingDep, $finalState);
         }
     }
     $em->getConnection()->executeUpdate("DELETE FROM jms_job_dependencies WHERE dest_job_id = :id", array('id' => $job->getId()));
 }
예제 #11
0
 public function testJobIsTerminatedIfMaxRuntimeIsExceeded()
 {
     $job = new Job('jms-job-queue:never-ending');
     $job->setMaxRuntime(1);
     $this->em->persist($job);
     $this->em->flush($job);
     $this->doRun(array('--max-runtime' => 1, '--worker-name' => 'test'));
     $this->assertEquals('terminated', $job->getState());
 }
예제 #12
0
 public function testIsRetryAllowed()
 {
     $job = new Job('a');
     $this->assertFalse($job->isRetryAllowed());
     $job->setMaxRetries(1);
     $this->assertTrue($job->isRetryAllowed());
     $job->setState('running');
     $retry = new Job('a');
     $job->addRetryJob($retry);
     $this->assertFalse($job->isRetryAllowed());
 }
예제 #13
0
 /**
  * Create JMS jobs for queued process jobs
  *
  * @param \Doctrine\ORM\EntityManager $entityManager
  */
 protected function createJobs($entityManager)
 {
     if (empty($this->queuedJobs)) {
         return;
     }
     foreach ($this->queuedJobs as $timeShift => $processJobBatch) {
         foreach ($processJobBatch as $priority => $processJobs) {
             $args = array();
             /** @var ProcessJob $processJob */
             foreach ($processJobs as $processJob) {
                 $args[] = '--id=' . $processJob->getId();
                 $this->logger->debug('Process queued', $processJob->getProcessTrigger(), $processJob->getData());
             }
             $jmsJob = new Job(ExecuteProcessJobCommand::NAME, $args, true, Job::DEFAULT_QUEUE, $priority);
             if ($timeShift) {
                 $timeShiftInterval = ProcessTrigger::convertSecondsToDateInterval($timeShift);
                 $executeAfter = new \DateTime('now', new \DateTimeZone('UTC'));
                 $executeAfter->add($timeShiftInterval);
                 $jmsJob->setExecuteAfter($executeAfter);
             }
             $entityManager->persist($jmsJob);
         }
     }
     $this->queuedJobs = array();
     $entityManager->flush();
 }
 public function testModifyingRelatedEntity()
 {
     $wagon = new Wagon();
     $train = new Train();
     $wagon->train = $train;
     $defEm = self::$kernel->getContainer()->get('doctrine')->getManager('default');
     $defEm->persist($wagon);
     $defEm->persist($train);
     $defEm->flush();
     $j = new Job('j');
     $j->addRelatedEntity($wagon);
     $this->em->persist($j);
     $this->em->flush();
     $defEm->clear();
     $this->em->clear();
     $this->assertNotSame($defEm, $this->em);
     $reloadedJ = $this->em->find('JMSJobQueueBundle:Job', $j->getId());
     $reloadedWagon = $reloadedJ->findRelatedEntity('JMS\\JobQueueBundle\\Tests\\Functional\\TestBundle\\Entity\\Wagon');
     $reloadedWagon->state = 'broken';
     $defEm->persist($reloadedWagon);
     $defEm->flush();
     $this->assertTrue($defEm->contains($reloadedWagon->train));
 }
 private function getJobIdsOfIncomingDependencies(Job $job)
 {
     $jobIds = $this->_em->getConnection()->executeQuery("SELECT source_job_id FROM jms_job_dependencies WHERE dest_job_id = :id", array('id' => $job->getId()))->fetchAll(\PDO::FETCH_COLUMN);
     return $jobIds;
 }
 /**
  * @Route("/{id}/retry", name = "jms_jobs_retry_job")
  */
 public function retryJobAction(Job $job)
 {
     $state = $job->getState();
     if (Job::STATE_FAILED !== $state && Job::STATE_TERMINATED !== $state && Job::STATE_INCOMPLETE !== $state) {
         throw new HttpException(400, 'Given job can\'t be retried');
     }
     $retryJob = clone $job;
     $this->getEm()->persist($retryJob);
     $this->getEm()->flush();
     $url = $this->router->generate('jms_jobs_details', array('id' => $retryJob->getId()), false);
     return new RedirectResponse($url, 201);
 }
 private function closeJobInternal(Job $job, $finalState, array &$visited = array())
 {
     if (in_array($job, $visited, true)) {
         return;
     }
     $visited[] = $job;
     if (null !== $this->dispatcher && ($job->isRetryJob() || 0 === count($job->getRetryJobs()))) {
         $event = new StateChangeEvent($job, $finalState);
         $this->dispatcher->dispatch('jms_job_queue.job_state_change', $event);
         $finalState = $event->getNewState();
     }
     switch ($finalState) {
         case Job::STATE_CANCELED:
             $job->setState(Job::STATE_CANCELED);
             $this->_em->persist($job);
             if ($job->isRetryJob()) {
                 $this->closeJobInternal($job->getOriginalJob(), Job::STATE_CANCELED, $visited);
                 return;
             }
             foreach ($this->findIncomingDependencies($job) as $dep) {
                 $this->closeJobInternal($dep, Job::STATE_CANCELED, $visited);
             }
             return;
         case Job::STATE_FAILED:
         case Job::STATE_TERMINATED:
         case Job::STATE_INCOMPLETE:
             if ($job->isRetryJob()) {
                 $job->setState($finalState);
                 $this->_em->persist($job);
                 $this->closeJobInternal($job->getOriginalJob(), $finalState);
                 return;
             }
             // The original job has failed, and we are allowed to retry it.
             if ($job->isRetryAllowed()) {
                 $retryJob = new Job($job->getCommand(), $job->getArgs());
                 $retryJob->setMaxRuntime($job->getMaxRuntime());
                 $job->addRetryJob($retryJob);
                 $this->_em->persist($retryJob);
                 $this->_em->persist($job);
                 return;
             }
             $job->setState($finalState);
             $this->_em->persist($job);
             // The original job has failed, and no retries are allowed.
             foreach ($this->findIncomingDependencies($job) as $dep) {
                 $this->closeJobInternal($dep, Job::STATE_CANCELED, $visited);
             }
             return;
         case Job::STATE_FINISHED:
             if ($job->isRetryJob()) {
                 $job->getOriginalJob()->setState($finalState);
                 $this->_em->persist($job->getOriginalJob());
             }
             $job->setState($finalState);
             $this->_em->persist($job);
             return;
         default:
             throw new \LogicException(sprintf('Non allowed state "%s" in closeJobInternal().', $finalState));
     }
 }
예제 #18
0
 public function addRetryJob(Job $job)
 {
     if (self::STATE_RUNNING !== $this->state) {
         throw new \LogicException('Retry jobs can only be added to running jobs.');
     }
     $job->setOriginalJob($this);
     $this->retryJobs->add($job);
 }