diff options
author | Joas Schilling <coding@schilljs.com> | 2025-07-24 00:47:37 +0200 |
---|---|---|
committer | backportbot[bot] <backportbot[bot]@users.noreply.github.com> | 2025-07-28 06:23:11 +0000 |
commit | 9b92839e009454e8a0e902172d4a2b417549e706 (patch) | |
tree | 4b477cbd6851c78e447df8b2b13e16c8c13a1dc5 | |
parent | d6468653e4e7241f5e9e6e38b35869a716b31d4f (diff) | |
download | nextcloud-server-backport/54068/stable31.tar.gz nextcloud-server-backport/54068/stable31.zip |
fix(cron): Fix infinite loop on ParallelAware blocked jobsbackport/54068/stable31
Signed-off-by: Joas Schilling <coding@schilljs.com>
-rw-r--r-- | lib/private/BackgroundJob/JobList.php | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/lib/private/BackgroundJob/JobList.php b/lib/private/BackgroundJob/JobList.php index 0d88200cff7..c00a51e3851 100644 --- a/lib/private/BackgroundJob/JobList.php +++ b/lib/private/BackgroundJob/JobList.php @@ -24,6 +24,9 @@ use function min; use function strlen; class JobList implements IJobList { + /** @var array<string, int> */ + protected array $alreadyVisitedParallelBlocked = []; + public function __construct( protected IDBConnection $connection, protected IConfig $config, @@ -198,6 +201,12 @@ class JobList implements IJobList { $job = $this->buildJob($row); if ($job instanceof IParallelAwareJob && !$job->getAllowParallelRuns() && $this->hasReservedJob(get_class($job))) { + if (!isset($this->alreadyVisitedParallelBlocked[get_class($job)])) { + $this->alreadyVisitedParallelBlocked[get_class($job)] = $job->getId(); + } elseif ($this->alreadyVisitedParallelBlocked[get_class($job)] === $job->getId()) { + $this->logger->info('Skipped through all jobs and revisited a IParallelAwareJob blocked job again, giving up.', ['app' => 'cron']); + return null; + } $this->logger->info('Skipping ' . get_class($job) . ' job with ID ' . $job->getId() . ' because another job with the same class is already running', ['app' => 'cron']); $update = $this->connection->getQueryBuilder(); @@ -210,6 +219,10 @@ class JobList implements IJobList { return $this->getNext($onlyTimeSensitive, $jobClasses); } + if ($job !== null && isset($this->alreadyVisitedParallelBlocked[get_class($job)])) { + unset($this->alreadyVisitedParallelBlocked[get_class($job)]); + } + if ($job instanceof \OCP\BackgroundJob\TimedJob) { $now = $this->timeFactory->getTime(); $nextPossibleRun = $job->getLastRun() + $job->getInterval(); |