/**
  * 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();
 }
 private function closeJobInternal(Job $job, $finalState, array &$visited = array())
 {
     if (in_array($job, $visited, true)) {
         return;
     }
     $visited[] = $job;
     if ($job->isInFinalState()) {
         return;
     }
     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());
                 $retryJob->setExecuteAfter(new \DateTime('+' . pow(5, count($job->getRetryJobs())) . ' seconds'));
                 $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 is a safe-guard to avoid blowing up if there is a database inconsistency.
                 if (!$dep->isPending() && !$dep->isNew()) {
                     continue;
                 }
                 $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));
     }
 }