setInterval(60 * 60); $this->setTimeSensitivity(IJob::TIME_SENSITIVE); } #[Override] protected function run($argument): void { $this->reapCrashedJobs(); // TODO Clean oldest jobs } private function reapCrashedJobs(): void { $currentServerId = $this->serverInfo->getServerId(); foreach ($this->jobRuns->runningJobs(1000) as $job) { if ($job->serverId !== $currentServerId) { continue; } $output = []; $result = 0; exec('ps -p ' . escapeshellarg((string)$job->pid) . ' -o cmd', $output, $result); if (count($output) === 1 && current($output) === 'CMD' && $result === 1) { // Process doesn't exists anymore $maxDuration = (new DateTimeImmutable())->diff($job->startedAt); $maxDuration = ($maxDuration->days * 24 * 60 * 60 * 1000) + ($maxDuration->h * 60 * 60 * 1000) + ($maxDuration->i * 60 * 1000) + ($maxDuration->s * 1000) + (int)($maxDuration->f * 1000); $this->jobRuns->finished($job->runId, $maxDuration, 0, JobStatus::CRASHED); $this->logger->warning('No process matching PID {pid} found on server {serverId}. Job {runId} was marked as crashed', [ 'pid' => $job->pid, 'serverId' => $job->serverId, 'runId' => $job->runId, ]); } } } }