From 8a69d92460a8c6074ebc6c8af26e928c41f3ce36 Mon Sep 17 00:00:00 2001 From: butschster Date: Fri, 12 Apr 2024 19:25:16 +0400 Subject: [PATCH] Use tokenizer listeners instead of tokenizer class locator to improve Spiral's performance during the bootloading stage. --- src/Bootloader/TemporalBridgeBootloader.php | 101 ++++++++------------ src/DeclarationLocator.php | 44 ++++++--- 2 files changed, 72 insertions(+), 73 deletions(-) diff --git a/src/Bootloader/TemporalBridgeBootloader.php b/src/Bootloader/TemporalBridgeBootloader.php index deecddd..b346329 100644 --- a/src/Bootloader/TemporalBridgeBootloader.php +++ b/src/Bootloader/TemporalBridgeBootloader.php @@ -23,7 +23,7 @@ use Spiral\TemporalBridge\WorkerFactoryInterface; use Spiral\TemporalBridge\WorkersRegistry; use Spiral\TemporalBridge\WorkersRegistryInterface; -use Spiral\Tokenizer\ClassesInterface; +use Spiral\Tokenizer\TokenizerListenerRegistryInterface; use Temporal\Client\GRPC\ServiceClient; use Temporal\Client\WorkflowClient; use Temporal\Client\WorkflowClientInterface; @@ -56,15 +56,46 @@ public function defineDependencies(): array public function defineSingletons(): array { return [ - TemporalWorkerFactoryInterface::class => [self::class, 'initWorkerFactory'], + TemporalWorkerFactoryInterface::class => static fn( + DataConverterInterface $dataConverter, + ): TemporalWorkerFactoryInterface => new TemporalWorkerFactory( + dataConverter: $dataConverter, + rpc: Goridge::create(), + ), WorkerFactoryInterface::class => WorkerFactory::class, - DeclarationLocatorInterface::class => [self::class, 'initDeclarationLocator'], - WorkflowClientInterface::class => [self::class, 'initWorkflowClient'], + + DeclarationLocatorInterface::class => static fn() => new DeclarationLocator( + reader: new AttributeReader(), + ), + + WorkflowClientInterface::class => static fn( + TemporalConfig $config, + DataConverterInterface $dataConverter, + PipelineProvider $pipelineProvider, + ServiceClientInterface $serviceClient, + ): WorkflowClientInterface => new WorkflowClient( + serviceClient: $serviceClient, + options: $config->getClientOptions(), + converter: $dataConverter, + interceptorProvider: $pipelineProvider, + ), WorkersRegistryInterface::class => WorkersRegistry::class, - ScheduleClientInterface::class => [self::class, 'initScheduleClient'], - DataConverterInterface::class => [self::class, 'initDataConverter'], + + ScheduleClientInterface::class => static fn( + TemporalConfig $config, + DataConverterInterface $dataConverter, + ServiceClientInterface $serviceClient, + ): ScheduleClientInterface => new ScheduleClient( + serviceClient: $serviceClient, + options: $config->getClientOptions(), + converter: $dataConverter, + ), + + DataConverterInterface::class => static fn() => DataConverter::createDefault(), PipelineProvider::class => [self::class, 'initPipelineProvider'], - ServiceClientInterface::class => [self::class, 'initServiceClient'], + ServiceClientInterface::class => static fn( + TemporalConfig $config, + ): ServiceClientInterface => ServiceClient::create($config->getAddress()), ]; } @@ -78,9 +109,11 @@ public function init( AbstractKernel $kernel, EnvironmentInterface $env, ConsoleBootloader $console, + TokenizerListenerRegistryInterface $tokenizer, + DeclarationLocator $locator, ): void { $this->initConfig($env); - + $tokenizer->addListener($locator); $console->addCommand(Commands\InfoCommand::class); $kernel->addDispatcher($this->factory->make(Dispatcher::class)); } @@ -133,41 +166,6 @@ protected function initConfig(EnvironmentInterface $env): void ); } - protected function initWorkflowClient( - TemporalConfig $config, - DataConverterInterface $dataConverter, - PipelineProvider $pipelineProvider, - ServiceClientInterface $serviceClient, - ): WorkflowClientInterface { - return new WorkflowClient( - serviceClient: $serviceClient, - options: $config->getClientOptions(), - converter: $dataConverter, - interceptorProvider: $pipelineProvider, - ); - } - - protected function initDataConverter(): DataConverterInterface - { - return DataConverter::createDefault(); - } - - protected function initWorkerFactory(DataConverterInterface $dataConverter,): TemporalWorkerFactoryInterface - { - return new TemporalWorkerFactory( - dataConverter: $dataConverter, - rpc: Goridge::create(), - ); - } - - protected function initDeclarationLocator(ClassesInterface $classes,): DeclarationLocatorInterface - { - return new DeclarationLocator( - classes: $classes, - reader: new AttributeReader(), - ); - } - protected function initPipelineProvider(TemporalConfig $config, FactoryInterface $factory): PipelineProvider { /** @var Interceptor[] $interceptors */ @@ -182,21 +180,4 @@ protected function initPipelineProvider(TemporalConfig $config, FactoryInterface return new SimplePipelineProvider($interceptors); } - - protected function initServiceClient(TemporalConfig $config): ServiceClientInterface - { - return ServiceClient::create($config->getAddress()); - } - - protected function initScheduleClient( - TemporalConfig $config, - DataConverterInterface $dataConverter, - ServiceClientInterface $serviceClient, - ): ScheduleClientInterface { - return new ScheduleClient( - serviceClient: $serviceClient, - options: $config->getClientOptions(), - converter: $dataConverter, - ); - } } diff --git a/src/DeclarationLocator.php b/src/DeclarationLocator.php index 066e48d..4f44444 100644 --- a/src/DeclarationLocator.php +++ b/src/DeclarationLocator.php @@ -5,32 +5,50 @@ namespace Spiral\TemporalBridge; use Spiral\Attributes\ReaderInterface; -use Spiral\Tokenizer\ClassesInterface; +use Spiral\Core\Attribute\Singleton; +use Spiral\Tokenizer\Attribute\TargetAttribute; +use Spiral\Tokenizer\TokenizationListenerInterface; use Temporal\Activity\ActivityInterface; use Temporal\Workflow\WorkflowInterface; -final class DeclarationLocator implements DeclarationLocatorInterface +#[Singleton] +#[TargetAttribute(WorkflowInterface::class)] +#[TargetAttribute(ActivityInterface::class)] +final class DeclarationLocator implements DeclarationLocatorInterface, TokenizationListenerInterface { + private array $declarations = []; + public function __construct( - private readonly ClassesInterface $classes, - private readonly ReaderInterface $reader + private readonly ReaderInterface $reader, ) { } public function getDeclarations(): iterable { - foreach ($this->classes->getClasses() as $class) { - if ($class->isAbstract() || $class->isInterface() || $class->isEnum()) { - continue; + foreach ($this->declarations as $type => $classes) { + foreach ($classes as $class) { + yield $type => $class; } + } + } - foreach (\array_merge($class->getInterfaces(), [$class]) as $type) { - if ($this->reader->firstClassMetadata($type, WorkflowInterface::class) !== null) { - yield WorkflowInterface::class => $class; - } elseif ($this->reader->firstClassMetadata($type, ActivityInterface::class) !== null) { - yield ActivityInterface::class => $class; - } + public function listen(\ReflectionClass $class): void + { + if ($class->isAbstract() || $class->isInterface() || $class->isEnum()) { + return; + } + + foreach (\array_merge($class->getInterfaces(), [$class]) as $type) { + if ($this->reader->firstClassMetadata($type, WorkflowInterface::class) !== null) { + $this->declarations[WorkflowInterface::class][] = $class; + } elseif ($this->reader->firstClassMetadata($type, ActivityInterface::class) !== null) { + $this->declarations[ActivityInterface::class][] = $class; } } } + + public function finalize(): void + { + // do nothing + } }