From 821e4db8e3572cef17bc7e0be4589b56fabf0260 Mon Sep 17 00:00:00 2001 From: Dmitry Derepko Date: Mon, 5 Jul 2021 23:18:37 +0300 Subject: [PATCH 01/16] Add temporal sdk to composer.json --- composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index f4ce305..be26a9d 100644 --- a/composer.json +++ b/composer.json @@ -26,7 +26,8 @@ "spiral/roadrunner-worker": ">=2.0.3", "spiral/goridge": "^3.0", "symfony/psr-http-message-bridge": "^1.1 || ^2.0", - "psr/log": "^1.1" + "psr/log": "^1.1", + "temporal/sdk": "^1.0" }, "suggest": { "nyholm/psr7": "For a super lightweight PSR-7/17 implementation", From 875b4041ff833a0134a0335490508d47c2a035c1 Mon Sep 17 00:00:00 2001 From: Dmitry Derepko Date: Mon, 5 Jul 2021 23:22:40 +0300 Subject: [PATCH 02/16] Rename Worker -> HttpWorker --- config/services.php | 4 ++-- src/Worker/{Worker.php => HttpWorker.php} | 12 ++++++------ tests/Worker/WorkerTest.php | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) rename src/Worker/{Worker.php => HttpWorker.php} (91%) diff --git a/config/services.php b/config/services.php index 7909665..eae5436 100644 --- a/config/services.php +++ b/config/services.php @@ -16,7 +16,7 @@ use Baldinof\RoadRunnerBundle\RoadRunnerBridge\HttpFoundationWorker; use Baldinof\RoadRunnerBundle\RoadRunnerBridge\HttpFoundationWorkerInterface; use Baldinof\RoadRunnerBundle\Worker\Dependencies; -use Baldinof\RoadRunnerBundle\Worker\Worker; +use Baldinof\RoadRunnerBundle\Worker\HttpWorker; use Baldinof\RoadRunnerBundle\Worker\WorkerInterface; use Psr\Log\LoggerInterface; use Spiral\Goridge\RPC\RPCInterface; @@ -66,7 +66,7 @@ function service(string $id): ReferenceConfigurator $services->set(HttpFoundationWorkerInterface::class, HttpFoundationWorker::class) ->args([service(HttpWorkerInterface::class)]); - $services->set(WorkerInterface::class, Worker::class) + $services->set(HttpWorker::class) ->public() // Manually retrieved on the DIC in the Worker if the kernel has been rebooted ->tag('monolog.logger', ['channel' => BaldinofRoadRunnerExtension::MONOLOG_CHANNEL]) ->args([ diff --git a/src/Worker/Worker.php b/src/Worker/HttpWorker.php similarity index 91% rename from src/Worker/Worker.php rename to src/Worker/HttpWorker.php index 183fb8c..854e80c 100644 --- a/src/Worker/Worker.php +++ b/src/Worker/HttpWorker.php @@ -4,7 +4,6 @@ namespace Baldinof\RoadRunnerBundle\Worker; -use function Baldinof\RoadRunnerBundle\consumes; use Baldinof\RoadRunnerBundle\Event\WorkerExceptionEvent; use Baldinof\RoadRunnerBundle\Event\WorkerKernelRebootedEvent; use Baldinof\RoadRunnerBundle\Event\WorkerStartEvent; @@ -15,11 +14,12 @@ use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\KernelInterface; use Symfony\Component\HttpKernel\RebootableInterface; +use function Baldinof\RoadRunnerBundle\consumes; /** * @internal */ -final class Worker implements WorkerInterface +final class HttpWorker implements WorkerInterface { private KernelInterface $kernel; private LoggerInterface $logger; @@ -35,7 +35,7 @@ public function __construct( $this->logger = $logger; $this->httpFoundationWorker = $httpFoundationWorker; - /** @var Dependencies */ + /** @var Dependencies $dependencies */ $dependencies = $kernel->getContainer()->get(Dependencies::class); $this->dependencies = $dependencies; } @@ -78,10 +78,10 @@ public function start(): void } finally { if ($this->kernel instanceof RebootableInterface && $this->dependencies->getKernelRebootStrategy()->shouldReboot()) { $this->kernel->reboot(null); - /** @var Dependencies */ - $deps = $this->kernel->getContainer()->get(Dependencies::class); + /** @var Dependencies $dependencies */ + $dependencies = $this->kernel->getContainer()->get(Dependencies::class); - $this->dependencies = $deps; + $this->dependencies = $dependencies; $this->dependencies->getEventDispatcher()->dispatch(new WorkerKernelRebootedEvent()); } diff --git a/tests/Worker/WorkerTest.php b/tests/Worker/WorkerTest.php index f722f0c..d600f35 100644 --- a/tests/Worker/WorkerTest.php +++ b/tests/Worker/WorkerTest.php @@ -12,7 +12,7 @@ use Baldinof\RoadRunnerBundle\Reboot\KernelRebootStrategyInterface; use Baldinof\RoadRunnerBundle\RoadRunnerBridge\HttpFoundationWorkerInterface; use Baldinof\RoadRunnerBundle\Worker\Dependencies; -use Baldinof\RoadRunnerBundle\Worker\Worker; +use Baldinof\RoadRunnerBundle\Worker\HttpWorker; use Iterator; use PHPUnit\Framework\Assert; use PHPUnit\Framework\TestCase; @@ -34,7 +34,7 @@ class WorkerTest extends TestCase public static $rebootStrategyReturns = false; - private Worker $worker; + private HttpWorker $worker; private \SplStack $requests; private \Closure $responder; @@ -96,7 +96,7 @@ public function clear(): void $c->set(Dependencies::class, new Dependencies(new MiddlewareStack($this->handler), $kernelBootStrategyClass, $this->eventDispatcher)); - $this->worker = new Worker( + $this->worker = new HttpWorker( $this->kernel->reveal(), new NullLogger(), $this->psrClient->reveal() From 0904f1887f392c2d83b45c12ea097c2cbeebafaf Mon Sep 17 00:00:00 2001 From: Dmitry Derepko Date: Mon, 5 Jul 2021 23:23:16 +0300 Subject: [PATCH 03/16] Add aliases for another dependencies --- config/services.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/config/services.php b/config/services.php index eae5436..2fc1a7b 100644 --- a/config/services.php +++ b/config/services.php @@ -22,8 +22,8 @@ use Spiral\Goridge\RPC\RPCInterface; use Spiral\RoadRunner\Environment; use Spiral\RoadRunner\EnvironmentInterface; -use Spiral\RoadRunner\Http\HttpWorker; -use Spiral\RoadRunner\Http\HttpWorkerInterface; +use Spiral\RoadRunner\Http\HttpWorker as RoadRunnerHttpWorker; +use Spiral\RoadRunner\Http\HttpWorkerInterface as RoadRunnerHttpWorkerInterface; use Spiral\RoadRunner\Metrics\Metrics; use Spiral\RoadRunner\Metrics\MetricsInterface; use Spiral\RoadRunner\Worker as RoadRunnerWorker; @@ -52,7 +52,7 @@ function service(string $id): ReferenceConfigurator ->factory([RoadRunnerWorker::class, 'createFromEnvironment']) ->args([service(EnvironmentInterface::class), '%baldinof_road_runner.intercept_side_effect%']); - $services->set(HttpWorkerInterface::class, HttpWorker::class) + $services->set(RoadRunnerHttpWorkerInterface::class, RoadRunnerHttpWorker::class) ->args([service(RoadRunnerWorkerInterface::class)]); $services->set(RPCInterface::class) @@ -64,7 +64,7 @@ function service(string $id): ReferenceConfigurator // Bundle services $services->set(HttpFoundationWorkerInterface::class, HttpFoundationWorker::class) - ->args([service(HttpWorkerInterface::class)]); + ->args([service(RoadRunnerHttpWorkerInterface::class)]); $services->set(HttpWorker::class) ->public() // Manually retrieved on the DIC in the Worker if the kernel has been rebooted From 3249c2f8f3350f8af328c5663534331c7537d6d6 Mon Sep 17 00:00:00 2001 From: Dmitry Derepko Date: Mon, 5 Jul 2021 23:24:39 +0300 Subject: [PATCH 04/16] Add worker resolver and temporal worker implementation --- src/Temporal/TemporalWorkerFactory.php | 26 ++++++++++++ src/Worker/TemporalWorker.php | 55 ++++++++++++++++++++++++++ src/Worker/WorkerResolver.php | 37 +++++++++++++++++ src/Worker/WorkerResolverInterface.php | 9 +++++ 4 files changed, 127 insertions(+) create mode 100644 src/Temporal/TemporalWorkerFactory.php create mode 100644 src/Worker/TemporalWorker.php create mode 100644 src/Worker/WorkerResolver.php create mode 100644 src/Worker/WorkerResolverInterface.php diff --git a/src/Temporal/TemporalWorkerFactory.php b/src/Temporal/TemporalWorkerFactory.php new file mode 100644 index 0000000..e5ee441 --- /dev/null +++ b/src/Temporal/TemporalWorkerFactory.php @@ -0,0 +1,26 @@ +workerFactory = $workerFactory; + } + + public function create(string $queue = WorkerFactoryInterface::DEFAULT_TASK_QUEUE, WorkerOptions $workerOptions = null): WorkerInterface + { + return $this->workerFactory->newWorker( + $queue, + $workerOptions + ); + } +} \ No newline at end of file diff --git a/src/Worker/TemporalWorker.php b/src/Worker/TemporalWorker.php new file mode 100644 index 0000000..992046b --- /dev/null +++ b/src/Worker/TemporalWorker.php @@ -0,0 +1,55 @@ +workerFactory = $workerFactory; + + /** @var Dependencies $dependencies */ + $dependencies = $kernel->getContainer()->get(Dependencies::class); + $this->dependencies = $dependencies; + + $this->workflows = $workflows; + $this->activities = $activities; + } + + public function start(): void + { + $this->dependencies->getEventDispatcher()->dispatch(new WorkerStartEvent()); + $worker = $this->workerFactory->newWorker(); + + foreach ($this->workflows as $workflow) { + $worker->registerWorkflowTypes(get_class($workflow)); + } + + foreach ($this->activities as $activity) { + $worker->registerActivityImplementations($activity); + } + + $this->workerFactory->run(); + + $this->dependencies->getEventDispatcher()->dispatch(new WorkerStopEvent()); + } +} \ No newline at end of file diff --git a/src/Worker/WorkerResolver.php b/src/Worker/WorkerResolver.php new file mode 100644 index 0000000..233f68e --- /dev/null +++ b/src/Worker/WorkerResolver.php @@ -0,0 +1,37 @@ +environment = $environment; + $this->httpWorker = $httpWorker; + $this->temporalWorker = $temporalWorker; + } + + public function resolve(string $mode): WorkerInterface + { + if ($this->environment->getMode() === Mode::MODE_HTTP) { + return $this->httpWorker; + } + if ($this->environment->getMode() === Mode::MODE_TEMPORAL) { + return $this->temporalWorker; + } + + throw new \RuntimeException('Could not resolve worker.'); + } +} \ No newline at end of file diff --git a/src/Worker/WorkerResolverInterface.php b/src/Worker/WorkerResolverInterface.php new file mode 100644 index 0000000..3633f9e --- /dev/null +++ b/src/Worker/WorkerResolverInterface.php @@ -0,0 +1,9 @@ + Date: Mon, 5 Jul 2021 23:24:56 +0300 Subject: [PATCH 05/16] Add configuration for new worker --- config/services.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/config/services.php b/config/services.php index 2fc1a7b..0812213 100644 --- a/config/services.php +++ b/config/services.php @@ -17,6 +17,7 @@ use Baldinof\RoadRunnerBundle\RoadRunnerBridge\HttpFoundationWorkerInterface; use Baldinof\RoadRunnerBundle\Worker\Dependencies; use Baldinof\RoadRunnerBundle\Worker\HttpWorker; +use Baldinof\RoadRunnerBundle\Worker\TemporalWorker; use Baldinof\RoadRunnerBundle\Worker\WorkerInterface; use Psr\Log\LoggerInterface; use Spiral\Goridge\RPC\RPCInterface; @@ -29,6 +30,8 @@ use Spiral\RoadRunner\Worker as RoadRunnerWorker; use Spiral\RoadRunner\WorkerInterface as RoadRunnerWorkerInterface; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; +use Temporal\Worker\WorkerFactoryInterface; +use Temporal\WorkerFactory; // Polyfill of the `service()` function introduced in Symfony 5.1 when using older version if (!\function_exists('Symfony\Component\DependencyInjection\Loader\Configurator\service')) { @@ -75,6 +78,17 @@ function service(string $id): ReferenceConfigurator service(HttpFoundationWorkerInterface::class), ]); + $services->set(WorkerFactoryInterface::class) + ->factory([WorkerFactory::class, 'create']); + + $services->set(TemporalWorker::class) + ->public() // Manually retrieved on the DIC in the Worker if the kernel has been rebooted + ->tag('monolog.logger', ['channel' => BaldinofRoadRunnerExtension::MONOLOG_CHANNEL]) + ->args([ + service('kernel'), + service(WorkerFactoryInterface::class), + ]); + $services->set(Dependencies::class) ->public() // Manually retrieved on the DIC in the Worker if the kernel has been rebooted ->args([ From 02d538c9c0e114a568ef7a86c413f60255e7868d Mon Sep 17 00:00:00 2001 From: Dmitry Derepko Date: Mon, 5 Jul 2021 23:31:40 +0300 Subject: [PATCH 06/16] Add worker resolver to command and remove redundant test case --- src/Command/WorkerCommand.php | 52 ++++++++++------------------------- tests/WorkerCommandTest.php | 23 ++++++++-------- 2 files changed, 26 insertions(+), 49 deletions(-) diff --git a/src/Command/WorkerCommand.php b/src/Command/WorkerCommand.php index 5d234b6..6b43b08 100644 --- a/src/Command/WorkerCommand.php +++ b/src/Command/WorkerCommand.php @@ -4,68 +4,44 @@ namespace Baldinof\RoadRunnerBundle\Command; -use Baldinof\RoadRunnerBundle\Worker\WorkerInterface; -use Spiral\RoadRunner\Environment\Mode; +use Baldinof\RoadRunnerBundle\Worker\WorkerResolverInterface; +use Spiral\RoadRunner\EnvironmentInterface; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; final class WorkerCommand extends Command { protected static $defaultName = 'baldinof:roadrunner:worker'; - private WorkerInterface $worker; + private WorkerResolverInterface $workerResolver; + private EnvironmentInterface $environment; - public function __construct(WorkerInterface $worker) + public function __construct( + WorkerResolverInterface $workerResolver, + EnvironmentInterface $environment + ) { parent::__construct(); - $this->worker = $worker; + $this->workerResolver = $workerResolver; + $this->environment = $environment; } public function configure(): void { $this - ->setDescription('Run the roadrunner worker') + ->setDescription('Run the roadrunner') ->setHelp(<<.rr.yaml configuration file. EOF); } - protected function execute(InputInterface $input, OutputInterface $output) + protected function execute(InputInterface $input, OutputInterface $output): int { - if (getenv('RR_MODE') !== Mode::MODE_HTTP) { - $io = new SymfonyStyle($input, $output); - - $io->title('RoadRunner Bundle'); - $io->error('Command baldinof:roadrunner:worker should not be run manually'); - $io->writeln('You should reference this command in a .rr.yaml configuration file, then run bin/rr serve. Example:'); - $io->writeln(<< - http: - address: "0.0.0.0:8080" - - uploads: - forbid: [".php", ".exe", ".bat"] - - workers: - command: "php bin/console baldinof:roadrunner:worker" - relay: "unix://var/roadrunner.sock" - - static: - dir: "public" - forbid: [".php", ".htaccess"] - - YAML); - - $io->writeln('See RoadRunner and baldinof/roadrunner-bundle documentations.'); - - return 1; - } - - $this->worker->start(); + $worker = $this->workerResolver->resolve($this->environment->getMode()); + $worker->start(); return 0; } diff --git a/tests/WorkerCommandTest.php b/tests/WorkerCommandTest.php index 672278f..42a070d 100644 --- a/tests/WorkerCommandTest.php +++ b/tests/WorkerCommandTest.php @@ -6,8 +6,10 @@ use Baldinof\RoadRunnerBundle\Command\WorkerCommand; use Baldinof\RoadRunnerBundle\Worker\WorkerInterface; +use Baldinof\RoadRunnerBundle\Worker\WorkerResolverInterface; use PHPUnit\Framework\TestCase; use Spiral\RoadRunner\Environment\Mode; +use Spiral\RoadRunner\EnvironmentInterface; use Symfony\Component\Console\Tester\CommandTester; class WorkerCommandTest extends TestCase @@ -20,21 +22,20 @@ public function setUp(): void { self::$workerExecuted = false; - $worker = new class() implements WorkerInterface { - public function start(): void + $environment = $this->createMock(EnvironmentInterface::class); + $workerResolver = new class implements WorkerResolverInterface{ + public function resolve(string $mode): WorkerInterface { - WorkerCommandTest::$workerExecuted = true; + return new class() implements WorkerInterface { + public function start(): void + { + WorkerCommandTest::$workerExecuted = true; + } + }; } }; - $this->command = new CommandTester(new WorkerCommand($worker)); - } - - public function test_it_displays_help_on_manual_run() - { - $this->command->execute([]); - - $this->assertStringContainsString('should not be run manually', $this->command->getDisplay()); + $this->command = new CommandTester(new WorkerCommand($workerResolver, $environment)); } public function test_it_start_the_worker_when_ran_by_roadrunner() From 7a301b304b0cabd141b020a8caa8668163b8e1d0 Mon Sep 17 00:00:00 2001 From: Dmitry Derepko Date: Fri, 9 Jul 2021 00:32:12 +0300 Subject: [PATCH 07/16] Improve .gitignore --- .gitignore | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 73cc28e..62f0096 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ -/vendor -/tests/__cache -/.phpunit.result.cache +.idea +vendor +tests/__cache +.phpunit.result.cache From 52adfb3ef6e4512b607ecc76243e0d789be5203c Mon Sep 17 00:00:00 2001 From: Dmitry Derepko Date: Fri, 9 Jul 2021 00:33:39 +0300 Subject: [PATCH 08/16] Add configuration for catching workflows and activities --- config/services.php | 39 ++++++++++++++++++- .../BaldinofRoadRunnerExtension.php | 13 ++++++- 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/config/services.php b/config/services.php index 0812213..27147b3 100644 --- a/config/services.php +++ b/config/services.php @@ -5,6 +5,8 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator; use Baldinof\RoadRunnerBundle\Command\WorkerCommand; +use Baldinof\RoadRunnerBundle\Contract\ActivityInterface; +use Baldinof\RoadRunnerBundle\Contract\WorkflowInterface; use Baldinof\RoadRunnerBundle\DependencyInjection\BaldinofRoadRunnerExtension; use Baldinof\RoadRunnerBundle\Helpers\RPCFactory; use Baldinof\RoadRunnerBundle\Http\KernelHandler; @@ -19,6 +21,8 @@ use Baldinof\RoadRunnerBundle\Worker\HttpWorker; use Baldinof\RoadRunnerBundle\Worker\TemporalWorker; use Baldinof\RoadRunnerBundle\Worker\WorkerInterface; +use Baldinof\RoadRunnerBundle\Worker\WorkerResolver; +use Baldinof\RoadRunnerBundle\Worker\WorkerResolverInterface; use Psr\Log\LoggerInterface; use Spiral\Goridge\RPC\RPCInterface; use Spiral\RoadRunner\Environment; @@ -30,11 +34,15 @@ use Spiral\RoadRunner\Worker as RoadRunnerWorker; use Spiral\RoadRunner\WorkerInterface as RoadRunnerWorkerInterface; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; +use Temporal\Client\GRPC\ServiceClient; +use Temporal\Client\WorkflowClient; +use Temporal\Client\WorkflowClientInterface; use Temporal\Worker\WorkerFactoryInterface; use Temporal\WorkerFactory; +use function function_exists; // Polyfill of the `service()` function introduced in Symfony 5.1 when using older version -if (!\function_exists('Symfony\Component\DependencyInjection\Loader\Configurator\service')) { +if (!function_exists('Symfony\Component\DependencyInjection\Loader\Configurator\service')) { function service(string $id): ReferenceConfigurator { return ref($id); @@ -87,6 +95,8 @@ function service(string $id): ReferenceConfigurator ->args([ service('kernel'), service(WorkerFactoryInterface::class), + tagged_iterator('baldinof_road_runner.temporal_workflows'), + tagged_iterator('baldinof_road_runner.temporal_activities'), ]); $services->set(Dependencies::class) @@ -97,8 +107,18 @@ function service(string $id): ReferenceConfigurator service(EventDispatcherInterface::class), ]); + $services->set(WorkerResolverInterface::class, WorkerResolver::class) + ->args([ + service(EnvironmentInterface::class), + service(HttpWorker::class), + service(TemporalWorker::class), + ]); + $services->set(WorkerCommand::class) - ->args([service(WorkerInterface::class)]) + ->args([ + service(WorkerResolverInterface::class), + service(EnvironmentInterface::class) + ]) ->autoconfigure(); $services->set(KernelHandler::class) @@ -119,4 +139,19 @@ function service(string $id): ReferenceConfigurator service(StreamedResponseListener::class.'.inner'), '%env(default::RR_MODE)%', ]); + + $services + ->set(WorkflowClientInterface::class, WorkflowClient::class) + ->args([ + service(ServiceClient::class) + ]) + ; + + $services + ->set(ServiceClient::class) + ->factory([ServiceClient::class, 'create']) + ->args([ + 'localhost:7233' + ]) + ; }; diff --git a/src/DependencyInjection/BaldinofRoadRunnerExtension.php b/src/DependencyInjection/BaldinofRoadRunnerExtension.php index be284f7..2be31b4 100644 --- a/src/DependencyInjection/BaldinofRoadRunnerExtension.php +++ b/src/DependencyInjection/BaldinofRoadRunnerExtension.php @@ -15,12 +15,14 @@ use Baldinof\RoadRunnerBundle\Integration\Symfony\ConfigureVarDumperListener; use Baldinof\RoadRunnerBundle\Reboot\KernelRebootStrategyInterface; use Baldinof\RoadRunnerBundle\Reboot\OnExceptionRebootStrategy; +use BlackfireProbe; use Doctrine\Persistence\ManagerRegistry; use Psr\Log\LoggerInterface; use Sentry\State\HubInterface; use Spiral\RoadRunner\Metrics\Collector; use Spiral\RoadRunner\Metrics\MetricsInterface; use Symfony\Component\Config\FileLocator; +use Symfony\Component\DependencyInjection\ChildDefinition; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Exception\LogicException; @@ -28,6 +30,8 @@ use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; use Symfony\Component\DependencyInjection\Reference; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; +use Temporal\Activity\ActivityInterface; +use Temporal\Workflow\WorkflowInterface; class BaldinofRoadRunnerExtension extends Extension { @@ -56,6 +60,13 @@ public function load(array $configs, ContainerBuilder $container): void $container->setParameter('baldinof_road_runner.middlewares', $config['middlewares']); + $container->registerAttributeForAutoconfiguration(WorkflowInterface::class, function (ChildDefinition $definition){ + $definition->addTag('baldinof_road_runner.temporal_workflows'); + }); + $container->registerAttributeForAutoconfiguration(ActivityInterface::class, function (ChildDefinition $definition){ + $definition->addTag('baldinof_road_runner.temporal_activities'); + }); + $this->loadIntegrations($container, $config); if ($config['metrics']['enabled']) { @@ -86,7 +97,7 @@ private function loadIntegrations(ContainerBuilder $container, array $config): v /** @var array */ $bundles = $container->getParameter('kernel.bundles'); - if (class_exists(\BlackfireProbe::class)) { + if (class_exists(BlackfireProbe::class)) { $container->register(BlackfireMiddleware::class); $beforeMiddlewares[] = BlackfireMiddleware::class; } From 4db5a9aa0acf0acd8bf4ee02390bba5a0bed5ba7 Mon Sep 17 00:00:00 2001 From: Dmitry Derepko Date: Sun, 1 Aug 2021 01:57:20 +0300 Subject: [PATCH 09/16] Move temporal sdk to dev requirements --- composer.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index be26a9d..0b5279a 100644 --- a/composer.json +++ b/composer.json @@ -26,8 +26,7 @@ "spiral/roadrunner-worker": ">=2.0.3", "spiral/goridge": "^3.0", "symfony/psr-http-message-bridge": "^1.1 || ^2.0", - "psr/log": "^1.1", - "temporal/sdk": "^1.0" + "psr/log": "^1.1" }, "suggest": { "nyholm/psr7": "For a super lightweight PSR-7/17 implementation", @@ -51,7 +50,8 @@ "spiral/roadrunner-metrics": "^2.0.1", "mikey179/vfsstream": "^1.6.8", "pestphp/pest-plugin-expectations": "^1.0", - "symfony/runtime": "^5.3.0" + "symfony/runtime": "^5.3.0", + "temporal/sdk": "^1.0" }, "conflict": { "doctrine/doctrine-bundle": "<2.1.1", From 87e6de4eda6ac9204e33c46fa7149c253b90d396 Mon Sep 17 00:00:00 2001 From: Dmitry Derepko Date: Sun, 1 Aug 2021 03:08:15 +0300 Subject: [PATCH 10/16] Split configuration --- config/services.php | 54 -------------- config/services_temporal.php | 74 +++++++++++++++++++ .../BaldinofRoadRunnerExtension.php | 10 +++ 3 files changed, 84 insertions(+), 54 deletions(-) create mode 100644 config/services_temporal.php diff --git a/config/services.php b/config/services.php index 27147b3..63fb5e8 100644 --- a/config/services.php +++ b/config/services.php @@ -4,9 +4,6 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator; -use Baldinof\RoadRunnerBundle\Command\WorkerCommand; -use Baldinof\RoadRunnerBundle\Contract\ActivityInterface; -use Baldinof\RoadRunnerBundle\Contract\WorkflowInterface; use Baldinof\RoadRunnerBundle\DependencyInjection\BaldinofRoadRunnerExtension; use Baldinof\RoadRunnerBundle\Helpers\RPCFactory; use Baldinof\RoadRunnerBundle\Http\KernelHandler; @@ -19,10 +16,6 @@ use Baldinof\RoadRunnerBundle\RoadRunnerBridge\HttpFoundationWorkerInterface; use Baldinof\RoadRunnerBundle\Worker\Dependencies; use Baldinof\RoadRunnerBundle\Worker\HttpWorker; -use Baldinof\RoadRunnerBundle\Worker\TemporalWorker; -use Baldinof\RoadRunnerBundle\Worker\WorkerInterface; -use Baldinof\RoadRunnerBundle\Worker\WorkerResolver; -use Baldinof\RoadRunnerBundle\Worker\WorkerResolverInterface; use Psr\Log\LoggerInterface; use Spiral\Goridge\RPC\RPCInterface; use Spiral\RoadRunner\Environment; @@ -34,11 +27,6 @@ use Spiral\RoadRunner\Worker as RoadRunnerWorker; use Spiral\RoadRunner\WorkerInterface as RoadRunnerWorkerInterface; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; -use Temporal\Client\GRPC\ServiceClient; -use Temporal\Client\WorkflowClient; -use Temporal\Client\WorkflowClientInterface; -use Temporal\Worker\WorkerFactoryInterface; -use Temporal\WorkerFactory; use function function_exists; // Polyfill of the `service()` function introduced in Symfony 5.1 when using older version @@ -86,19 +74,6 @@ function service(string $id): ReferenceConfigurator service(HttpFoundationWorkerInterface::class), ]); - $services->set(WorkerFactoryInterface::class) - ->factory([WorkerFactory::class, 'create']); - - $services->set(TemporalWorker::class) - ->public() // Manually retrieved on the DIC in the Worker if the kernel has been rebooted - ->tag('monolog.logger', ['channel' => BaldinofRoadRunnerExtension::MONOLOG_CHANNEL]) - ->args([ - service('kernel'), - service(WorkerFactoryInterface::class), - tagged_iterator('baldinof_road_runner.temporal_workflows'), - tagged_iterator('baldinof_road_runner.temporal_activities'), - ]); - $services->set(Dependencies::class) ->public() // Manually retrieved on the DIC in the Worker if the kernel has been rebooted ->args([ @@ -107,20 +82,6 @@ function service(string $id): ReferenceConfigurator service(EventDispatcherInterface::class), ]); - $services->set(WorkerResolverInterface::class, WorkerResolver::class) - ->args([ - service(EnvironmentInterface::class), - service(HttpWorker::class), - service(TemporalWorker::class), - ]); - - $services->set(WorkerCommand::class) - ->args([ - service(WorkerResolverInterface::class), - service(EnvironmentInterface::class) - ]) - ->autoconfigure(); - $services->set(KernelHandler::class) ->args([ service('kernel'), @@ -139,19 +100,4 @@ function service(string $id): ReferenceConfigurator service(StreamedResponseListener::class.'.inner'), '%env(default::RR_MODE)%', ]); - - $services - ->set(WorkflowClientInterface::class, WorkflowClient::class) - ->args([ - service(ServiceClient::class) - ]) - ; - - $services - ->set(ServiceClient::class) - ->factory([ServiceClient::class, 'create']) - ->args([ - 'localhost:7233' - ]) - ; }; diff --git a/config/services_temporal.php b/config/services_temporal.php new file mode 100644 index 0000000..b2705c8 --- /dev/null +++ b/config/services_temporal.php @@ -0,0 +1,74 @@ +parameters() + ->set('baldinof_road_runner.temporal_address', '127.0.0.1:7233'); + + $services = $container->services(); + + $services->set(WorkerFactoryInterface::class) + ->factory([WorkerFactory::class, 'create']); + + $services->set(TemporalWorker::class) + ->public() // Manually retrieved on the DIC in the Worker if the kernel has been rebooted + ->tag('monolog.logger', ['channel' => BaldinofRoadRunnerExtension::MONOLOG_CHANNEL]) + ->args([ + service('kernel'), + service(WorkerFactoryInterface::class), + tagged_iterator('baldinof_road_runner.temporal_workflows'), + tagged_iterator('baldinof_road_runner.temporal_activities'), + ]); + + $services->set(WorkerResolverInterface::class, WorkerResolver::class) + ->args([ + service(EnvironmentInterface::class), + service(HttpWorker::class), + service(TemporalWorker::class), + ]); + + $services->set(WorkerCommand::class) + ->args([ + service(WorkerResolverInterface::class), + service(EnvironmentInterface::class), + ]) + ->autoconfigure(); + + $services + ->set(WorkflowClientInterface::class, WorkflowClient::class) + ->args([ + service(ServiceClient::class), + ]); + + $services + ->set(ServiceClient::class) + ->factory([ServiceClient::class, 'create']) + ->args([ + param('baldinof_road_runner.temporal_address') + ]); +}; diff --git a/src/DependencyInjection/BaldinofRoadRunnerExtension.php b/src/DependencyInjection/BaldinofRoadRunnerExtension.php index 2be31b4..c356582 100644 --- a/src/DependencyInjection/BaldinofRoadRunnerExtension.php +++ b/src/DependencyInjection/BaldinofRoadRunnerExtension.php @@ -31,6 +31,7 @@ use Symfony\Component\DependencyInjection\Reference; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; use Temporal\Activity\ActivityInterface; +use Temporal\Client\WorkflowClientInterface; use Temporal\Workflow\WorkflowInterface; class BaldinofRoadRunnerExtension extends Extension @@ -48,6 +49,10 @@ public function load(array $configs, ContainerBuilder $container): void $loader = new PhpFileLoader($container, new FileLocator(__DIR__.'/../../config')); $loader->load('services.php'); + if ($this->isTemporalSdkInstalled()) { + $loader->load('services_temporal.php'); + } + if ($container->getParameter('kernel.debug')) { $this->loadDebug($container); } @@ -160,4 +165,9 @@ private function configureMetrics(array $config, ContainerBuilder $container): v $listenerDef->addMethodCall('addCollector', [$name, $metric]); } } + + private function isTemporalSdkInstalled(): bool + { + return interface_exists(WorkflowClientInterface::class); + } } From e32fd0319e431efdac300b498a979b9fdc9c9eab Mon Sep 17 00:00:00 2001 From: Dmitry Derepko Date: Sun, 1 Aug 2021 03:08:30 +0300 Subject: [PATCH 11/16] Add example to .rr.yaml file --- .rr.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.rr.yaml b/.rr.yaml index b414c54..99ba20d 100644 --- a/.rr.yaml +++ b/.rr.yaml @@ -26,6 +26,12 @@ logs: metrics: level: error +# Uncomment to use temporal integration +# temporal: +# address: localhost:7233 +# activities: +# num_workers: 5 + # Uncomment to use metrics integration # rpc: # listen: tcp://127.0.0.1:6001 From b9292c27475426e2e035f705669c73f69d6f693d Mon Sep 17 00:00:00 2001 From: Dmitry Derepko Date: Sun, 1 Aug 2021 03:18:16 +0300 Subject: [PATCH 12/16] Remove unused class --- src/Temporal/TemporalWorkerFactory.php | 26 -------------------------- 1 file changed, 26 deletions(-) delete mode 100644 src/Temporal/TemporalWorkerFactory.php diff --git a/src/Temporal/TemporalWorkerFactory.php b/src/Temporal/TemporalWorkerFactory.php deleted file mode 100644 index e5ee441..0000000 --- a/src/Temporal/TemporalWorkerFactory.php +++ /dev/null @@ -1,26 +0,0 @@ -workerFactory = $workerFactory; - } - - public function create(string $queue = WorkerFactoryInterface::DEFAULT_TASK_QUEUE, WorkerOptions $workerOptions = null): WorkerInterface - { - return $this->workerFactory->newWorker( - $queue, - $workerOptions - ); - } -} \ No newline at end of file From 54ace14fcc8b21a6f8033022964b053dc58960b7 Mon Sep 17 00:00:00 2001 From: Dmitry Derepko Date: Sun, 1 Aug 2021 03:41:27 +0300 Subject: [PATCH 13/16] Adjust workers configuration --- config/services.php | 2 +- config/services_temporal.php | 14 +++++++++----- src/Worker/HttpWorker.php | 2 +- src/Worker/TemporalWorker.php | 2 +- src/Worker/WorkerResolver.php | 3 +-- 5 files changed, 13 insertions(+), 10 deletions(-) diff --git a/config/services.php b/config/services.php index 63fb5e8..bea1126 100644 --- a/config/services.php +++ b/config/services.php @@ -66,8 +66,8 @@ function service(string $id): ReferenceConfigurator ->args([service(RoadRunnerHttpWorkerInterface::class)]); $services->set(HttpWorker::class) - ->public() // Manually retrieved on the DIC in the Worker if the kernel has been rebooted ->tag('monolog.logger', ['channel' => BaldinofRoadRunnerExtension::MONOLOG_CHANNEL]) + ->lazy() ->args([ service('kernel'), service(LoggerInterface::class), diff --git a/config/services_temporal.php b/config/services_temporal.php index b2705c8..62e776d 100644 --- a/config/services_temporal.php +++ b/config/services_temporal.php @@ -32,12 +32,14 @@ function service(string $id): ReferenceConfigurator $services = $container->services(); - $services->set(WorkerFactoryInterface::class) + $services + ->set(WorkerFactoryInterface::class) ->factory([WorkerFactory::class, 'create']); - $services->set(TemporalWorker::class) - ->public() // Manually retrieved on the DIC in the Worker if the kernel has been rebooted + $services + ->set(TemporalWorker::class) ->tag('monolog.logger', ['channel' => BaldinofRoadRunnerExtension::MONOLOG_CHANNEL]) + ->lazy() ->args([ service('kernel'), service(WorkerFactoryInterface::class), @@ -45,14 +47,16 @@ function service(string $id): ReferenceConfigurator tagged_iterator('baldinof_road_runner.temporal_activities'), ]); - $services->set(WorkerResolverInterface::class, WorkerResolver::class) + $services + ->set(WorkerResolverInterface::class, WorkerResolver::class) ->args([ service(EnvironmentInterface::class), service(HttpWorker::class), service(TemporalWorker::class), ]); - $services->set(WorkerCommand::class) + $services + ->set(WorkerCommand::class) ->args([ service(WorkerResolverInterface::class), service(EnvironmentInterface::class), diff --git a/src/Worker/HttpWorker.php b/src/Worker/HttpWorker.php index 854e80c..0489ead 100644 --- a/src/Worker/HttpWorker.php +++ b/src/Worker/HttpWorker.php @@ -19,7 +19,7 @@ /** * @internal */ -final class HttpWorker implements WorkerInterface +class HttpWorker implements WorkerInterface { private KernelInterface $kernel; private LoggerInterface $logger; diff --git a/src/Worker/TemporalWorker.php b/src/Worker/TemporalWorker.php index 992046b..ee19e84 100644 --- a/src/Worker/TemporalWorker.php +++ b/src/Worker/TemporalWorker.php @@ -11,7 +11,7 @@ /** * @internal */ -final class TemporalWorker implements WorkerInterface +class TemporalWorker implements WorkerInterface { private Dependencies $dependencies; private WorkerFactoryInterface $workerFactory; diff --git a/src/Worker/WorkerResolver.php b/src/Worker/WorkerResolver.php index 233f68e..3be8fec 100644 --- a/src/Worker/WorkerResolver.php +++ b/src/Worker/WorkerResolver.php @@ -16,8 +16,7 @@ public function __construct( EnvironmentInterface $environment, HttpWorker $httpWorker, TemporalWorker $temporalWorker - ) - { + ) { $this->environment = $environment; $this->httpWorker = $httpWorker; $this->temporalWorker = $temporalWorker; From b062bc2303f1cb67badf8a135a754f6b0274f2b4 Mon Sep 17 00:00:00 2001 From: Dmitry Derepko Date: Sun, 1 Aug 2021 03:56:09 +0300 Subject: [PATCH 14/16] Give back error message --- src/Command/WorkerCommand.php | 24 ++++++++++++++++++- .../UnsupportedRoadRunnerModeException.php | 13 ++++++++++ src/Worker/WorkerResolver.php | 3 ++- 3 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 src/Exception/UnsupportedRoadRunnerModeException.php diff --git a/src/Command/WorkerCommand.php b/src/Command/WorkerCommand.php index 6b43b08..becaf64 100644 --- a/src/Command/WorkerCommand.php +++ b/src/Command/WorkerCommand.php @@ -4,11 +4,13 @@ namespace Baldinof\RoadRunnerBundle\Command; +use Baldinof\RoadRunnerBundle\Exception\UnsupportedRoadRunnerModeException; use Baldinof\RoadRunnerBundle\Worker\WorkerResolverInterface; use Spiral\RoadRunner\EnvironmentInterface; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; final class WorkerCommand extends Command { @@ -40,7 +42,27 @@ public function configure(): void protected function execute(InputInterface $input, OutputInterface $output): int { - $worker = $this->workerResolver->resolve($this->environment->getMode()); + try { + $worker = $this->workerResolver->resolve($this->environment->getMode()); + } catch (UnsupportedRoadRunnerModeException $e) { + $content = file_get_contents(__DIR__.'/../../.rr.dev.yaml'); + + $io = new SymfonyStyle($input, $output); + + $io->title('RoadRunner Bundle'); + $io->error('Command baldinof:roadrunner:worker should not be run manually'); + $io->writeln('You should reference this command in a .rr.yaml configuration file, then run bin/rr serve. Example:'); + $io->writeln(<< + {$content} + + YAML); + + $io->writeln('See RoadRunner and baldinof/roadrunner-bundle documentations.'); + + return 1; + } + $worker->start(); return 0; diff --git a/src/Exception/UnsupportedRoadRunnerModeException.php b/src/Exception/UnsupportedRoadRunnerModeException.php new file mode 100644 index 0000000..d85f99d --- /dev/null +++ b/src/Exception/UnsupportedRoadRunnerModeException.php @@ -0,0 +1,13 @@ +temporalWorker; } - throw new \RuntimeException('Could not resolve worker.'); + throw new UnsupportedRoadRunnerModeException($mode); } } \ No newline at end of file From 34075f48b55dcde7ded8849ed1d6991399f7d48f Mon Sep 17 00:00:00 2001 From: Dmitry Derepko Date: Sun, 1 Aug 2021 03:56:25 +0300 Subject: [PATCH 15/16] Add temporal configuration to .rr.dev.yaml --- .rr.dev.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.rr.dev.yaml b/.rr.dev.yaml index a5dd3f2..951c5bf 100644 --- a/.rr.dev.yaml +++ b/.rr.dev.yaml @@ -15,6 +15,11 @@ http: dir: "public" forbid: [ ".php", ".htaccess" ] +temporal: + address: localhost:7233 + activities: + num_workers: 5 + logs: mode: development channels: From a239d1e6c05dbd78564dcdd72d55ad87d7f78f9a Mon Sep 17 00:00:00 2001 From: Dmitry Derepko Date: Sun, 1 Aug 2021 03:57:30 +0300 Subject: [PATCH 16/16] Give back `public` declaration for workers --- config/services.php | 1 + config/services_temporal.php | 1 + 2 files changed, 2 insertions(+) diff --git a/config/services.php b/config/services.php index bea1126..72b075c 100644 --- a/config/services.php +++ b/config/services.php @@ -66,6 +66,7 @@ function service(string $id): ReferenceConfigurator ->args([service(RoadRunnerHttpWorkerInterface::class)]); $services->set(HttpWorker::class) + ->public() // Manually retrieved on the DIC in the Worker if the kernel has been rebooted ->tag('monolog.logger', ['channel' => BaldinofRoadRunnerExtension::MONOLOG_CHANNEL]) ->lazy() ->args([ diff --git a/config/services_temporal.php b/config/services_temporal.php index 62e776d..999c92f 100644 --- a/config/services_temporal.php +++ b/config/services_temporal.php @@ -38,6 +38,7 @@ function service(string $id): ReferenceConfigurator $services ->set(TemporalWorker::class) + ->public() // Manually retrieved on the DIC in the Worker if the kernel has been rebooted ->tag('monolog.logger', ['channel' => BaldinofRoadRunnerExtension::MONOLOG_CHANNEL]) ->lazy() ->args([