From 9cc334312b58b1cf6f1df75d43fc1a17b0c20f3c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Mar 2026 19:32:06 +0000 Subject: [PATCH] feat(taskprocessing): Add --taskTypes whitelist option to taskprocessing:worker command Co-authored-by: marcelklehr <986878+marcelklehr@users.noreply.github.com> --- core/Command/TaskProcessing/WorkerCommand.php | 18 +++- .../TaskProcessing/WorkerCommandTest.php | 91 +++++++++++++++++++ 2 files changed, 107 insertions(+), 2 deletions(-) diff --git a/core/Command/TaskProcessing/WorkerCommand.php b/core/Command/TaskProcessing/WorkerCommand.php index 29d35be7975..569045ef3af 100644 --- a/core/Command/TaskProcessing/WorkerCommand.php +++ b/core/Command/TaskProcessing/WorkerCommand.php @@ -50,6 +50,12 @@ class WorkerCommand extends Base { null, InputOption::VALUE_NONE, 'Process at most one task then exit' + ) + ->addOption( + 'taskTypes', + null, + InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, + 'Only process tasks of the given task type IDs (can be specified multiple times)' ); parent::configure(); } @@ -59,6 +65,8 @@ class WorkerCommand extends Base { $timeout = (int)$input->getOption('timeout'); $interval = (int)$input->getOption('interval'); $once = $input->getOption('once') === true; + /** @var list $taskTypes */ + $taskTypes = $input->getOption('taskTypes'); if ($timeout > 0) { $output->writeln('Task processing worker will stop after ' . $timeout . ' seconds'); @@ -79,7 +87,7 @@ class WorkerCommand extends Base { break; } - $processedTask = $this->processNextTask($output); + $processedTask = $this->processNextTask($output, $taskTypes); if ($once) { break; @@ -97,9 +105,10 @@ class WorkerCommand extends Base { /** * Attempt to process one task across all preferred synchronous providers. * + * @param list $taskTypes When non-empty, only providers for these task type IDs are considered. * @return bool True if a task was processed, false if no task was found */ - private function processNextTask(OutputInterface $output): bool { + private function processNextTask(OutputInterface $output, array $taskTypes = []): bool { $providers = $this->taskProcessingManager->getProviders(); foreach ($providers as $provider) { @@ -109,6 +118,11 @@ class WorkerCommand extends Base { $taskTypeId = $provider->getTaskTypeId(); + // If a task type whitelist was provided, skip providers not in the list + if (!empty($taskTypes) && !in_array($taskTypeId, $taskTypes, true)) { + continue; + } + // Only use this provider if it is the preferred one for the task type try { $preferredProvider = $this->taskProcessingManager->getPreferredProvider($taskTypeId); diff --git a/tests/Core/Command/TaskProcessing/WorkerCommandTest.php b/tests/Core/Command/TaskProcessing/WorkerCommandTest.php index 71ebdee0dbc..7765a9a85f1 100644 --- a/tests/Core/Command/TaskProcessing/WorkerCommandTest.php +++ b/tests/Core/Command/TaskProcessing/WorkerCommandTest.php @@ -261,4 +261,95 @@ class WorkerCommandTest extends TestCase { $this->assertSame(0, $result); } + + public function testTaskTypesWhitelistFiltersProviders(): void { + $taskTypeId1 = 'type_a'; + $taskTypeId2 = 'type_b'; + + $provider1 = $this->createProvider('provider_a', $taskTypeId1); + $provider2 = $this->createProvider('provider_b', $taskTypeId2); + $task = $this->createTask(99); + + $this->manager->expects($this->once()) + ->method('getProviders') + ->willReturn([$provider1, $provider2]); + + // Only type_b is whitelisted, so provider_a (type_a) must be skipped entirely + $this->manager->expects($this->once()) + ->method('getPreferredProvider') + ->with($taskTypeId2) + ->willReturn($provider2); + + $this->manager->expects($this->once()) + ->method('getNextScheduledTask') + ->with([$taskTypeId2]) + ->willReturn($task); + + $this->manager->expects($this->once()) + ->method('processTask') + ->with($task, $provider2) + ->willReturn(true); + + $input = new ArrayInput(['--once' => true, '--taskTypes' => [$taskTypeId2]], $this->command->getDefinition()); + $output = new NullOutput(); + + $result = $this->command->run($input, $output); + + $this->assertSame(0, $result); + } + + public function testTaskTypesWhitelistWithNoMatchingProviders(): void { + $provider = $this->createProvider('provider_a', 'type_a'); + + $this->manager->expects($this->once()) + ->method('getProviders') + ->willReturn([$provider]); + + // Whitelist does not include type_a so nothing should be processed + $this->manager->expects($this->never()) + ->method('getPreferredProvider'); + + $this->manager->expects($this->never()) + ->method('getNextScheduledTask'); + + $input = new ArrayInput(['--once' => true, '--taskTypes' => ['type_b']], $this->command->getDefinition()); + $output = new NullOutput(); + + $result = $this->command->run($input, $output); + + $this->assertSame(0, $result); + } + + public function testEmptyTaskTypesAllowsAllProviders(): void { + $taskTypeId = 'type_a'; + $provider = $this->createProvider('provider_a', $taskTypeId); + $task = $this->createTask(5); + + $this->manager->expects($this->once()) + ->method('getProviders') + ->willReturn([$provider]); + + $this->manager->expects($this->once()) + ->method('getPreferredProvider') + ->with($taskTypeId) + ->willReturn($provider); + + $this->manager->expects($this->once()) + ->method('getNextScheduledTask') + ->with([$taskTypeId]) + ->willReturn($task); + + $this->manager->expects($this->once()) + ->method('processTask') + ->with($task, $provider) + ->willReturn(true); + + // No --taskTypes option provided + $input = new ArrayInput(['--once' => true], $this->command->getDefinition()); + $output = new NullOutput(); + + $result = $this->command->run($input, $output); + + $this->assertSame(0, $result); + } }