feat(bg-jobs): allow setting a job class list instead of a single class in cron.php and the job worker occ command

Signed-off-by: Julien Veyssier <julien-nc@posteo.net>
pull/30359/head
Julien Veyssier 1 month ago
parent a5f244a58b
commit 1acc57b5c0
No known key found for this signature in database
GPG Key ID: 4141FEE162030638

@ -35,8 +35,10 @@ abstract class JobBase extends \OC\Core\Command\Base {
protected IJobList $jobList;
protected LoggerInterface $logger;
public function __construct(IJobList $jobList,
LoggerInterface $logger) {
public function __construct(
IJobList $jobList,
LoggerInterface $logger
) {
parent::__construct();
$this->jobList = $jobList;
$this->logger = $logger;

@ -40,9 +40,9 @@ class JobWorker extends JobBase {
->setName('background-job:worker')
->setDescription('Run a background job worker')
->addArgument(
'job-class',
'job-classes',
InputArgument::OPTIONAL,
'The class of the job in the database'
'The classes of the jobs to look for in the database, comma-separated'
)
->addOption(
'once',
@ -61,11 +61,31 @@ class JobWorker extends JobBase {
}
protected function execute(InputInterface $input, OutputInterface $output): int {
$jobClass = $input->getArgument('job-class');
$jobClassesString = $input->getArgument('job-classes');
// only keep non-empty strings
$jobClasses = $jobClassesString === null
? null
: array_filter(
explode(',', $jobClassesString),
static function (string $jobClass) {
return strlen($jobClass) > 0;
}
);
if ($jobClasses !== null) {
// no class
if (count($jobClasses) === 0) {
$output->writeln('<error>Invalid job class list supplied</error>');
return 1;
}
if ($jobClass && !class_exists($jobClass)) {
$output->writeln('<error>Invalid job class</error>');
return 1;
// at least one invalid class
foreach ($jobClasses as $jobClass) {
if (!class_exists($jobClass)) {
$output->writeln('<error>Invalid job class: ' . $jobClass . '</error>');
return 1;
}
}
}
while (true) {
@ -80,10 +100,10 @@ class JobWorker extends JobBase {
$this->printSummary($input, $output);
usleep(50000);
$job = $this->jobList->getNext(false, $jobClass);
$job = $this->jobList->getNext(false, $jobClasses);
if (!$job) {
if ($input->getOption('once') === true) {
$output->writeln('No job of class ' . $jobClass . ' is currently queued', OutputInterface::VERBOSITY_VERBOSE);
$output->writeln('No job of classes ' . $jobClassesString . ' is currently queued', OutputInterface::VERBOSITY_VERBOSE);
$output->writeln('Exiting...', OutputInterface::VERBOSITY_VERBOSE);
break;
}

@ -62,10 +62,10 @@ try {
Run the background job routine
Usage:
php -f cron.php -- [-h] [<job-class>]
php -f cron.php -- [-h] [<job-classes>]
Arguments:
job-class Optional job class to only run those jobs
job-classes Optional job class comma-separated list to only run those jobs
Options:
-h, --help Display this help message' . PHP_EOL;
@ -175,9 +175,17 @@ Options:
$endTime = time() + 14 * 60;
$executedJobs = [];
// a specific job class can optionally be given as first argument
$jobClass = isset($argv[1]) ? $argv[1] : null;
while ($job = $jobList->getNext($onlyTimeSensitive, $jobClass)) {
// a specific job class list can optionally be given as first argument
// only keep non-empty strings
$jobClasses = isset($argv[1])
? array_filter(
explode(',', $argv[1]),
static function (string $jobClass) {
return strlen($jobClass) > 0;
}
)
: null;
while ($job = $jobList->getNext($onlyTimeSensitive, $jobClasses)) {
if (isset($executedJobs[$job->getId()])) {
$jobList->unlockJob($job);
break;

@ -1056,6 +1056,8 @@ return array(
'OC\\Core\\Command\\Background\\Cron' => $baseDir . '/core/Command/Background/Cron.php',
'OC\\Core\\Command\\Background\\Delete' => $baseDir . '/core/Command/Background/Delete.php',
'OC\\Core\\Command\\Background\\Job' => $baseDir . '/core/Command/Background/Job.php',
'OC\\Core\\Command\\Background\\JobBase' => $baseDir . '/core/Command/Background/JobBase.php',
'OC\\Core\\Command\\Background\\JobWorker' => $baseDir . '/core/Command/Background/JobWorker.php',
'OC\\Core\\Command\\Background\\ListCommand' => $baseDir . '/core/Command/Background/ListCommand.php',
'OC\\Core\\Command\\Background\\WebCron' => $baseDir . '/core/Command/Background/WebCron.php',
'OC\\Core\\Command\\Base' => $baseDir . '/core/Command/Base.php',

@ -1089,6 +1089,8 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OC\\Core\\Command\\Background\\Cron' => __DIR__ . '/../../..' . '/core/Command/Background/Cron.php',
'OC\\Core\\Command\\Background\\Delete' => __DIR__ . '/../../..' . '/core/Command/Background/Delete.php',
'OC\\Core\\Command\\Background\\Job' => __DIR__ . '/../../..' . '/core/Command/Background/Job.php',
'OC\\Core\\Command\\Background\\JobBase' => __DIR__ . '/../../..' . '/core/Command/Background/JobBase.php',
'OC\\Core\\Command\\Background\\JobWorker' => __DIR__ . '/../../..' . '/core/Command/Background/JobWorker.php',
'OC\\Core\\Command\\Background\\ListCommand' => __DIR__ . '/../../..' . '/core/Command/Background/ListCommand.php',
'OC\\Core\\Command\\Background\\WebCron' => __DIR__ . '/../../..' . '/core/Command/Background/WebCron.php',
'OC\\Core\\Command\\Base' => __DIR__ . '/../../..' . '/core/Command/Base.php',

@ -214,7 +214,7 @@ class JobList implements IJobList {
* Get the next job in the list
* @return ?IJob the next job to run. Beware that this object may be a singleton and may be modified by the next call to buildJob.
*/
public function getNext(bool $onlyTimeSensitive = false, string $jobClass = null): ?IJob {
public function getNext(bool $onlyTimeSensitive = false, ?array $jobClasses = null): ?IJob {
$query = $this->connection->getQueryBuilder();
$query->select('*')
->from('jobs')
@ -227,8 +227,12 @@ class JobList implements IJobList {
$query->andWhere($query->expr()->eq('time_sensitive', $query->createNamedParameter(IJob::TIME_SENSITIVE, IQueryBuilder::PARAM_INT)));
}
if ($jobClass) {
$query->andWhere($query->expr()->eq('class', $query->createNamedParameter($jobClass)));
if ($jobClasses !== null && count($jobClasses) > 0) {
$orClasses = $query->expr()->orx();
foreach ($jobClasses as $jobClass) {
$orClasses->add($query->expr()->eq('class', $query->createNamedParameter($jobClass, IQueryBuilder::PARAM_STR)));
}
$query->andWhere($orClasses);
}
$result = $query->executeQuery();
@ -265,7 +269,7 @@ class JobList implements IJobList {
if ($count === 0) {
// Background job already executed elsewhere, try again.
return $this->getNext($onlyTimeSensitive, $jobClass);
return $this->getNext($onlyTimeSensitive, $jobClasses);
}
if ($job === null) {
@ -278,7 +282,7 @@ class JobList implements IJobList {
$reset->executeStatement();
// Background job from disabled app, try again.
return $this->getNext($onlyTimeSensitive, $jobClass);
return $this->getNext($onlyTimeSensitive, $jobClasses);
}
return $job;

@ -110,9 +110,12 @@ interface IJobList {
/**
* get the next job in the list
*
* @since 7.0.0 - In 24.0.0 parameter $onlyTimeSensitive got added; In 29.0.0 parameter $jobClass got added
* @param bool $onlyTimeSensitive Whether we get only time sensitive jobs or not
* @param array|null $jobClasses List of job classes to restrict which next job we get
* @return IJob|null
* @since 7.0.0 - In 24.0.0 parameter $onlyTimeSensitive got added; In 30.0.0 parameter $jobClasses got added
*/
public function getNext(bool $onlyTimeSensitive = false, string $jobClass = null): ?IJob;
public function getNext(bool $onlyTimeSensitive = false, ?array $jobClasses = null): ?IJob;
/**
* @since 7.0.0

@ -100,7 +100,7 @@ class DummyJobList extends \OC\BackgroundJob\JobList {
/**
* get the next job in the list
*/
public function getNext(bool $onlyTimeSensitive = false, string $jobClass = null): ?IJob {
public function getNext(bool $onlyTimeSensitive = false, ?array $jobClasses = null): ?IJob {
if (count($this->jobs) > 0) {
if ($this->last < (count($this->jobs) - 1)) {
$i = $this->last + 1;

Loading…
Cancel
Save