diff --git a/src/Attribute/AssignWorker.php b/src/Attribute/AssignWorker.php index 6d1e765..bb73dea 100644 --- a/src/Attribute/AssignWorker.php +++ b/src/Attribute/AssignWorker.php @@ -10,7 +10,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 208c0e3..ee2328a 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, ) { } @@ -44,7 +44,9 @@ public function serve(): void 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. @@ -55,7 +57,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()), ); } } @@ -64,14 +66,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 29ed66c..9851571 100644 --- a/tests/src/DispatcherTest.php +++ b/tests/src/DispatcherTest.php @@ -12,30 +12,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'); - $method->setAccessible(true); + $ref = new \ReflectionClass($this->dispatcher); + $this->method = $ref->getMethod('resolveQueueName'); + $this->method->setAccessible(true); + } - $queue = $method->invoke( - $dispatcher, - new \ReflectionClass(ActivityInterfaceWithAttribute::class) + public function testResolvingQueueNameWithAttributeOnClass(): void + { + $queue = $this->method->invoke( + $this->dispatcher, + new \ReflectionClass(ActivityInterfaceWithAttribute::class), ); + $this->assertSame('worker1', $queue); + } - $queue = $method->invoke( - $dispatcher, - new \ReflectionClass(ActivityInterfaceWithoutAttribute::class) + public function testResolvingQueueNameWithAttributeOnParentClass(): void + { + $queue = $this->method->invoke( + $this->dispatcher, + new \ReflectionClass(ActivityClass::class), ); - $this->assertSame('foo', $queue); + + $this->assertSame('worker1', $queue); + } + + public function testResolvingQueueNameWithoutAttribute(): void + { + $queue = $this->method->invoke( + $this->dispatcher, + new \ReflectionClass(ActivityInterfaceWithoutAttribute::class), + ); + + $this->assertNull($queue); } } @@ -48,3 +71,7 @@ interface ActivityInterfaceWithAttribute interface ActivityInterfaceWithoutAttribute { } + +class ActivityClass implements ActivityInterfaceWithAttribute +{ +}