Skip to content

Commit

Permalink
Adds the ability to set the AssignWorker attribute not only directly …
Browse files Browse the repository at this point in the history
…on Workflow or Activity classes, but also on their parent classes.
  • Loading branch information
butschster committed Dec 14, 2023
1 parent abcdebc commit 88b0495
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 20 deletions.
2 changes: 1 addition & 1 deletion src/Attribute/AssignWorker.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
final class AssignWorker
{
public function __construct(
public readonly string $name
public readonly string $name,
) {
}
}
24 changes: 17 additions & 7 deletions src/Dispatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -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,
) {
}

Expand All @@ -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.
Expand All @@ -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()),
);
}
}
Expand All @@ -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;
}
}
51 changes: 39 additions & 12 deletions tests/src/DispatcherTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand All @@ -48,3 +71,7 @@ interface ActivityInterfaceWithAttribute
interface ActivityInterfaceWithoutAttribute
{
}

class ActivityClass implements ActivityInterfaceWithAttribute
{
}

0 comments on commit 88b0495

Please sign in to comment.