/** * 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)); } }