diff --git a/src/Attribute/AssignWorker.php b/src/Attribute/AssignWorker.php index 545a921..b7f8028 100644 --- a/src/Attribute/AssignWorker.php +++ b/src/Attribute/AssignWorker.php @@ -13,7 +13,7 @@ final class AssignWorker { public function __construct( - public readonly string $name + public readonly string $name, ) { } } diff --git a/src/Dispatcher.php b/src/Dispatcher.php index cf6c532..b6db7fa 100644 --- a/src/Dispatcher.php +++ b/src/Dispatcher.php @@ -21,7 +21,7 @@ public function __construct( private readonly RoadRunnerMode $mode, private readonly ReaderInterface $reader, private readonly TemporalConfig $config, - private readonly Container $container + private readonly Container $container, ) { } @@ -45,7 +45,9 @@ public function serve(): void $hasDeclarations = false; foreach ($declarations as $type => $declaration) { // Worker that listens on a task queue and hosts both workflow and activity implementations. - $worker = $registry->get($this->resolveQueueName($declaration)); + $queueName = $this->resolveQueueName($declaration) ?? $this->config->getDefaultWorker(); + + $worker = $registry->get($queueName); if ($type === WorkflowInterface::class) { // Workflows are stateful. So you need a type to create instances. @@ -56,7 +58,7 @@ public function serve(): void // Workflows are stateful. So you need a type to create instances. $worker->registerActivity( $declaration->getName(), - fn(ReflectionClass $class): object => $this->container->make($class->getName()) + fn(ReflectionClass $class): object => $this->container->make($class->getName()), ); } $hasDeclarations = true; @@ -70,14 +72,22 @@ public function serve(): void $factory->run(); } - private function resolveQueueName(\ReflectionClass $declaration): string + private function resolveQueueName(\ReflectionClass $declaration): ?string { $assignWorker = $this->reader->firstClassMetadata($declaration, AssignWorker::class); - if ($assignWorker === null) { - return $this->config->getDefaultWorker(); + if ($assignWorker !== null) { + return $assignWorker->name; + } + + $parents = $declaration->getInterfaceNames(); + foreach ($parents as $parent) { + $queueName = $this->resolveQueueName(new \ReflectionClass($parent)); + if ($queueName !== null) { + return $queueName; + } } - return $assignWorker->name; + return null; } } diff --git a/tests/src/DispatcherTest.php b/tests/src/DispatcherTest.php index ec7b87d..75f33b6 100644 --- a/tests/src/DispatcherTest.php +++ b/tests/src/DispatcherTest.php @@ -18,29 +18,53 @@ final class DispatcherTest extends TestCase { - public function testResolvingQueueName(): void + private \ReflectionMethod $method; + private Dispatcher $dispatcher; + + protected function setUp(): void { - $dispatcher = new Dispatcher( + parent::setUp(); + + $this->dispatcher = new Dispatcher( RoadRunnerMode::Temporal, new AttributeReader(), new TemporalConfig(['defaultWorker' => 'foo']), $this->getContainer(), ); - $ref = new \ReflectionClass($dispatcher); - $method = $ref->getMethod('resolveQueueName'); + $ref = new \ReflectionClass($this->dispatcher); + $this->method = $ref->getMethod('resolveQueueName'); + $this->method->setAccessible(true); + } + + public function testResolvingQueueNameWithAttributeOnClass(): void + { + $queue = $this->method->invoke( + $this->dispatcher, + new \ReflectionClass(ActivityInterfaceWithAttribute::class), + ); + + $this->assertSame('worker1', $queue); + } - $queue = $method->invoke( - $dispatcher, - new \ReflectionClass(ActivityInterfaceWithAttribute::class) + public function testResolvingQueueNameWithAttributeOnParentClass(): void + { + $queue = $this->method->invoke( + $this->dispatcher, + new \ReflectionClass(ActivityClass::class), ); + $this->assertSame('worker1', $queue); + } - $queue = $method->invoke( - $dispatcher, - new \ReflectionClass(ActivityInterfaceWithoutAttribute::class) + public function testResolvingQueueNameWithoutAttribute(): void + { + $queue = $this->method->invoke( + $this->dispatcher, + new \ReflectionClass(ActivityInterfaceWithoutAttribute::class), ); - $this->assertSame('foo', $queue); + + $this->assertNull($queue); } public function testServeWithoutDeclarations(): void @@ -105,3 +129,7 @@ interface ActivityInterfaceWithAttribute interface ActivityInterfaceWithoutAttribute { } + +class ActivityClass implements ActivityInterfaceWithAttribute +{ +}