params = $params; $this->queueUtil = $queueUtil; $this->jobRunner = $jobRunner; $this->asyncPoolFactory = $asyncPoolFactory; $this->entityManager = $entityManager; } public function process(): void { $pool = null; if ($this->params->useProcessPool()) { $pool = $this->asyncPoolFactory->create(); } $pendingJobList = $this->queueUtil->getPendingJobList( $this->params->getQueue(), $this->params->getLimit() ); foreach ($pendingJobList as $job) { $this->processJob($job, $pool); } if ($pool) { $pool->wait(); } } protected function processJob(JobEntity $job, ?AsyncPool $pool = null): void { $useProcessPool = $this->params->useProcessPool(); $noLock = $this->params->noLock(); $lockTable = (bool) $job->getScheduledJobId() && !$noLock; $skip = false; if (!$noLock) { if ($lockTable) { // MySQL doesn't allow to lock non-existent rows. We resort to locking an entire table. $this->entityManager->getLocker()->lockExclusive('Job'); } else { $this->entityManager->getTransactionManager()->start(); } } if ($noLock || $this->queueUtil->isJobPending($job->id)) { if ( $job->getScheduledJobId() && $this->queueUtil->isScheduledJobRunning( $job->getScheduledJobId(), $job->getTargetId(), $job->getTargetType() ) ) { $skip = true; } } else { $skip = true; } if ($skip && !$noLock) { if ($lockTable) { $this->entityManager->getLocker()->rollback(); } else { $this->entityManager->getTransactionManager()->rollback(); } } if ($skip) { return; } $job->set('startedAt', date('Y-m-d H:i:s')); if ($useProcessPool) { $job->set('status', JobManager::READY); } else { $job->set('status', JobManager::RUNNING); $job->set('pid', System::getPid()); } $this->entityManager->saveEntity($job); if (!$noLock) { if ($lockTable) { $this->entityManager->getLocker()->commit(); } else { $this->entityManager->getTransactionManager()->commit(); } } if ($useProcessPool) { $task = new JobTask($job->id); $pool->add($task); return; } $this->jobRunner->run($job); } }