From 7d78c4e0e37b8196040af0ca13730f5a4867320c Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 11 Sep 2026 18:23:55 +0200 Subject: [PATCH] feat: add option to show background jobs grouped by class Signed-off-by: Robin Appelman --- core/Command/Background/ListCommand.php | 27 ++++++++++++++++++------- lib/private/BackgroundJob/JobList.php | 8 +++++++- lib/public/BackgroundJob/IJobList.php | 2 +- 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/core/Command/Background/ListCommand.php b/core/Command/Background/ListCommand.php index b60e33e780060..d56e81f53c1d5 100644 --- a/core/Command/Background/ListCommand.php +++ b/core/Command/Background/ListCommand.php @@ -29,22 +29,28 @@ protected function configure(): void { ->addOption( 'class', 'c', - InputOption::VALUE_OPTIONAL, + InputOption::VALUE_REQUIRED, 'Job class to search for', null )->addOption( 'limit', 'l', - InputOption::VALUE_OPTIONAL, + InputOption::VALUE_REQUIRED, 'Number of jobs to retrieve', '500' )->addOption( 'offset', 'o', - InputOption::VALUE_OPTIONAL, + InputOption::VALUE_REQUIRED, 'Offset for retrieving jobs', '0' ) + ->addOption( + 'group', + null, + InputOption::VALUE_NONE, + 'Group jobs by class' + ) ; parent::configure(); } @@ -52,10 +58,17 @@ protected function configure(): void { #[\Override] protected function execute(InputInterface $input, OutputInterface $output): int { $limit = (int)$input->getOption('limit'); - $jobsInfo = $this->formatJobs($this->jobList->getJobsIterator($input->getOption('class'), $limit, (int)$input->getOption('offset'))); - $this->writeTableInOutputFormat($input, $output, $jobsInfo); - if ($input->getOption('output') === self::OUTPUT_FORMAT_PLAIN && count($jobsInfo) >= $limit) { - $output->writeln("\nOutput is currently limited to " . $limit . ' jobs. Specify `-l, --limit[=LIMIT]` to override.'); + $offset = (int)$input->getOption('offset'); + $group = $input->getOption('group'); + if ($group) { + $grouped = $this->jobList->countByClass($limit, $offset); + $this->writeTableInOutputFormat($input, $output, $grouped); + } else { + $jobsInfo = $this->formatJobs($this->jobList->getJobsIterator($input->getOption('class'), $limit, $offset)); + $this->writeTableInOutputFormat($input, $output, $jobsInfo); + if ($input->getOption('output') === self::OUTPUT_FORMAT_PLAIN && count($jobsInfo) >= $limit) { + $output->writeln("\nOutput is currently limited to " . $limit . ' jobs. Specify `-l, --limit[=LIMIT]` to override.'); + } } return 0; } diff --git a/lib/private/BackgroundJob/JobList.php b/lib/private/BackgroundJob/JobList.php index 2c63ef1777164..8a286d07d21c0 100644 --- a/lib/private/BackgroundJob/JobList.php +++ b/lib/private/BackgroundJob/JobList.php @@ -422,13 +422,19 @@ public function hasReservedJob(?string $className = null): bool { } #[Override] - public function countByClass(): array { + public function countByClass(?int $limit = null, int $offset = 0): array { $query = $this->connection->getQueryBuilder(); $query->select('class') ->selectAlias($query->func()->count('id'), 'count') ->from('jobs') ->orderBy('count') ->groupBy('class'); + if ($offset > 0) { + $query = $query->setFirstResult($offset); + } + if ($limit !== null) { + $query = $query->setMaxResults($limit); + } $result = $query->executeQuery(); diff --git a/lib/public/BackgroundJob/IJobList.php b/lib/public/BackgroundJob/IJobList.php index 340f00b443546..7b268587fb1ff 100644 --- a/lib/public/BackgroundJob/IJobList.php +++ b/lib/public/BackgroundJob/IJobList.php @@ -173,5 +173,5 @@ public function hasReservedJob(?string $className): bool; * @return list, count:int}> * @since 30.0.0 */ - public function countByClass(): array; + public function countByClass(?int $limit = null, int $offset = 0): array; }