diff --git a/src/Bootloader/TemporalBridgeBootloader.php b/src/Bootloader/TemporalBridgeBootloader.php index fc798ff..7741bf8 100644 --- a/src/Bootloader/TemporalBridgeBootloader.php +++ b/src/Bootloader/TemporalBridgeBootloader.php @@ -117,7 +117,7 @@ public function init( $this->initConfig($env); $tokenizer->addListener($locator); $console->addCommand(Commands\InfoCommand::class); - $kernel->addDispatcher($this->factory->make(Dispatcher::class)); + $kernel->addDispatcher(Dispatcher::class); } public function addWorkerOptions(string $worker, WorkerOptions $options): void diff --git a/src/Dispatcher.php b/src/Dispatcher.php index dca0012..288fbd8 100644 --- a/src/Dispatcher.php +++ b/src/Dispatcher.php @@ -4,26 +4,31 @@ namespace Spiral\TemporalBridge; +use Psr\Container\ContainerInterface; use ReflectionClass; +use Spiral\Attribute\DispatcherScope; use Spiral\Boot\DispatcherInterface; -use Spiral\Core\Container; +use Spiral\Core\FactoryInterface; +use Spiral\Core\Scope; +use Spiral\Core\ScopeInterface; use Spiral\RoadRunnerBridge\RoadRunnerMode; use Spiral\TemporalBridge\Declaration\DeclarationDto; use Spiral\TemporalBridge\Declaration\DeclarationType; use Temporal\Worker\WorkerFactoryInterface; +#[DispatcherScope('temporal')] final class Dispatcher implements DispatcherInterface { public function __construct( - private readonly RoadRunnerMode $mode, - private readonly Container $container, + private readonly ContainerInterface $container, private readonly DeclarationWorkerResolver $workerResolver, + private readonly ScopeInterface $scope, ) { } - public function canServe(): bool + public static function canServe(RoadRunnerMode $mode): bool { - return \PHP_SAPI === 'cli' && $this->mode === RoadRunnerMode::Temporal; + return \PHP_SAPI === 'cli' && $mode === RoadRunnerMode::Temporal; } public function serve(): void @@ -55,10 +60,7 @@ public function serve(): void if ($declaration->type === DeclarationType::Activity) { // Workflows are stateful. So you need a type to create instances. - $worker->registerActivity( - $declaration->class->getName(), - fn(ReflectionClass $class): object => $this->container->make($class->getName()), - ); + $worker->registerActivity($declaration->class->getName(), $this->makeActivity(...)); } $hasDeclarations = true; @@ -72,4 +74,13 @@ public function serve(): void // start primary loop $factory->run(); } + + private function makeActivity(ReflectionClass $class): object + { + /** @psalm-suppress InvalidArgument */ + return $this->scope->runScope( + new Scope('temporal-activity'), + static fn (FactoryInterface $factory): object => $factory->make($class->getName()), + ); + } } diff --git a/tests/app/src/SomeActivityWithScope.php b/tests/app/src/SomeActivityWithScope.php new file mode 100644 index 0000000..2303b90 --- /dev/null +++ b/tests/app/src/SomeActivityWithScope.php @@ -0,0 +1,19 @@ +dispatcher = new Dispatcher( - RoadRunnerMode::Temporal, $this->getContainer(), new DeclarationWorkerResolver( new AttributeReader(), new TemporalConfig(['defaultWorker' => 'foo']), ), + $this->getContainer(), ); } + public function testCanServe(): void + { + $this->assertTrue(Dispatcher::canServe(RoadRunnerMode::Temporal)); + + $this->assertFalse(Dispatcher::canServe(RoadRunnerMode::Http)); + $this->assertFalse(Dispatcher::canServe(RoadRunnerMode::Jobs)); + $this->assertFalse(Dispatcher::canServe(RoadRunnerMode::Grpc)); + $this->assertFalse(Dispatcher::canServe(RoadRunnerMode::Tcp)); + $this->assertFalse(Dispatcher::canServe(RoadRunnerMode::Centrifuge)); + $this->assertFalse(Dispatcher::canServe(RoadRunnerMode::Unknown)); + } + public function testServeWithoutDeclarations(): void { $locator = $this->mockContainer(DeclarationRegistryInterface::class); @@ -101,4 +114,18 @@ public function testServeWithDeclarations(): void $this->dispatcher->serve(); } + + public function testScope(): void + { + $binder = $this->getContainer()->getBinder('temporal-activity'); + $binder->bind(SomeActivityWithScope::class, SomeActivityWithScope::class); + $binder->bind(\ArrayAccess::class, $this->createMock(\ArrayAccess::class)); + + $ref = new \ReflectionMethod($this->dispatcher, 'makeActivity'); + + $this->assertInstanceOf( + SomeActivityWithScope::class, + $ref->invoke($this->dispatcher, new \ReflectionClass(SomeActivityWithScope::class)) + ); + } }