summaryrefslogtreecommitdiffstats
path: root/lib/public
diff options
context:
space:
mode:
authorCôme Chilliet <91878298+come-nc@users.noreply.github.com>2023-04-25 12:10:43 +0200
committerGitHub <noreply@github.com>2023-04-25 12:10:43 +0200
commit7250f54ca32c1c353470fbc4042ee648e57b760f (patch)
tree15be4b1e070978f81ee9481238e27f5d704e6997 /lib/public
parent77bb867ad5c74216364d593c419419412d27594f (diff)
parent06d6cf4ebcc49d97f89b46e127599b97f8fa1800 (diff)
downloadnextcloud-server-7250f54ca32c1c353470fbc4042ee648e57b760f.tar.gz
nextcloud-server-7250f54ca32c1c353470fbc4042ee648e57b760f.zip
Merge pull request #37835 from nextcloud/feat/background-allow-parallel-runs
feat(BackgroundJobs): Allow preventing parallel runs for a job class
Diffstat (limited to 'lib/public')
-rw-r--r--lib/public/BackgroundJob/IJobList.php9
-rw-r--r--lib/public/BackgroundJob/IParallelAwareJob.php47
-rw-r--r--lib/public/BackgroundJob/Job.php33
3 files changed, 86 insertions, 3 deletions
diff --git a/lib/public/BackgroundJob/IJobList.php b/lib/public/BackgroundJob/IJobList.php
index e8d0380e604..71faefb8825 100644
--- a/lib/public/BackgroundJob/IJobList.php
+++ b/lib/public/BackgroundJob/IJobList.php
@@ -145,4 +145,13 @@ interface IJobList {
* @since 23.0.0
*/
public function resetBackgroundJob(IJob $job): void;
+
+ /**
+ * Checks whether a job of the passed class is reserved to run
+ *
+ * @param string|null $className
+ * @return bool
+ * @since 27.0.0
+ */
+ public function hasReservedJob(?string $className): bool;
}
diff --git a/lib/public/BackgroundJob/IParallelAwareJob.php b/lib/public/BackgroundJob/IParallelAwareJob.php
new file mode 100644
index 00000000000..30c69e16b5f
--- /dev/null
+++ b/lib/public/BackgroundJob/IParallelAwareJob.php
@@ -0,0 +1,47 @@
+<?php
+
+declare(strict_types=1);
+
+
+/**
+ * @copyright Copyright (c) 2023, Marcel Klehr <mklehr@gmx.net>
+ *
+ * @author Marcel Klehr <mklehr@gmx.net>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+namespace OCP\BackgroundJob;
+
+/**
+ * @since 27.0.0
+ */
+interface IParallelAwareJob {
+ /**
+ * Set this to false to prevent two Jobs from the same class from running in parallel
+ *
+ * @param bool $allow
+ * @return void
+ * @since 27.0.0
+ */
+ public function setAllowParallelRuns(bool $allow): void;
+
+ /**
+ * @return bool
+ * @since 27.0.0
+ */
+ public function getAllowParallelRuns(): bool;
+}
diff --git a/lib/public/BackgroundJob/Job.php b/lib/public/BackgroundJob/Job.php
index d60fb5905c9..455fb3d42e7 100644
--- a/lib/public/BackgroundJob/Job.php
+++ b/lib/public/BackgroundJob/Job.php
@@ -38,11 +38,13 @@ use Psr\Log\LoggerInterface;
*
* @since 15.0.0
*/
-abstract class Job implements IJob {
+abstract class Job implements IJob, IParallelAwareJob {
protected int $id = 0;
protected int $lastRun = 0;
protected $argument;
protected ITimeFactory $time;
+ protected bool $allowParallelRuns = true;
+ private ?ILogger $logger = null;
/**
* @since 15.0.0
@@ -61,6 +63,7 @@ abstract class Job implements IJob {
* @since 15.0.0
*/
public function execute(IJobList $jobList, ILogger $logger = null) {
+ $this->logger = $logger;
$this->start($jobList);
}
@@ -70,7 +73,12 @@ abstract class Job implements IJob {
*/
public function start(IJobList $jobList): void {
$jobList->setLastRun($this);
- $logger = \OCP\Server::get(LoggerInterface::class);
+ $logger = $this->logger ?? \OCP\Server::get(LoggerInterface::class);
+
+ if (!$this->getAllowParallelRuns() && $jobList->hasReservedJob(get_class($this))) {
+ $logger->debug('Skipping ' . get_class($this) . ' job with ID ' . $this->getId() . ' because another job with the same class is already running', ['app' => 'cron']);
+ return;
+ }
try {
$jobStartTime = $this->time->getTime();
@@ -80,7 +88,7 @@ abstract class Job implements IJob {
$logger->debug('Finished ' . get_class($this) . ' job with ID ' . $this->getId() . ' in ' . $timeTaken . ' seconds', ['app' => 'cron']);
$jobList->setExecutionTime($this, $timeTaken);
- } catch (\Exception $e) {
+ } catch (\Throwable $e) {
if ($logger) {
$logger->error('Error while running background job (class: ' . get_class($this) . ', arguments: ' . print_r($this->argument, true) . ')', [
'app' => 'core',
@@ -133,6 +141,25 @@ abstract class Job implements IJob {
}
/**
+ * Set this to false to prevent two Jobs from this class from running in parallel
+ *
+ * @param bool $allow
+ * @return void
+ * @since 27.0.0
+ */
+ public function setAllowParallelRuns(bool $allow): void {
+ $this->allowParallelRuns = $allow;
+ }
+
+ /**
+ * @return bool
+ * @since 27.0.0
+ */
+ public function getAllowParallelRuns(): bool {
+ return $this->allowParallelRuns;
+ }
+
+ /**
* The actual function that is called to run the job
*
* @param $argument