From fdbf137ed0c09c2ef94b4308ffbd1c9b9bba300b Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Thu, 31 Oct 2024 11:53:30 +0300 Subject: [PATCH 01/33] Remove `@internal` from `QueueInterface` --- src/QueueInterface.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/QueueInterface.php b/src/QueueInterface.php index 489909e1..80a5016b 100644 --- a/src/QueueInterface.php +++ b/src/QueueInterface.php @@ -10,10 +10,6 @@ use Yiisoft\Queue\Message\MessageInterface; use Yiisoft\Queue\Middleware\Push\MiddlewarePushInterface; -/** - * @internal Please don't use this interface. It is only used here to make tests simpler and will be removed - * after tests refactoring. Use the {@see Queue} class directly instead. - */ interface QueueInterface { /** From a26869474fcd8f2b486a684f02df0f70d6444a1f Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Fri, 1 Nov 2024 11:30:17 +0300 Subject: [PATCH 02/33] queue provider --- composer.json | 1 + src/Provider/ChannelNotFoundException.php | 22 +++++++ src/Provider/CompositeQueueProvider.php | 41 ++++++++++++ src/Provider/FactoryQueueProvider.php | 69 ++++++++++++++++++++ src/Provider/InvalidQueueConfigException.php | 11 ++++ src/Provider/PrototypeQueueProvider.php | 25 +++++++ src/Provider/QueueProviderException.php | 11 ++++ src/Provider/QueueProviderInterface.php | 19 ++++++ 8 files changed, 199 insertions(+) create mode 100644 src/Provider/ChannelNotFoundException.php create mode 100644 src/Provider/CompositeQueueProvider.php create mode 100644 src/Provider/FactoryQueueProvider.php create mode 100644 src/Provider/InvalidQueueConfigException.php create mode 100644 src/Provider/PrototypeQueueProvider.php create mode 100644 src/Provider/QueueProviderException.php create mode 100644 src/Provider/QueueProviderInterface.php diff --git a/composer.json b/composer.json index 664f5853..de5d4b2b 100644 --- a/composer.json +++ b/composer.json @@ -41,6 +41,7 @@ "psr/log": "^2.0|^3.0", "symfony/console": "^5.4|^6.0", "yiisoft/definitions": "^1.0|^2.0|^3.0", + "yiisoft/factory": "dev-strict", "yiisoft/friendly-exception": "^1.0", "yiisoft/injector": "^1.0" }, diff --git a/src/Provider/ChannelNotFoundException.php b/src/Provider/ChannelNotFoundException.php new file mode 100644 index 00000000..fa2a6695 --- /dev/null +++ b/src/Provider/ChannelNotFoundException.php @@ -0,0 +1,22 @@ +providers = $providers; + } + + public function get(string $channel): QueueInterface + { + foreach ($this->providers as $provider) { + if ($provider->has($channel)) { + return $provider->get($channel); + } + } + throw new ChannelNotFoundException($channel); + } + + public function has(string $channel): bool + { + foreach ($this->providers as $provider) { + if ($provider->has($channel)) { + return true; + } + } + return false; + } +} diff --git a/src/Provider/FactoryQueueProvider.php b/src/Provider/FactoryQueueProvider.php new file mode 100644 index 00000000..ee914eaf --- /dev/null +++ b/src/Provider/FactoryQueueProvider.php @@ -0,0 +1,69 @@ + + */ + private array $queues = []; + + private readonly StrictFactory $factory; + + /** + * @throws InvalidConfigException + */ + public function __construct( + private readonly array $definitions = [], + ?ContainerInterface $container = null, + bool $validate = true, + ) { + $this->factory = new StrictFactory($definitions, $container, $validate); + } + + public function get(string $channel): QueueInterface + { + $queue = $this->getOrTryCreate($channel); + if ($queue === null) { + throw new ChannelNotFoundException($channel); + } + return $queue; + } + + public function has(string $channel): bool + { + return array_key_exists($channel, $this->definitions); + } + + /** + * @throws InvalidQueueConfigException + */ + private function getOrTryCreate(string $channel): QueueInterface|null + { + if (array_key_exists($channel, $this->queues)) { + return $this->queues[$channel]; + } + + if ($this->factory->has($channel)) { + try { + $this->queues[$channel] = $this->factory->create($channel); + } catch (InvalidConfigException $exception) { + throw new InvalidQueueConfigException($exception->getMessage(), previous: $exception); + } + } else { + $this->queues[$channel] = null; + } + + return $this->queues[$channel]; + } +} diff --git a/src/Provider/InvalidQueueConfigException.php b/src/Provider/InvalidQueueConfigException.php new file mode 100644 index 00000000..e1c24a0c --- /dev/null +++ b/src/Provider/InvalidQueueConfigException.php @@ -0,0 +1,11 @@ +baseQueue->withChannelName($channel); + } + + public function has(string $channel): bool + { + return true; + } +} diff --git a/src/Provider/QueueProviderException.php b/src/Provider/QueueProviderException.php new file mode 100644 index 00000000..62a1a11c --- /dev/null +++ b/src/Provider/QueueProviderException.php @@ -0,0 +1,11 @@ + Date: Fri, 1 Nov 2024 12:33:38 +0300 Subject: [PATCH 03/33] improve --- src/Provider/FactoryQueueProvider.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Provider/FactoryQueueProvider.php b/src/Provider/FactoryQueueProvider.php index ee914eaf..81db8da3 100644 --- a/src/Provider/FactoryQueueProvider.php +++ b/src/Provider/FactoryQueueProvider.php @@ -24,7 +24,7 @@ final class FactoryQueueProvider implements QueueProviderInterface * @throws InvalidConfigException */ public function __construct( - private readonly array $definitions = [], + array $definitions = [], ?ContainerInterface $container = null, bool $validate = true, ) { @@ -42,7 +42,7 @@ public function get(string $channel): QueueInterface public function has(string $channel): bool { - return array_key_exists($channel, $this->definitions); + return $this->factory->has($channel); } /** From c8953c482ecee9fd7c75b7e64c12661cf4f346e6 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Tue, 5 Nov 2024 15:33:58 +0300 Subject: [PATCH 04/33] `QueueProviderInterfaceProxy` --- src/Debug/QueueFactoryInterfaceProxy.php | 24 ------------------- src/Debug/QueueProviderInterfaceProxy.php | 28 +++++++++++++++++++++++ 2 files changed, 28 insertions(+), 24 deletions(-) delete mode 100644 src/Debug/QueueFactoryInterfaceProxy.php create mode 100644 src/Debug/QueueProviderInterfaceProxy.php diff --git a/src/Debug/QueueFactoryInterfaceProxy.php b/src/Debug/QueueFactoryInterfaceProxy.php deleted file mode 100644 index cbfe4e76..00000000 --- a/src/Debug/QueueFactoryInterfaceProxy.php +++ /dev/null @@ -1,24 +0,0 @@ -queueFactory->get($channel); - - return new QueueDecorator($queue, $this->collector); - } -} diff --git a/src/Debug/QueueProviderInterfaceProxy.php b/src/Debug/QueueProviderInterfaceProxy.php new file mode 100644 index 00000000..5f00096e --- /dev/null +++ b/src/Debug/QueueProviderInterfaceProxy.php @@ -0,0 +1,28 @@ +queueProvider->get($channel); + return new QueueDecorator($queue, $this->collector); + } + + public function has(string $channel): bool + { + return $this->queueProvider->has($channel); + } +} From 372aeca96f1db4e6facead6a7de90debec77a208 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Tue, 5 Nov 2024 15:43:56 +0300 Subject: [PATCH 05/33] remove exceptions --- .../ChannelIncorrectlyConfigured.php | 47 ------------------- .../ChannelNotConfiguredException.php | 39 --------------- 2 files changed, 86 deletions(-) delete mode 100644 src/Exception/AdapterConfiguration/ChannelIncorrectlyConfigured.php delete mode 100644 src/Exception/AdapterConfiguration/ChannelNotConfiguredException.php diff --git a/src/Exception/AdapterConfiguration/ChannelIncorrectlyConfigured.php b/src/Exception/AdapterConfiguration/ChannelIncorrectlyConfigured.php deleted file mode 100644 index 9decddff..00000000 --- a/src/Exception/AdapterConfiguration/ChannelIncorrectlyConfigured.php +++ /dev/null @@ -1,47 +0,0 @@ -channel = $channel; - parent::__construct($message, $code, $previous); - } - - public function getName(): string - { - return 'Incorrect queue channel configuration'; - } - - public function getSolution(): ?string - { - $factoryClass = QueueFactory::class; - - return <<channel" which is incorrectly configured. - Please take a look to the documentation for the $factoryClass "\$definitions" constructor parameter. - SOLUTION; - } -} diff --git a/src/Exception/AdapterConfiguration/ChannelNotConfiguredException.php b/src/Exception/AdapterConfiguration/ChannelNotConfiguredException.php deleted file mode 100644 index ae417d60..00000000 --- a/src/Exception/AdapterConfiguration/ChannelNotConfiguredException.php +++ /dev/null @@ -1,39 +0,0 @@ -channel = $channel; - parent::__construct($message, $code, $previous); - } - - public function getName(): string - { - return 'Queue channel is not properly configured'; - } - - public function getSolution(): ?string - { - $factoryClass = QueueFactory::class; - - return <<channel" creation is not configured in the $factoryClass. - Please take a look to the documentation for the $factoryClass constructor. - The most important parameters are "\$definitions" and "\$enableRuntimeChannelDefinition". - - SOLUTION; - } -} From 3634ab131104b4bbc7918fdf69eb81d6f7e67084 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Tue, 5 Nov 2024 15:44:04 +0300 Subject: [PATCH 06/33] config --- config/di.php | 14 ++++++++------ config/params.php | 11 ++++------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/config/di.php b/config/di.php index 3af1ad8b..28d5bc26 100644 --- a/config/di.php +++ b/config/di.php @@ -19,9 +19,9 @@ use Yiisoft\Queue\Middleware\Push\MiddlewareFactoryPush; use Yiisoft\Queue\Middleware\Push\MiddlewareFactoryPushInterface; use Yiisoft\Queue\Middleware\Push\PushMiddlewareDispatcher; +use Yiisoft\Queue\Provider\FactoryQueueProvider; +use Yiisoft\Queue\Provider\QueueProviderInterface; use Yiisoft\Queue\Queue; -use Yiisoft\Queue\QueueFactory; -use Yiisoft\Queue\QueueFactoryInterface; use Yiisoft\Queue\QueueInterface; use Yiisoft\Queue\Worker\Worker as QueueWorker; use Yiisoft\Queue\Worker\WorkerInterface; @@ -29,6 +29,12 @@ /* @var array $params */ return [ + QueueProviderInterface::class => [ + 'class' => FactoryQueueProvider::class, + '__construct()' => [ + 'definitions' => $params['yiisoft/queue']['channel-definitions'], + ], + ], QueueWorker::class => [ 'class' => QueueWorker::class, '__construct()' => [$params['yiisoft/queue']['handlers']], @@ -39,10 +45,6 @@ ? $container->get(SignalLoop::class) : $container->get(SimpleLoop::class); }, - QueueFactoryInterface::class => QueueFactory::class, - QueueFactory::class => [ - '__construct()' => ['channelConfiguration' => $params['yiisoft/queue']['channel-definitions']], - ], QueueInterface::class => Queue::class, MiddlewareFactoryPushInterface::class => MiddlewareFactoryPush::class, MiddlewareFactoryConsumeInterface::class => MiddlewareFactoryConsume::class, diff --git a/config/params.php b/config/params.php index 1251c408..c1994af7 100644 --- a/config/params.php +++ b/config/params.php @@ -2,14 +2,13 @@ declare(strict_types=1); -use Yiisoft\Queue\Adapter\AdapterInterface; use Yiisoft\Queue\Command\ListenAllCommand; use Yiisoft\Queue\Command\ListenCommand; use Yiisoft\Queue\Command\RunCommand; use Yiisoft\Queue\Debug\QueueCollector; -use Yiisoft\Queue\Debug\QueueFactoryInterfaceProxy; +use Yiisoft\Queue\Debug\QueueProviderInterfaceProxy; use Yiisoft\Queue\Debug\QueueWorkerInterfaceProxy; -use Yiisoft\Queue\QueueFactoryInterface; +use Yiisoft\Queue\Provider\QueueProviderInterface; use Yiisoft\Queue\Worker\WorkerInterface; return [ @@ -22,9 +21,7 @@ ], 'yiisoft/queue' => [ 'handlers' => [], - 'channel-definitions' => [ - QueueFactoryInterface::DEFAULT_CHANNEL_NAME => AdapterInterface::class, - ], + 'channel-definitions' => [], 'middlewares-push' => [], 'middlewares-consume' => [], 'middlewares-fail' => [], @@ -34,7 +31,7 @@ QueueCollector::class, ], 'trackedServices' => [ - QueueFactoryInterface::class => [QueueFactoryInterfaceProxy::class, QueueCollector::class], + QueueProviderInterface::class => [QueueProviderInterfaceProxy::class, QueueCollector::class], WorkerInterface::class => [QueueWorkerInterfaceProxy::class, QueueCollector::class], ], ], From 7384ad082049ef6e7c8dddabd5ad0ae70e9b815c Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Tue, 5 Nov 2024 15:51:14 +0300 Subject: [PATCH 07/33] Remove factory --- src/Adapter/SynchronousAdapter.php | 4 +- src/Command/ListenAllCommand.php | 17 +- src/Command/ListenCommand.php | 13 +- src/Command/RunCommand.php | 10 +- .../AdapterNotConfiguredException.php | 3 - src/Queue.php | 5 +- src/QueueFactory.php | 192 ------------------ src/QueueFactoryInterface.php | 18 -- 8 files changed, 29 insertions(+), 233 deletions(-) delete mode 100644 src/QueueFactory.php delete mode 100644 src/QueueFactoryInterface.php diff --git a/src/Adapter/SynchronousAdapter.php b/src/Adapter/SynchronousAdapter.php index e0430733..46dca1df 100644 --- a/src/Adapter/SynchronousAdapter.php +++ b/src/Adapter/SynchronousAdapter.php @@ -7,7 +7,7 @@ use InvalidArgumentException; use Yiisoft\Queue\Enum\JobStatus; use Yiisoft\Queue\Message\MessageInterface; -use Yiisoft\Queue\QueueFactory; +use Yiisoft\Queue\Queue; use Yiisoft\Queue\QueueInterface; use Yiisoft\Queue\Worker\WorkerInterface; use Yiisoft\Queue\Message\IdEnvelope; @@ -20,7 +20,7 @@ final class SynchronousAdapter implements AdapterInterface public function __construct( private WorkerInterface $worker, private QueueInterface $queue, - private string $channel = QueueFactory::DEFAULT_CHANNEL_NAME, + private string $channel = Queue::DEFAULT_CHANNEL_NAME, ) { } diff --git a/src/Command/ListenAllCommand.php b/src/Command/ListenAllCommand.php index e94a77fe..021c3c0d 100644 --- a/src/Command/ListenAllCommand.php +++ b/src/Command/ListenAllCommand.php @@ -10,7 +10,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Yiisoft\Queue\Cli\LoopInterface; -use Yiisoft\Queue\QueueFactoryInterface; +use Yiisoft\Queue\Provider\QueueProviderInterface; final class ListenAllCommand extends Command { @@ -20,8 +20,11 @@ final class ListenAllCommand extends Command 'Listens all configured queues by default in case you\'re using yiisoft/config. ' . 'Needs to be stopped manually.'; - public function __construct(private QueueFactoryInterface $queueFactory, private LoopInterface $loop, private array $channels) - { + public function __construct( + private readonly QueueProviderInterface $queueProvider, + private readonly LoopInterface $loop, + private readonly array $channels + ) { parent::__construct(); } @@ -45,7 +48,7 @@ public function configure(): void 'm', InputOption::VALUE_REQUIRED, 'Maximum number of messages to process in each channel before switching to another channel. ' . - 'Default is 0 (no limits).', + 'Default is 0 (no limits).', 0, ); @@ -57,17 +60,17 @@ protected function execute(InputInterface $input, OutputInterface $output): int $queues = []; /** @var string $channel */ foreach ($input->getArgument('channel') as $channel) { - $queues[] = $this->queueFactory->get($channel); + $queues[] = $this->queueProvider->get($channel); } while ($this->loop->canContinue()) { $hasMessages = false; foreach ($queues as $queue) { - $hasMessages = $queue->run((int)$input->getOption('maximum')) > 0 || $hasMessages; + $hasMessages = $queue->run((int) $input->getOption('maximum')) > 0 || $hasMessages; } if (!$hasMessages) { - $pauseSeconds = (int)$input->getOption('pause'); + $pauseSeconds = (int) $input->getOption('pause'); if ($pauseSeconds < 0) { $pauseSeconds = 1; } diff --git a/src/Command/ListenCommand.php b/src/Command/ListenCommand.php index 21915c47..752852e9 100644 --- a/src/Command/ListenCommand.php +++ b/src/Command/ListenCommand.php @@ -8,16 +8,17 @@ use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Yiisoft\Queue\QueueFactory; -use Yiisoft\Queue\QueueFactoryInterface; +use Yiisoft\Queue\Provider\QueueProviderInterface; +use Yiisoft\Queue\Queue; final class ListenCommand extends Command { protected static $defaultName = 'queue:listen'; protected static $defaultDescription = 'Listens the queue and executes messages as they come. Needs to be stopped manually.'; - public function __construct(private QueueFactoryInterface $queueFactory) - { + public function __construct( + private readonly QueueProviderInterface $queueProvider + ) { parent::__construct(); } @@ -27,13 +28,13 @@ public function configure(): void 'channel', InputArgument::OPTIONAL, 'Queue channel name to connect to', - QueueFactory::DEFAULT_CHANNEL_NAME + Queue::DEFAULT_CHANNEL_NAME, ); } protected function execute(InputInterface $input, OutputInterface $output): int { - $this->queueFactory + $this->queueProvider ->get($input->getArgument('channel')) ->listen(); diff --git a/src/Command/RunCommand.php b/src/Command/RunCommand.php index f01a9e17..a6bd3c18 100644 --- a/src/Command/RunCommand.php +++ b/src/Command/RunCommand.php @@ -9,7 +9,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -use Yiisoft\Queue\QueueFactoryInterface; +use Yiisoft\Queue\Provider\QueueProviderInterface; final class RunCommand extends Command { @@ -17,8 +17,10 @@ final class RunCommand extends Command protected static $defaultDescription = 'Runs all the existing messages in the given queues. ' . 'Exits once messages are over.'; - public function __construct(private QueueFactoryInterface $queueFactory, private array $channels) - { + public function __construct( + private readonly QueueProviderInterface $queueProvider, + private readonly array $channels, + ) { parent::__construct(); } @@ -45,7 +47,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int /** @var string $channel */ foreach ($input->getArgument('channel') as $channel) { $output->write("Processing channel $channel... "); - $count = $this->queueFactory + $count = $this->queueProvider ->get($channel) ->run((int)$input->getOption('maximum')); diff --git a/src/Exception/AdapterConfiguration/AdapterNotConfiguredException.php b/src/Exception/AdapterConfiguration/AdapterNotConfiguredException.php index 487fa5ca..f5eec158 100644 --- a/src/Exception/AdapterConfiguration/AdapterNotConfiguredException.php +++ b/src/Exception/AdapterConfiguration/AdapterNotConfiguredException.php @@ -7,7 +7,6 @@ use RuntimeException; use Yiisoft\FriendlyException\FriendlyExceptionInterface; use Yiisoft\Queue\Queue; -use Yiisoft\Queue\QueueFactory; class AdapterNotConfiguredException extends RuntimeException implements FriendlyExceptionInterface { @@ -21,7 +20,6 @@ public function getName(): string public function getSolution(): ?string { $queueClass = Queue::class; - $factoryClass = QueueFactory::class; return <<middlewareDefinitions = $middlewareDefinitions; diff --git a/src/QueueFactory.php b/src/QueueFactory.php deleted file mode 100644 index e6b963d0..00000000 --- a/src/QueueFactory.php +++ /dev/null @@ -1,192 +0,0 @@ - $channelConfiguration Configuration array in [channel_name => definition] format. - * "Definition" here is a {@see Factory} definition - * @param QueueInterface $queue A default queue implementation. `$queue->withAdapter()` will be returned - * with the `get` method - * @param bool $enableRuntimeChannelDefinition A flag whether to enable a such behavior when there is no - * explicit channel adapter definition: `return $this->queue->withAdapter($this->adapter->withChannel($channel)` - * When this flag is set to false, only explicit definitions from the $definition parameter are used. - * @param AdapterInterface|null $defaultAdapter A default adapter implementation. - * It must be set when $enableRuntimeChannelDefinition is true. - */ - public function __construct( - private array $channelConfiguration, - private QueueInterface $queue, - private ContainerInterface $container, - private CallableFactory $callableFactory, - private Injector $injector, - private bool $enableRuntimeChannelDefinition = false, - private ?AdapterInterface $defaultAdapter = null, - ) { - if ($enableRuntimeChannelDefinition === true && $defaultAdapter === null) { - $message = 'Either $enableRuntimeChannelDefinition must be false, or $defaultAdapter should be provided.'; - - throw new InvalidArgumentException($message); - } - } - - public function get(string $channel = self::DEFAULT_CHANNEL_NAME): QueueInterface - { - if ($channel === $this->queue->getChannelName()) { - return $this->queue; - } - - if (isset($this->queueCollection[$channel]) && $this->queueCollection[$channel]->get() !== null) { - $queue = $this->queueCollection[$channel]->get(); - } else { - $queue = $this->create($channel); - $this->queueCollection[$channel] = WeakReference::create($queue); - } - - return $queue; - } - - /** - * @throws ChannelIncorrectlyConfigured - * @return QueueInterface - */ - private function create(string $channel): QueueInterface - { - if (isset($this->channelConfiguration[$channel])) { - $definition = $this->channelConfiguration[$channel]; - $this->checkDefinitionType($channel, $definition); - $adapter = $this->createFromDefinition($channel, $definition)->withChannel($channel); - - return $this->queue->withChannelName($channel)->withAdapter($adapter); - } - - if ($this->enableRuntimeChannelDefinition === false) { - throw new ChannelNotConfiguredException($channel); - } - - /** @psalm-suppress PossiblyNullReference */ - return $this->queue->withChannelName($channel)->withAdapter($this->defaultAdapter->withChannel($channel)); - } - - private function checkDefinitionType(string $channel, mixed $definition): void - { - if ( - !$definition instanceof AdapterInterface - && !is_array($definition) - && !is_callable($definition) - && !is_string($definition) - ) { - throw new ChannelIncorrectlyConfigured($channel, $definition); - } - } - - public function createFromDefinition( - string $channel, - AdapterInterface|callable|array|string $definition - ): AdapterInterface { - if ($definition instanceof AdapterInterface) { - return $definition; - } - - if (is_string($definition)) { - return $this->getFromContainer($channel, $definition); - } - - return $this->tryGetFromCallable($channel, $definition) - ?? $this->tryGetFromArrayDefinition($channel, $definition) - ?? throw new ChannelIncorrectlyConfigured($channel, $definition); - } - - private function getFromContainer(string $channel, string $definition): AdapterInterface - { - if (class_exists($definition)) { - if (is_subclass_of($definition, AdapterInterface::class)) { - /** @var AdapterInterface */ - return $this->container->get($definition); - } - } elseif ($this->container->has($definition)) { - $middleware = $this->container->get($definition); - if ($middleware instanceof AdapterInterface) { - return $middleware; - } - } - - throw new ChannelIncorrectlyConfigured($channel, $definition); - } - - private function tryGetFromCallable( - string $channel, - callable|AdapterInterface|array|string $definition - ): ?AdapterInterface { - $callable = null; - - if ($definition instanceof Closure) { - $callable = $definition; - } - - if ( - is_array($definition) - && array_keys($definition) === [0, 1] - ) { - try { - $callable = $this->callableFactory->create($definition); - } catch (InvalidCallableConfigurationException $exception) { - throw new ChannelIncorrectlyConfigured($channel, $definition, previous: $exception); - } - } - - if ($callable !== null) { - $adapter = $this->injector->invoke($callable); - - if (!$adapter instanceof AdapterInterface) { - throw new ChannelIncorrectlyConfigured($channel, $definition); - } - } - - return null; - } - - private function tryGetFromArrayDefinition( - string $channel, - callable|AdapterInterface|array|string $definition - ): ?AdapterInterface { - if (!is_array($definition)) { - return null; - } - - try { - DefinitionValidator::validateArrayDefinition($definition); - - $middleware = ArrayDefinition::fromConfig($definition)->resolve($this->container); - if ($middleware instanceof AdapterInterface) { - return $middleware; - } - - throw new ChannelIncorrectlyConfigured($channel, $definition); - } catch (InvalidConfigException) { - } - - throw new ChannelIncorrectlyConfigured($channel, $definition); - } -} diff --git a/src/QueueFactoryInterface.php b/src/QueueFactoryInterface.php deleted file mode 100644 index 9761e583..00000000 --- a/src/QueueFactoryInterface.php +++ /dev/null @@ -1,18 +0,0 @@ - Date: Tue, 5 Nov 2024 15:54:35 +0300 Subject: [PATCH 08/33] fix tests --- tests/Integration/QueueFactoryTest.php | 82 -------- tests/Unit/Command/ListenCommandTest.php | 6 +- tests/Unit/Command/RunCommandTest.php | 10 +- ...hp => QueueProviderInterfaceProxyTest.php} | 12 +- tests/Unit/QueueFactoryTest.php | 178 ------------------ tests/Unit/SynchronousAdapterTest.php | 4 +- 6 files changed, 16 insertions(+), 276 deletions(-) delete mode 100644 tests/Integration/QueueFactoryTest.php rename tests/Unit/Debug/{QueueFactoryInterfaceProxyTest.php => QueueProviderInterfaceProxyTest.php} (61%) delete mode 100644 tests/Unit/QueueFactoryTest.php diff --git a/tests/Integration/QueueFactoryTest.php b/tests/Integration/QueueFactoryTest.php deleted file mode 100644 index 50076896..00000000 --- a/tests/Integration/QueueFactoryTest.php +++ /dev/null @@ -1,82 +0,0 @@ -createMock(WorkerInterface::class); - $queue = $this->getDefaultQueue($worker); - $container = $this->createMock(ContainerInterface::class); - $factory = new QueueFactory( - [], - $queue, - $container, - new CallableFactory($container), - new Injector($container), - true, - new SynchronousAdapter($worker, $queue) - ); - - $adapter = $factory->get('test-channel'); - - self::assertEquals('test-channel', $adapter->getChannelName()); - } - - public function testConfiguredChange(): void - { - $worker = $this->createMock(WorkerInterface::class); - $queue = $this->getDefaultQueue($worker); - $container = $this->createMock(ContainerInterface::class); - $factory = new QueueFactory( - [ - 'test-channel' => [ - 'class' => FakeAdapter::class, - 'withChannel()' => ['test-channel'], - ], - QueueFactoryInterface::DEFAULT_CHANNEL_NAME => [ - 'class' => FakeAdapter::class, - 'withChannel()' => [QueueFactoryInterface::DEFAULT_CHANNEL_NAME], - ], - ], - $queue, - $container, - new CallableFactory($container), - new Injector($container), - true, - new SynchronousAdapter($worker, $queue) - ); - $queue = $factory->get('test-channel'); - - self::assertEquals('test-channel', $queue->getChannelName()); - self::assertEquals(QueueFactoryInterface::DEFAULT_CHANNEL_NAME, $factory->get()->getChannelName()); - } - - private function getDefaultQueue(WorkerInterface $worker): Queue - { - return new Queue( - $worker, - $this->createMock(LoopInterface::class), - $this->createMock(LoggerInterface::class), - new PushMiddlewareDispatcher($this->createMock(MiddlewareFactoryPushInterface::class)), - ); - } -} diff --git a/tests/Unit/Command/ListenCommandTest.php b/tests/Unit/Command/ListenCommandTest.php index f4a337a4..2e2971ea 100644 --- a/tests/Unit/Command/ListenCommandTest.php +++ b/tests/Unit/Command/ListenCommandTest.php @@ -8,14 +8,14 @@ use Symfony\Component\Console\Input\StringInput; use Symfony\Component\Console\Output\OutputInterface; use Yiisoft\Queue\Command\ListenCommand; -use Yiisoft\Queue\QueueFactoryInterface; +use Yiisoft\Queue\Provider\QueueProviderInterface; use Yiisoft\Queue\QueueInterface; final class ListenCommandTest extends TestCase { public function testConfigure(): void { - $command = new ListenCommand($this->createMock(QueueFactoryInterface::class)); + $command = new ListenCommand($this->createMock(QueueProviderInterface::class)); $channelArgument = $command->getNativeDefinition()->getArgument('channel'); $this->assertEquals('channel', $channelArgument->getName()); } @@ -24,7 +24,7 @@ public function testExecute(): void { $queue = $this->createMock(QueueInterface::class); $queue->expects($this->once())->method('listen'); - $queueFactory = $this->createMock(QueueFactoryInterface::class); + $queueFactory = $this->createMock(QueueProviderInterface::class); $queueFactory->method('get')->willReturn($queue); $input = new StringInput('channel'); diff --git a/tests/Unit/Command/RunCommandTest.php b/tests/Unit/Command/RunCommandTest.php index fb70914a..3e38305e 100644 --- a/tests/Unit/Command/RunCommandTest.php +++ b/tests/Unit/Command/RunCommandTest.php @@ -8,14 +8,14 @@ use Symfony\Component\Console\Input\StringInput; use Symfony\Component\Console\Output\OutputInterface; use Yiisoft\Queue\Command\RunCommand; -use Yiisoft\Queue\QueueFactoryInterface; +use Yiisoft\Queue\Provider\QueueProviderInterface; use Yiisoft\Queue\QueueInterface; final class RunCommandTest extends TestCase { public function testConfigure(): void { - $command = new RunCommand($this->createMock(QueueFactoryInterface::class), []); + $command = new RunCommand($this->createMock(QueueProviderInterface::class), []); $channelArgument = $command->getNativeDefinition()->getArgument('channel'); $this->assertEquals('channel', $channelArgument->getName()); } @@ -24,11 +24,11 @@ public function testExecute(): void { $queue = $this->createMock(QueueInterface::class); $queue->expects($this->once())->method('run'); - $queueFactory = $this->createMock(QueueFactoryInterface::class); - $queueFactory->method('get')->willReturn($queue); + $queueProvider = $this->createMock(QueueProviderInterface::class); + $queueProvider->method('get')->willReturn($queue); $input = new StringInput('channel'); - $command = new RunCommand($queueFactory, []); + $command = new RunCommand($queueProvider, []); $exitCode = $command->run($input, $this->createMock(OutputInterface::class)); $this->assertEquals(0, $exitCode); diff --git a/tests/Unit/Debug/QueueFactoryInterfaceProxyTest.php b/tests/Unit/Debug/QueueProviderInterfaceProxyTest.php similarity index 61% rename from tests/Unit/Debug/QueueFactoryInterfaceProxyTest.php rename to tests/Unit/Debug/QueueProviderInterfaceProxyTest.php index d8534aa3..2bde59c5 100644 --- a/tests/Unit/Debug/QueueFactoryInterfaceProxyTest.php +++ b/tests/Unit/Debug/QueueProviderInterfaceProxyTest.php @@ -7,20 +7,20 @@ use PHPUnit\Framework\TestCase; use Yiisoft\Queue\Debug\QueueCollector; use Yiisoft\Queue\Debug\QueueDecorator; -use Yiisoft\Queue\Debug\QueueFactoryInterfaceProxy; -use Yiisoft\Queue\QueueFactoryInterface; +use Yiisoft\Queue\Debug\QueueProviderInterfaceProxy; +use Yiisoft\Queue\Provider\QueueProviderInterface; use Yiisoft\Queue\QueueInterface; -class QueueFactoryInterfaceProxyTest extends TestCase +class QueueProviderInterfaceProxyTest extends TestCase { public function testGet(): void { - $queueFactory = $this->createMock(QueueFactoryInterface::class); + $queueFactory = $this->createMock(QueueProviderInterface::class); $queue = $this->createMock(QueueInterface::class); $queueFactory->expects($this->once())->method('get')->willReturn($queue); $collector = new QueueCollector(); - $factory = new QueueFactoryInterfaceProxy($queueFactory, $collector); + $factory = new QueueProviderInterfaceProxy($queueFactory, $collector); - $this->assertInstanceOf(QueueDecorator::class, $factory->get()); + $this->assertInstanceOf(QueueDecorator::class, $factory->get('test')); } } diff --git a/tests/Unit/QueueFactoryTest.php b/tests/Unit/QueueFactoryTest.php deleted file mode 100644 index a72f9751..00000000 --- a/tests/Unit/QueueFactoryTest.php +++ /dev/null @@ -1,178 +0,0 @@ -createMock(QueueInterface::class); - $queue - ->expects(self::once()) - ->method('withAdapter') - ->willReturn($queue); - $queue - ->expects(self::once()) - ->method('withChannelName') - ->willReturn($queue); - - $adapter = $this->createMock(AdapterInterface::class); - $adapter - ->expects(self::once()) - ->method('withChannel') - ->willReturn($adapter); - - $factory = new QueueFactory( - [], - $queue, - $this->getContainer(), - new CallableFactory($this->getContainer()), - new Injector($this->getContainer()), - true, - $adapter - ); - - $factory->get('test'); - } - - public function testThrowExceptionOnEmptyAdapter(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage( - 'Either $enableRuntimeChannelDefinition must be false, or $defaultAdapter should be provided.' - ); - - new QueueFactory( - [], - $this->createMock(QueueInterface::class), - $this->getContainer(), - new CallableFactory($this->getContainer()), - new Injector($this->getContainer()), - true - ); - } - - public function testThrowExceptionOnEmptyDefinition(): void - { - try { - $queue = $this->createMock(QueueInterface::class); - $factory = new QueueFactory( - [], - $queue, - $this->getContainer(), - new CallableFactory($this->getContainer()), - new Injector($this->getContainer()), - false - ); - - $factory->get('test'); - } catch (ChannelNotConfiguredException $exception) { - self::assertSame($exception::class, ChannelNotConfiguredException::class); - self::assertSame($exception->getName(), 'Queue channel is not properly configured'); - $this->assertMatchesRegularExpression('/"test"/', $exception->getSolution()); - } - } - - public function testThrowExceptionOnIncorrectDefinition(): void - { - try { - $queue = $this->createMock(QueueInterface::class); - $factory = new QueueFactory( - ['test' => new stdClass()], - $queue, - $this->getContainer(), - new CallableFactory($this->getContainer()), - new Injector($this->getContainer()), - false - ); - - $factory->get('test'); - } catch (ChannelIncorrectlyConfigured $exception) { - self::assertSame($exception::class, ChannelIncorrectlyConfigured::class); - self::assertSame($exception->getName(), 'Incorrect queue channel configuration'); - $this->assertMatchesRegularExpression('/"test"/', $exception->getSolution()); - } - } - - public function testSuccessfulDefinitionWithDefaultAdapter(): void - { - $adapterDefault = $this->createMock(AdapterInterface::class); - $adapterDefault->method('withChannel')->willReturn($adapterDefault); - - $adapterNew = $this->createMock(AdapterInterface::class); - $adapterNew->method('withChannel')->willReturn($adapterNew); - - $queue = $this->createMock(QueueInterface::class); - $queue - ->expects(self::once()) - ->method('withAdapter') - ->with($adapterNew) - ->willReturn($queue); - $queue - ->expects(self::once()) - ->method('withChannelName') - ->with('test') - ->willReturn($queue); - - $factory = new QueueFactory( - ['test' => $adapterNew], - $queue, - $this->getContainer(), - new CallableFactory($this->getContainer()), - new Injector($this->getContainer()), - false, - $adapterDefault - ); - - $factory->get('test'); - } - - public function testSuccessfulDefinitionWithoutDefaultAdapter(): void - { - $adapterNew = $this->createMock(AdapterInterface::class); - $adapterNew->method('withChannel')->willReturn($adapterNew); - - $queue = $this->createMock(QueueInterface::class); - $queue - ->expects(self::once()) - ->method('withAdapter') - ->with($adapterNew) - ->willReturn($queue); - $queue - ->expects(self::once()) - ->method('withChannelName') - ->with('test') - ->willReturn($queue); - - $factory = new QueueFactory( - ['test' => $adapterNew], - $queue, - $this->getContainer(), - new CallableFactory($this->getContainer()), - new Injector($this->getContainer()), - false - ); - - $factory->get('test'); - } - - private function getContainer(array $instances = []): ContainerInterface - { - return new SimpleContainer($instances); - } -} diff --git a/tests/Unit/SynchronousAdapterTest.php b/tests/Unit/SynchronousAdapterTest.php index 31a43f50..7c369ae7 100644 --- a/tests/Unit/SynchronousAdapterTest.php +++ b/tests/Unit/SynchronousAdapterTest.php @@ -6,7 +6,7 @@ use Yiisoft\Queue\Enum\JobStatus; use Yiisoft\Queue\Message\Message; -use Yiisoft\Queue\QueueFactory; +use Yiisoft\Queue\Queue; use Yiisoft\Queue\Tests\TestCase; use Yiisoft\Queue\Message\IdEnvelope; @@ -51,7 +51,7 @@ public function testIdSetting(): void public function testWithSameChannel(): void { $adapter = $this->getAdapter(); - self::assertEquals($adapter, $adapter->withChannel(QueueFactory::DEFAULT_CHANNEL_NAME)); + self::assertEquals($adapter, $adapter->withChannel(Queue::DEFAULT_CHANNEL_NAME)); } public function testWithAnotherChannel(): void From 47c69406d01ab26fa14ec54b49c9d85ff5f911e4 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Tue, 5 Nov 2024 16:08:01 +0300 Subject: [PATCH 09/33] test `PrototypeQueueProvider` --- src/Cli/StubLoop.php | 18 +++++++++ src/Worker/StubWorker.php | 16 ++++++++ tests/Unit/Cli/StubLoopTest.php | 26 +++++++++++++ .../Provider/PrototypeQueueProviderTest.php | 38 +++++++++++++++++++ tests/Unit/Worker/StubWorkerTest.php | 27 +++++++++++++ 5 files changed, 125 insertions(+) create mode 100644 src/Cli/StubLoop.php create mode 100644 src/Worker/StubWorker.php create mode 100644 tests/Unit/Cli/StubLoopTest.php create mode 100644 tests/Unit/Provider/PrototypeQueueProviderTest.php create mode 100644 tests/Unit/Worker/StubWorkerTest.php diff --git a/src/Cli/StubLoop.php b/src/Cli/StubLoop.php new file mode 100644 index 00000000..b38276e2 --- /dev/null +++ b/src/Cli/StubLoop.php @@ -0,0 +1,18 @@ +canContinue; + } +} diff --git a/src/Worker/StubWorker.php b/src/Worker/StubWorker.php new file mode 100644 index 00000000..398a7aae --- /dev/null +++ b/src/Worker/StubWorker.php @@ -0,0 +1,16 @@ + [true]; + yield 'false' => [false]; + } + + #[DataProvider('dataBase')] + public function testBase(bool $canContinue): void + { + $loop = new StubLoop($canContinue); + + $this->assertSame($canContinue, $loop->canContinue()); + } +} diff --git a/tests/Unit/Provider/PrototypeQueueProviderTest.php b/tests/Unit/Provider/PrototypeQueueProviderTest.php new file mode 100644 index 00000000..9c911fe9 --- /dev/null +++ b/tests/Unit/Provider/PrototypeQueueProviderTest.php @@ -0,0 +1,38 @@ +createMock(MiddlewareFactoryPushInterface::class) + ), + ), + ); + + $queue = $provider->get('test-channel'); + + $this->assertInstanceOf(Queue::class, $queue); + $this->assertSame('test-channel', $queue->getChannelName()); + $this->assertTrue($provider->has('test-channel')); + $this->assertTrue($provider->has('yet-another-channel')); + } +} diff --git a/tests/Unit/Worker/StubWorkerTest.php b/tests/Unit/Worker/StubWorkerTest.php new file mode 100644 index 00000000..9f8d379d --- /dev/null +++ b/tests/Unit/Worker/StubWorkerTest.php @@ -0,0 +1,27 @@ +process($sourceMessage, $this->createMock(QueueInterface::class)); + + $this->assertSame($sourceMessage, $message); + $this->assertSame('test', $message->getHandlerName()); + $this->assertSame(42, $message->getData()); + $this->assertSame([], $message->getMetadata()); + } +} From 48ad3af804da8a5cc41b8be0334736a984d430ae Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Tue, 5 Nov 2024 16:44:36 +0300 Subject: [PATCH 10/33] test `FactoryQueueProvider` --- src/Adapter/StubAdapter.php | 34 ++++++++ src/Provider/FactoryQueueProvider.php | 17 ++-- src/StubQueue.php | 56 +++++++++++++ tests/Unit/Adapter/StubAdapterTest.php | 24 ++++++ .../Provider/FactoryQueueProviderTest.php | 83 +++++++++++++++++++ .../Provider/PrototypeQueueProviderTest.php | 18 +--- tests/Unit/StubQueueTest.php | 44 ++++++++++ 7 files changed, 251 insertions(+), 25 deletions(-) create mode 100644 src/Adapter/StubAdapter.php create mode 100644 src/StubQueue.php create mode 100644 tests/Unit/Adapter/StubAdapterTest.php create mode 100644 tests/Unit/Provider/FactoryQueueProviderTest.php create mode 100644 tests/Unit/StubQueueTest.php diff --git a/src/Adapter/StubAdapter.php b/src/Adapter/StubAdapter.php new file mode 100644 index 00000000..e5c83cb3 --- /dev/null +++ b/src/Adapter/StubAdapter.php @@ -0,0 +1,34 @@ +factory = new StrictFactory($definitions, $container, $validate); + try { + $this->factory = new StrictFactory($definitions, $container, $validate); + } catch (InvalidConfigException $exception) { + throw new InvalidQueueConfigException($exception->getMessage(), previous: $exception); + } } public function get(string $channel): QueueInterface @@ -45,9 +49,6 @@ public function has(string $channel): bool return $this->factory->has($channel); } - /** - * @throws InvalidQueueConfigException - */ private function getOrTryCreate(string $channel): QueueInterface|null { if (array_key_exists($channel, $this->queues)) { @@ -55,11 +56,7 @@ private function getOrTryCreate(string $channel): QueueInterface|null } if ($this->factory->has($channel)) { - try { - $this->queues[$channel] = $this->factory->create($channel); - } catch (InvalidConfigException $exception) { - throw new InvalidQueueConfigException($exception->getMessage(), previous: $exception); - } + $this->queues[$channel] = $this->factory->create($channel); } else { $this->queues[$channel] = null; } diff --git a/src/StubQueue.php b/src/StubQueue.php new file mode 100644 index 00000000..5827b3ad --- /dev/null +++ b/src/StubQueue.php @@ -0,0 +1,56 @@ +channelName; + } + + public function withChannelName(string $channel): QueueInterface + { + $new = clone $this; + $new->channelName = $channel; + return $new; + } +} diff --git a/tests/Unit/Adapter/StubAdapterTest.php b/tests/Unit/Adapter/StubAdapterTest.php new file mode 100644 index 00000000..3903ba84 --- /dev/null +++ b/tests/Unit/Adapter/StubAdapterTest.php @@ -0,0 +1,24 @@ +assertSame($message, $adapter->push($message)); + $this->assertTrue($adapter->status('test')->isDone()); + $this->assertNotSame($adapter, $adapter->withChannel('test')); + $adapter->runExisting(static fn() => null); + $adapter->subscribe(static fn() => null); + } +} diff --git a/tests/Unit/Provider/FactoryQueueProviderTest.php b/tests/Unit/Provider/FactoryQueueProviderTest.php new file mode 100644 index 00000000..75d4fed0 --- /dev/null +++ b/tests/Unit/Provider/FactoryQueueProviderTest.php @@ -0,0 +1,83 @@ + [ + 'class' => StubQueue::class, + '__construct()' => [ + 'channelName' => 'channel1', + ], + ], + ], + ); + + $queue = $provider->get('channel1'); + + $this->assertInstanceOf(StubQueue::class, $queue); + $this->assertSame('channel1', $queue->getChannelName()); + $this->assertTrue($provider->has('channel1')); + $this->assertFalse($provider->has('not-exist-channel')); + } + + public function testGetTwice(): void + { + $provider = new FactoryQueueProvider( + [ + 'channel1' => [ + 'class' => StubQueue::class, + '__construct()' => [ + 'channelName' => 'channel1', + ], + ], + ], + ); + + $queue1 = $provider->get('channel1'); + $queue2 = $provider->get('channel1'); + + $this->assertSame($queue1, $queue2); + } + + public function testGetNotExistChannel() + { + $provider = new FactoryQueueProvider( + [ + 'channel1' => StubQueue::class, + ], + ); + + $this->expectException(ChannelNotFoundException::class); + $this->expectExceptionMessage('Channel "not-exist-channel" not found.'); + $provider->get('not-exist-channel'); + } + + public function testInvalidQueueConfig(): void + { + $definitions = [ + 'channel1' => [ + 'class' => StubQueue::class, + '__construct()' => 'hello', + ], + ]; + + $this->expectException(InvalidQueueConfigException::class); + $this->expectExceptionMessage( + 'Invalid definition: incorrect constructor arguments. Expected array, got string.' + ); + new FactoryQueueProvider($definitions); + } +} diff --git a/tests/Unit/Provider/PrototypeQueueProviderTest.php b/tests/Unit/Provider/PrototypeQueueProviderTest.php index 9c911fe9..06fc5e18 100644 --- a/tests/Unit/Provider/PrototypeQueueProviderTest.php +++ b/tests/Unit/Provider/PrototypeQueueProviderTest.php @@ -5,32 +5,20 @@ namespace Yiisoft\Queue\Tests\Unit\Provider; use PHPUnit\Framework\TestCase; -use Psr\Log\NullLogger; -use Yiisoft\Queue\Cli\StubLoop; -use Yiisoft\Queue\Middleware\Push\MiddlewareFactoryPushInterface; -use Yiisoft\Queue\Middleware\Push\PushMiddlewareDispatcher; use Yiisoft\Queue\Provider\PrototypeQueueProvider; -use Yiisoft\Queue\Queue; -use Yiisoft\Queue\Worker\StubWorker; +use Yiisoft\Queue\StubQueue; final class PrototypeQueueProviderTest extends TestCase { public function testBase(): void { $provider = new PrototypeQueueProvider( - new Queue( - new StubWorker(), - new StubLoop(), - new NullLogger(), - new PushMiddlewareDispatcher( - $this->createMock(MiddlewareFactoryPushInterface::class) - ), - ), + new StubQueue(), ); $queue = $provider->get('test-channel'); - $this->assertInstanceOf(Queue::class, $queue); + $this->assertInstanceOf(StubQueue::class, $queue); $this->assertSame('test-channel', $queue->getChannelName()); $this->assertTrue($provider->has('test-channel')); $this->assertTrue($provider->has('yet-another-channel')); diff --git a/tests/Unit/StubQueueTest.php b/tests/Unit/StubQueueTest.php new file mode 100644 index 00000000..a25a36fb --- /dev/null +++ b/tests/Unit/StubQueueTest.php @@ -0,0 +1,44 @@ +assertSame($message, $queue->push($message)); + $this->assertSame(0, $queue->run()); + $this->assertTrue($queue->status('test')->isDone()); + $this->assertSame(Queue::DEFAULT_CHANNEL_NAME, $queue->getChannelName()); + $queue->listen(); + } + + public function testWithAdapter(): void + { + $queue = new StubQueue(); + + $this->assertNotSame($queue, $queue->withAdapter(new StubAdapter())); + } + + public function testWithChannelName(): void + { + $sourceQueue = new StubQueue(); + + $queue = $sourceQueue->withChannelName('test'); + + $this->assertNotSame($queue, $sourceQueue); + $this->assertSame(Queue::DEFAULT_CHANNEL_NAME, $sourceQueue->getChannelName()); + $this->assertSame('test', $queue->getChannelName()); + } +} From 0fb0d45dbe86802bd7d99d45133213ef21ad41db Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Tue, 5 Nov 2024 16:52:18 +0300 Subject: [PATCH 11/33] test `CompositeQueueProvider` --- .../Provider/CompositeQueueProviderTest.php | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 tests/Unit/Provider/CompositeQueueProviderTest.php diff --git a/tests/Unit/Provider/CompositeQueueProviderTest.php b/tests/Unit/Provider/CompositeQueueProviderTest.php new file mode 100644 index 00000000..aaac4a94 --- /dev/null +++ b/tests/Unit/Provider/CompositeQueueProviderTest.php @@ -0,0 +1,46 @@ + new StubQueue('channel1'), + ]), + new FactoryQueueProvider([ + 'channel2' => new StubQueue('channel2'), + ]), + ); + + $this->assertTrue($provider->has('channel1')); + $this->assertTrue($provider->has('channel2')); + $this->assertFalse($provider->has('channel3')); + + $this->assertSame('channel1', $provider->get('channel1')->getChannelName()); + $this->assertSame('channel2', $provider->get('channel2')->getChannelName()); + } + + public function testNotFound(): void + { + $provider = new CompositeQueueProvider( + new FactoryQueueProvider([ + 'channel1' => new StubQueue(), + ]), + ); + + $this->expectException(ChannelNotFoundException::class); + $this->expectExceptionMessage('Channel "not-exist" not found.'); + $provider->get('not-exist'); + } +} From bfd3445e3c60967f921a5516f0c68c45b24b547a Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Tue, 5 Nov 2024 13:52:41 +0000 Subject: [PATCH 12/33] Apply fixes from StyleCI --- src/Queue.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Queue.php b/src/Queue.php index 151ccd41..be600317 100644 --- a/src/Queue.php +++ b/src/Queue.php @@ -35,7 +35,7 @@ public function __construct( private LoggerInterface $logger, private PushMiddlewareDispatcher $pushMiddlewareDispatcher, private ?AdapterInterface $adapter = null, - private string $channelName = Queue::DEFAULT_CHANNEL_NAME, + private string $channelName = self::DEFAULT_CHANNEL_NAME, MiddlewarePushInterface|callable|array|string ...$middlewareDefinitions ) { $this->middlewareDefinitions = $middlewareDefinitions; From 97689daa0e388f12ee5112a1897240fb1d77128f Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Wed, 6 Nov 2024 10:10:40 +0300 Subject: [PATCH 13/33] Improve `QueueFactoryQueueProvider` --- config/di.php | 4 +- ...ider.php => QueueFactoryQueueProvider.php} | 22 +++++++-- .../Provider/CompositeQueueProviderTest.php | 8 ++-- ....php => QueueFactoryQueueProviderTest.php} | 45 +++++++++++-------- 4 files changed, 52 insertions(+), 27 deletions(-) rename src/Provider/{FactoryQueueProvider.php => QueueFactoryQueueProvider.php} (66%) rename tests/Unit/Provider/{FactoryQueueProviderTest.php => QueueFactoryQueueProviderTest.php} (62%) diff --git a/config/di.php b/config/di.php index 28d5bc26..6980d616 100644 --- a/config/di.php +++ b/config/di.php @@ -19,7 +19,7 @@ use Yiisoft\Queue\Middleware\Push\MiddlewareFactoryPush; use Yiisoft\Queue\Middleware\Push\MiddlewareFactoryPushInterface; use Yiisoft\Queue\Middleware\Push\PushMiddlewareDispatcher; -use Yiisoft\Queue\Provider\FactoryQueueProvider; +use Yiisoft\Queue\Provider\QueueFactoryQueueProvider; use Yiisoft\Queue\Provider\QueueProviderInterface; use Yiisoft\Queue\Queue; use Yiisoft\Queue\QueueInterface; @@ -30,7 +30,7 @@ return [ QueueProviderInterface::class => [ - 'class' => FactoryQueueProvider::class, + 'class' => QueueFactoryQueueProvider::class, '__construct()' => [ 'definitions' => $params['yiisoft/queue']['channel-definitions'], ], diff --git a/src/Provider/FactoryQueueProvider.php b/src/Provider/QueueFactoryQueueProvider.php similarity index 66% rename from src/Provider/FactoryQueueProvider.php rename to src/Provider/QueueFactoryQueueProvider.php index 67efa649..bbb5ff11 100644 --- a/src/Provider/FactoryQueueProvider.php +++ b/src/Provider/QueueFactoryQueueProvider.php @@ -10,8 +10,9 @@ use Yiisoft\Queue\QueueInterface; use function array_key_exists; +use function sprintf; -final class FactoryQueueProvider implements QueueProviderInterface +final class QueueFactoryQueueProvider implements QueueProviderInterface { /** * @psalm-var array @@ -21,10 +22,11 @@ final class FactoryQueueProvider implements QueueProviderInterface private readonly StrictFactory $factory; /** + * @psalm-param array $definitions * @throws InvalidQueueConfigException */ public function __construct( - array $definitions = [], + array $definitions, ?ContainerInterface $container = null, bool $validate = true, ) { @@ -49,6 +51,9 @@ public function has(string $channel): bool return $this->factory->has($channel); } + /** + * @throws InvalidQueueConfigException + */ private function getOrTryCreate(string $channel): QueueInterface|null { if (array_key_exists($channel, $this->queues)) { @@ -56,7 +61,18 @@ private function getOrTryCreate(string $channel): QueueInterface|null } if ($this->factory->has($channel)) { - $this->queues[$channel] = $this->factory->create($channel); + $queue = $this->factory->create($channel); + if (!$queue instanceof QueueInterface) { + throw new InvalidQueueConfigException( + sprintf( + 'Queue must implement "%s". For channel "%s" got "%s" instead.', + QueueInterface::class, + $channel, + get_debug_type($queue), + ), + ); + } + $this->queues[$channel] = $queue->withChannelName($channel); } else { $this->queues[$channel] = null; } diff --git a/tests/Unit/Provider/CompositeQueueProviderTest.php b/tests/Unit/Provider/CompositeQueueProviderTest.php index aaac4a94..4804870a 100644 --- a/tests/Unit/Provider/CompositeQueueProviderTest.php +++ b/tests/Unit/Provider/CompositeQueueProviderTest.php @@ -6,7 +6,7 @@ use Yiisoft\Queue\Provider\ChannelNotFoundException; use Yiisoft\Queue\Provider\CompositeQueueProvider; -use Yiisoft\Queue\Provider\FactoryQueueProvider; +use Yiisoft\Queue\Provider\QueueFactoryQueueProvider; use Yiisoft\Queue\StubQueue; use Yiisoft\Queue\Tests\TestCase; @@ -15,10 +15,10 @@ final class CompositeQueueProviderTest extends TestCase public function testBase(): void { $provider = new CompositeQueueProvider( - new FactoryQueueProvider([ + new QueueFactoryQueueProvider([ 'channel1' => new StubQueue('channel1'), ]), - new FactoryQueueProvider([ + new QueueFactoryQueueProvider([ 'channel2' => new StubQueue('channel2'), ]), ); @@ -34,7 +34,7 @@ public function testBase(): void public function testNotFound(): void { $provider = new CompositeQueueProvider( - new FactoryQueueProvider([ + new QueueFactoryQueueProvider([ 'channel1' => new StubQueue(), ]), ); diff --git a/tests/Unit/Provider/FactoryQueueProviderTest.php b/tests/Unit/Provider/QueueFactoryQueueProviderTest.php similarity index 62% rename from tests/Unit/Provider/FactoryQueueProviderTest.php rename to tests/Unit/Provider/QueueFactoryQueueProviderTest.php index 75d4fed0..0f6ea56a 100644 --- a/tests/Unit/Provider/FactoryQueueProviderTest.php +++ b/tests/Unit/Provider/QueueFactoryQueueProviderTest.php @@ -5,23 +5,20 @@ namespace Yiisoft\Queue\Tests\Unit\Provider; use PHPUnit\Framework\TestCase; +use Yiisoft\Queue\Cli\StubLoop; use Yiisoft\Queue\Provider\ChannelNotFoundException; -use Yiisoft\Queue\Provider\FactoryQueueProvider; +use Yiisoft\Queue\Provider\QueueFactoryQueueProvider; use Yiisoft\Queue\Provider\InvalidQueueConfigException; +use Yiisoft\Queue\QueueInterface; use Yiisoft\Queue\StubQueue; -final class FactoryQueueProviderTest extends TestCase +final class QueueFactoryQueueProviderTest extends TestCase { public function testBase(): void { - $provider = new FactoryQueueProvider( + $provider = new QueueFactoryQueueProvider( [ - 'channel1' => [ - 'class' => StubQueue::class, - '__construct()' => [ - 'channelName' => 'channel1', - ], - ], + 'channel1' => StubQueue::class, ], ); @@ -35,14 +32,9 @@ public function testBase(): void public function testGetTwice(): void { - $provider = new FactoryQueueProvider( + $provider = new QueueFactoryQueueProvider( [ - 'channel1' => [ - 'class' => StubQueue::class, - '__construct()' => [ - 'channelName' => 'channel1', - ], - ], + 'channel1' => StubQueue::class, ], ); @@ -54,7 +46,7 @@ public function testGetTwice(): void public function testGetNotExistChannel() { - $provider = new FactoryQueueProvider( + $provider = new QueueFactoryQueueProvider( [ 'channel1' => StubQueue::class, ], @@ -78,6 +70,23 @@ public function testInvalidQueueConfig(): void $this->expectExceptionMessage( 'Invalid definition: incorrect constructor arguments. Expected array, got string.' ); - new FactoryQueueProvider($definitions); + new QueueFactoryQueueProvider($definitions); + } + + public function testInvalidQueueConfigOnGet(): void + { + $provider = new QueueFactoryQueueProvider([ + 'channel1' => StubLoop::class, + ]); + + $this->expectException(InvalidQueueConfigException::class); + $this->expectExceptionMessage( + sprintf( + 'Queue must implement "%s". For channel "channel1" got "%s" instead.', + QueueInterface::class, + StubLoop::class, + ) + ); + $provider->get('channel1'); } } From 9bbe35806fa0a8fed703d2669856b00bb36c5062 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Wed, 6 Nov 2024 10:30:50 +0300 Subject: [PATCH 14/33] Add `AdapterFactoryQueueProvider` --- src/Provider/AdapterFactoryQueueProvider.php | 84 ++++++++++++++ src/StubQueue.php | 13 ++- .../AdapterFactoryQueueProviderTest.php | 103 ++++++++++++++++++ .../QueueFactoryQueueProviderTest.php | 4 +- 4 files changed, 202 insertions(+), 2 deletions(-) create mode 100644 src/Provider/AdapterFactoryQueueProvider.php create mode 100644 tests/Unit/Provider/AdapterFactoryQueueProviderTest.php diff --git a/src/Provider/AdapterFactoryQueueProvider.php b/src/Provider/AdapterFactoryQueueProvider.php new file mode 100644 index 00000000..3346c667 --- /dev/null +++ b/src/Provider/AdapterFactoryQueueProvider.php @@ -0,0 +1,84 @@ + + */ + private array $queues = []; + + private readonly StrictFactory $factory; + + /** + * @psalm-param array $definitions + * @throws InvalidQueueConfigException + */ + public function __construct( + private readonly QueueInterface $baseQueue, + array $definitions, + ?ContainerInterface $container = null, + bool $validate = true, + ) { + try { + $this->factory = new StrictFactory($definitions, $container, $validate); + } catch (InvalidConfigException $exception) { + throw new InvalidQueueConfigException($exception->getMessage(), previous: $exception); + } + } + + public function get(string $channel): QueueInterface + { + $queue = $this->getOrTryCreate($channel); + if ($queue === null) { + throw new ChannelNotFoundException($channel); + } + return $queue; + } + + public function has(string $channel): bool + { + return $this->factory->has($channel); + } + + /** + * @throws InvalidQueueConfigException + */ + private function getOrTryCreate(string $channel): QueueInterface|null + { + if (array_key_exists($channel, $this->queues)) { + return $this->queues[$channel]; + } + + if ($this->factory->has($channel)) { + $adapter = $this->factory->create($channel); + if (!$adapter instanceof AdapterInterface) { + throw new InvalidQueueConfigException( + sprintf( + 'Adapter must implement "%s". For channel "%s" got "%s" instead.', + AdapterInterface::class, + $channel, + get_debug_type($adapter), + ), + ); + } + $this->queues[$channel] = $this->baseQueue->withAdapter($adapter)->withChannelName($channel); + } else { + $this->queues[$channel] = null; + } + + return $this->queues[$channel]; + } +} diff --git a/src/StubQueue.php b/src/StubQueue.php index 5827b3ad..c8dc1348 100644 --- a/src/StubQueue.php +++ b/src/StubQueue.php @@ -13,6 +13,7 @@ final class StubQueue implements QueueInterface { public function __construct( private string $channelName = Queue::DEFAULT_CHANNEL_NAME, + private ?AdapterInterface $adapter = null, ) { } @@ -37,9 +38,16 @@ public function status(int|string $id): JobStatus return JobStatus::done(); } + public function getAdapter(): ?AdapterInterface + { + return $this->adapter; + } + public function withAdapter(AdapterInterface $adapter): QueueInterface { - return clone $this; + $new = clone $this; + $new->adapter = $adapter; + return $new; } public function getChannelName(): string @@ -51,6 +59,9 @@ public function withChannelName(string $channel): QueueInterface { $new = clone $this; $new->channelName = $channel; + if ($new->adapter !== null) { + $new->adapter = $new->adapter->withChannel($channel); + } return $new; } } diff --git a/tests/Unit/Provider/AdapterFactoryQueueProviderTest.php b/tests/Unit/Provider/AdapterFactoryQueueProviderTest.php new file mode 100644 index 00000000..410d6446 --- /dev/null +++ b/tests/Unit/Provider/AdapterFactoryQueueProviderTest.php @@ -0,0 +1,103 @@ + StubAdapter::class, + ], + ); + + $queue = $provider->get('channel1'); + + $this->assertInstanceOf(StubQueue::class, $queue); + $this->assertSame('channel1', $queue->getChannelName()); + $this->assertInstanceOf(StubAdapter::class, $queue->getAdapter()); + $this->assertTrue($provider->has('channel1')); + $this->assertFalse($provider->has('not-exist-channel')); + } + + public function testGetTwice(): void + { + $provider = new AdapterFactoryQueueProvider( + new StubQueue(), + [ + 'channel1' => StubAdapter::class, + ], + ); + + $queue1 = $provider->get('channel1'); + $queue2 = $provider->get('channel1'); + + $this->assertSame($queue1, $queue2); + } + + public function testGetNotExistChannel(): void + { + $provider = new AdapterFactoryQueueProvider( + new StubQueue(), + [ + 'channel1' => StubAdapter::class, + ], + ); + + $this->expectException(ChannelNotFoundException::class); + $this->expectExceptionMessage('Channel "not-exist-channel" not found.'); + $provider->get('not-exist-channel'); + } + + public function testInvalidQueueConfig(): void + { + $baseQueue = new StubQueue(); + $definitions = [ + 'channel1' => [ + 'class' => StubAdapter::class, + '__construct()' => 'hello', + ], + ]; + + $this->expectException(InvalidQueueConfigException::class); + $this->expectExceptionMessage( + 'Invalid definition: incorrect constructor arguments. Expected array, got string.' + ); + new AdapterFactoryQueueProvider($baseQueue, $definitions); + } + + public function testInvalidQueueConfigOnGet(): void + { + $provider = new AdapterFactoryQueueProvider( + new StubQueue(), + [ + 'channel1' => StubLoop::class, + ] + ); + + $this->expectException(InvalidQueueConfigException::class); + $this->expectExceptionMessage( + sprintf( + 'Adapter must implement "%s". For channel "channel1" got "%s" instead.', + AdapterInterface::class, + StubLoop::class, + ) + ); + $provider->get('channel1'); + } +} diff --git a/tests/Unit/Provider/QueueFactoryQueueProviderTest.php b/tests/Unit/Provider/QueueFactoryQueueProviderTest.php index 0f6ea56a..629d04fc 100644 --- a/tests/Unit/Provider/QueueFactoryQueueProviderTest.php +++ b/tests/Unit/Provider/QueueFactoryQueueProviderTest.php @@ -12,6 +12,8 @@ use Yiisoft\Queue\QueueInterface; use Yiisoft\Queue\StubQueue; +use function sprintf; + final class QueueFactoryQueueProviderTest extends TestCase { public function testBase(): void @@ -44,7 +46,7 @@ public function testGetTwice(): void $this->assertSame($queue1, $queue2); } - public function testGetNotExistChannel() + public function testGetNotExistChannel(): void { $provider = new QueueFactoryQueueProvider( [ From 4b25f4b4c553f0074ce108511f77ae4238067663 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Wed, 6 Nov 2024 10:37:46 +0300 Subject: [PATCH 15/33] improve tests --- tests/Unit/StubQueueTest.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/Unit/StubQueueTest.php b/tests/Unit/StubQueueTest.php index a25a36fb..12e49080 100644 --- a/tests/Unit/StubQueueTest.php +++ b/tests/Unit/StubQueueTest.php @@ -21,14 +21,18 @@ public function testBase(): void $this->assertSame(0, $queue->run()); $this->assertTrue($queue->status('test')->isDone()); $this->assertSame(Queue::DEFAULT_CHANNEL_NAME, $queue->getChannelName()); + $this->assertNull($queue->getAdapter()); $queue->listen(); } public function testWithAdapter(): void { - $queue = new StubQueue(); + $sourceQueue = new StubQueue(); - $this->assertNotSame($queue, $queue->withAdapter(new StubAdapter())); + $queue = $sourceQueue->withAdapter(new StubAdapter()); + + $this->assertNotSame($queue, $sourceQueue); + $this->assertInstanceOf(StubAdapter::class, $queue->getAdapter()); } public function testWithChannelName(): void From 8f593d91d4681e369c8769351a1f13cf91399fcf Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Thu, 7 Nov 2024 10:19:01 +0300 Subject: [PATCH 16/33] Rename "channel-definitions" to "channels" --- config/di.php | 6 +++--- config/params.php | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/config/di.php b/config/di.php index 6980d616..d4fec057 100644 --- a/config/di.php +++ b/config/di.php @@ -32,7 +32,7 @@ QueueProviderInterface::class => [ 'class' => QueueFactoryQueueProvider::class, '__construct()' => [ - 'definitions' => $params['yiisoft/queue']['channel-definitions'], + 'definitions' => $params['yiisoft/queue']['channels'], ], ], QueueWorker::class => [ @@ -61,12 +61,12 @@ MessageSerializerInterface::class => JsonMessageSerializer::class, RunCommand::class => [ '__construct()' => [ - 'channels' => array_keys($params['yiisoft/queue']['channel-definitions']), + 'channels' => array_keys($params['yiisoft/queue']['channels']), ], ], ListenAllCommand::class => [ '__construct()' => [ - 'channels' => array_keys($params['yiisoft/queue']['channel-definitions']), + 'channels' => array_keys($params['yiisoft/queue']['channels']), ], ], ]; diff --git a/config/params.php b/config/params.php index c1994af7..4ac7ccc7 100644 --- a/config/params.php +++ b/config/params.php @@ -21,7 +21,7 @@ ], 'yiisoft/queue' => [ 'handlers' => [], - 'channel-definitions' => [], + 'channels' => [], 'middlewares-push' => [], 'middlewares-consume' => [], 'middlewares-fail' => [], From 394c50f5da6718f6f4c8222e41e238b208519002 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Thu, 7 Nov 2024 10:24:19 +0300 Subject: [PATCH 17/33] stubs phpdoc --- src/Adapter/StubAdapter.php | 3 +++ src/Cli/StubLoop.php | 3 +++ src/StubQueue.php | 3 +++ src/Worker/StubWorker.php | 3 +++ 4 files changed, 12 insertions(+) diff --git a/src/Adapter/StubAdapter.php b/src/Adapter/StubAdapter.php index e5c83cb3..894a5951 100644 --- a/src/Adapter/StubAdapter.php +++ b/src/Adapter/StubAdapter.php @@ -7,6 +7,9 @@ use Yiisoft\Queue\Enum\JobStatus; use Yiisoft\Queue\Message\MessageInterface; +/** + * Stub adapter that does nothing. Job status is always "done". + */ final class StubAdapter implements AdapterInterface { public function runExisting(callable $handlerCallback): void diff --git a/src/Cli/StubLoop.php b/src/Cli/StubLoop.php index b38276e2..a8747365 100644 --- a/src/Cli/StubLoop.php +++ b/src/Cli/StubLoop.php @@ -4,6 +4,9 @@ namespace Yiisoft\Queue\Cli; +/** + * Stub loop. + */ final class StubLoop implements LoopInterface { public function __construct( diff --git a/src/StubQueue.php b/src/StubQueue.php index c8dc1348..8f06e2da 100644 --- a/src/StubQueue.php +++ b/src/StubQueue.php @@ -9,6 +9,9 @@ use Yiisoft\Queue\Message\MessageInterface; use Yiisoft\Queue\Middleware\Push\MiddlewarePushInterface; +/** + * Stub queue that does nothing. Job status is always "done". + */ final class StubQueue implements QueueInterface { public function __construct( diff --git a/src/Worker/StubWorker.php b/src/Worker/StubWorker.php index 398a7aae..2080f893 100644 --- a/src/Worker/StubWorker.php +++ b/src/Worker/StubWorker.php @@ -7,6 +7,9 @@ use Yiisoft\Queue\Message\MessageInterface; use Yiisoft\Queue\QueueInterface; +/** + * Stub worker that does nothing. + */ final class StubWorker implements WorkerInterface { public function process(MessageInterface $message, QueueInterface $queue): MessageInterface From 7a8601c67836466e3ce3799c1ace849f4a490c80 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Thu, 7 Nov 2024 10:37:50 +0300 Subject: [PATCH 18/33] phpdoc --- src/Provider/AdapterFactoryQueueProvider.php | 11 ++++++++++ src/Provider/ChannelNotFoundException.php | 3 +++ src/Provider/CompositeQueueProvider.php | 6 ++++++ src/Provider/InvalidQueueConfigException.php | 3 +++ src/Provider/PrototypeQueueProvider.php | 7 +++++++ src/Provider/QueueFactoryQueueProvider.php | 10 +++++++++ src/Provider/QueueProviderException.php | 3 +++ src/Provider/QueueProviderInterface.php | 22 +++++++++++++++++--- 8 files changed, 62 insertions(+), 3 deletions(-) diff --git a/src/Provider/AdapterFactoryQueueProvider.php b/src/Provider/AdapterFactoryQueueProvider.php index 3346c667..feaed434 100644 --- a/src/Provider/AdapterFactoryQueueProvider.php +++ b/src/Provider/AdapterFactoryQueueProvider.php @@ -13,6 +13,12 @@ use function array_key_exists; use function sprintf; +/** + * Queue provider based on adapter definitions. + * + * @see https://github.com/yiisoft/definitions/ + * @see https://github.com/yiisoft/factory/ + */ final class AdapterFactoryQueueProvider implements QueueProviderInterface { /** @@ -23,6 +29,11 @@ final class AdapterFactoryQueueProvider implements QueueProviderInterface private readonly StrictFactory $factory; /** + * @param QueueInterface $baseQueue Base queue to use for creating queues. + * @param array $definitions Definitions to create adapters with indexed by channel names. + * @param ContainerInterface|null $container Container to use for resolving dependencies. + * @param bool $validate If definitions should be validated when set. + * * @psalm-param array $definitions * @throws InvalidQueueConfigException */ diff --git a/src/Provider/ChannelNotFoundException.php b/src/Provider/ChannelNotFoundException.php index fa2a6695..2538cda7 100644 --- a/src/Provider/ChannelNotFoundException.php +++ b/src/Provider/ChannelNotFoundException.php @@ -9,6 +9,9 @@ use function sprintf; +/** + * Thrown when channel is not found. + */ final class ChannelNotFoundException extends LogicException implements QueueProviderException { public function __construct(string $channel, int $code = 0, ?Throwable $previous = null) diff --git a/src/Provider/CompositeQueueProvider.php b/src/Provider/CompositeQueueProvider.php index 57152b94..cd7f36ca 100644 --- a/src/Provider/CompositeQueueProvider.php +++ b/src/Provider/CompositeQueueProvider.php @@ -6,6 +6,9 @@ use Yiisoft\Queue\QueueInterface; +/** + * Composite queue provider. + */ final class CompositeQueueProvider implements QueueProviderInterface { /** @@ -13,6 +16,9 @@ final class CompositeQueueProvider implements QueueProviderInterface */ private readonly array $providers; + /** + * @param QueueProviderInterface ...$providers Queue providers to use. + */ public function __construct( QueueProviderInterface ...$providers ) { diff --git a/src/Provider/InvalidQueueConfigException.php b/src/Provider/InvalidQueueConfigException.php index e1c24a0c..136fe746 100644 --- a/src/Provider/InvalidQueueConfigException.php +++ b/src/Provider/InvalidQueueConfigException.php @@ -6,6 +6,9 @@ use LogicException; +/** + * Thrown when queue configuration is invalid. + */ final class InvalidQueueConfigException extends LogicException implements QueueProviderException { } diff --git a/src/Provider/PrototypeQueueProvider.php b/src/Provider/PrototypeQueueProvider.php index bcb443d8..53b0d6e2 100644 --- a/src/Provider/PrototypeQueueProvider.php +++ b/src/Provider/PrototypeQueueProvider.php @@ -6,8 +6,15 @@ use Yiisoft\Queue\QueueInterface; +/** + * Queue provider that only changes the channel name of the base queue. + * It can be useful when your queues used the same adapter. + */ final class PrototypeQueueProvider implements QueueProviderInterface { + /** + * @param QueueInterface $baseQueue Base queue to use for creating queues. + */ public function __construct( private readonly QueueInterface $baseQueue, ) { diff --git a/src/Provider/QueueFactoryQueueProvider.php b/src/Provider/QueueFactoryQueueProvider.php index bbb5ff11..3b57375b 100644 --- a/src/Provider/QueueFactoryQueueProvider.php +++ b/src/Provider/QueueFactoryQueueProvider.php @@ -12,6 +12,12 @@ use function array_key_exists; use function sprintf; +/** + * Queue provider based on queue definitions. + * + * @see https://github.com/yiisoft/definitions/ + * @see https://github.com/yiisoft/factory/ + */ final class QueueFactoryQueueProvider implements QueueProviderInterface { /** @@ -22,6 +28,10 @@ final class QueueFactoryQueueProvider implements QueueProviderInterface private readonly StrictFactory $factory; /** + * @param array $definitions Definitions to create queues with indexed by channel names. + * @param ContainerInterface|null $container Container to use for resolving dependencies. + * @param bool $validate If definitions should be validated when set. + * * @psalm-param array $definitions * @throws InvalidQueueConfigException */ diff --git a/src/Provider/QueueProviderException.php b/src/Provider/QueueProviderException.php index 62a1a11c..17fa3bc4 100644 --- a/src/Provider/QueueProviderException.php +++ b/src/Provider/QueueProviderException.php @@ -6,6 +6,9 @@ use Throwable; +/** + * Base interface representing a generic exception in a queue provider. + */ interface QueueProviderException extends Throwable { } diff --git a/src/Provider/QueueProviderInterface.php b/src/Provider/QueueProviderInterface.php index 7c67c27e..a02cd42b 100644 --- a/src/Provider/QueueProviderInterface.php +++ b/src/Provider/QueueProviderInterface.php @@ -6,14 +6,30 @@ use Yiisoft\Queue\QueueInterface; +/** + * `QueueProviderInterface` provides a way to get a queue instance by channel name. + */ interface QueueProviderInterface { /** - * @throws InvalidQueueConfigException - * @throws ChannelNotFoundException - * @throws QueueProviderException + * Find a queue by channel name and returns it. + * + * @param string $channel Channel name. + * + * @return QueueInterface Queue instance. + * + * @throws InvalidQueueConfigException If the queue configuration is invalid. + * @throws ChannelNotFoundException If the channel is not found. + * @throws QueueProviderException If the queue provider fails to provide a queue. */ public function get(string $channel): QueueInterface; + /** + * Check if a queue with the specified channel name exists. + * + * @param string $channel Channel name. + * + * @return bool Whether the queue exists. + */ public function has(string $channel): bool; } From f90b3df8f40616aa6939c883b29a978ae5d4a268 Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Thu, 7 Nov 2024 07:38:18 +0000 Subject: [PATCH 19/33] Apply fixes from StyleCI --- src/Provider/QueueProviderInterface.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Provider/QueueProviderInterface.php b/src/Provider/QueueProviderInterface.php index a02cd42b..7d3501b7 100644 --- a/src/Provider/QueueProviderInterface.php +++ b/src/Provider/QueueProviderInterface.php @@ -16,11 +16,10 @@ interface QueueProviderInterface * * @param string $channel Channel name. * - * @return QueueInterface Queue instance. - * * @throws InvalidQueueConfigException If the queue configuration is invalid. * @throws ChannelNotFoundException If the channel is not found. * @throws QueueProviderException If the queue provider fails to provide a queue. + * @return QueueInterface Queue instance. */ public function get(string $channel): QueueInterface; From cf9dd96973a87f8aa5b157b828c8c7c6e522162f Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Thu, 7 Nov 2024 10:49:57 +0300 Subject: [PATCH 20/33] readme --- README.md | 43 ++++++++++++++++++++++++++++--------------- config/di.php | 4 ++-- config/params.php | 6 +++++- 3 files changed, 35 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 25f94f74..9701a6d8 100644 --- a/README.md +++ b/README.md @@ -28,15 +28,15 @@ The package could be installed with [Composer](https://getcomposer.org): composer require yiisoft/queue ``` -## Ready for yiisoft/config +## Ready for Yii Config If you are using [yiisoft/config](https://github.com/yiisoft/config), you'll find out this package has some defaults in the [`common`](config/di.php) and [`params`](config/params.php) configurations saving your time. Things you should change to start working with the queue: - Optionally: define default `\Yiisoft\Queue\Adapter\AdapterInterface` implementation. -- And/or define channel-specific `AdapterInterface` implementations in the `channel-definitions` params key to be used - with the [queue factory](#different-queue-channels). +- And/or define channel-specific `AdapterInterface` implementations in the `channel` params key to be used + with the [queue provider](#different-queue-channels). - Define [message handlers](docs/guide/worker.md#handler-format) in the `handlers` params key to be used with the `QueueWorker`. - Resolve other `\Yiisoft\Queue\Queue` dependencies (psr-compliant event dispatcher). @@ -136,15 +136,24 @@ $status->isDone(); ## Different queue channels -Often we need to push to different queue channels with an only application. There is the `QueueFactory` class to make -different `Queue` objects creation for different channels. With this factory channel-specific `Queue` creation is as -simple as +Often we need to push to different queue channels with an only application. There is the `QueueProviderInterface` +interface that provides different `Queue` objects creation for different channels. With implementation of this interface +channel-specific `Queue` creation is as simple as ```php -$queue = $factory->get('channel-name'); +$queue = $provider->get('channel-name'); ``` -The main usage strategy is with explicit definition of channel-specific adapters. Definitions are passed in +Out of the box, there are four implementations of the `QueueProviderInterface`: + +- `AdapterFactoryQueueProvider` +- `QueueFactoryQueueProvider` +- `PrototypeQueueProvider` +- `CompositeQueueProvider` + +### `AdapterFactoryQueueProvider` + +Provider based on definition of channel-specific adapters. Definitions are passed in the `$definitions` constructor parameter of the factory, where keys are channel names and values are definitions for the [`Yiisoft\Factory\Factory`](https://github.com/yiisoft/factory). Below are some examples: @@ -163,19 +172,23 @@ use Yiisoft\Queue\Adapter\SynchronousAdapter; For more information about a definition formats available see the [factory](https://github.com/yiisoft/factory) documentation. -Another queue factory usage strategy is implicit adapter creation via `withChannel()` method call. To use this approach -you should pass some specific constructor parameters: +### `QueueFactoryQueueProvider` -- `true` to the `$enableRuntimeChannelDefinition` -- a default `AdapterInterface` implementation to the `$defaultAdapter`. +Provider is similar to `AdapterFactoryQueueProvider`, but it uses definitions of channel-specific queues. -In this case `$factory->get('channel-name')` call will be converted -to `$this->queue->withAdapter($this->defaultAdapter->withChannel($channel))`, when there is no explicit adapter definition -in the `$definitions`. +### `PrototypeQueueProvider` + +Queue provider that only changes the channel name of the base queue. It can be useful when your queues used the same +adapter. > Warning: This strategy is not recommended as it does not give you any protection against typos and mistakes > in channel names. +### `CompositeQueueProvider` + +This provider allows you to combine multiple providers into one. It will try to get a queue from each provider in the +order they are passed to the constructor. The first queue found will be returned. + ## Console execution The exact way of task execution depends on the adapter used. Most adapters can be run using diff --git a/config/di.php b/config/di.php index d4fec057..6e1867d5 100644 --- a/config/di.php +++ b/config/di.php @@ -19,7 +19,7 @@ use Yiisoft\Queue\Middleware\Push\MiddlewareFactoryPush; use Yiisoft\Queue\Middleware\Push\MiddlewareFactoryPushInterface; use Yiisoft\Queue\Middleware\Push\PushMiddlewareDispatcher; -use Yiisoft\Queue\Provider\QueueFactoryQueueProvider; +use Yiisoft\Queue\Provider\AdapterFactoryQueueProvider; use Yiisoft\Queue\Provider\QueueProviderInterface; use Yiisoft\Queue\Queue; use Yiisoft\Queue\QueueInterface; @@ -30,7 +30,7 @@ return [ QueueProviderInterface::class => [ - 'class' => QueueFactoryQueueProvider::class, + 'class' => AdapterFactoryQueueProvider::class, '__construct()' => [ 'definitions' => $params['yiisoft/queue']['channels'], ], diff --git a/config/params.php b/config/params.php index 4ac7ccc7..0d412dcf 100644 --- a/config/params.php +++ b/config/params.php @@ -2,6 +2,7 @@ declare(strict_types=1); +use Yiisoft\Queue\Adapter\AdapterInterface; use Yiisoft\Queue\Command\ListenAllCommand; use Yiisoft\Queue\Command\ListenCommand; use Yiisoft\Queue\Command\RunCommand; @@ -9,6 +10,7 @@ use Yiisoft\Queue\Debug\QueueProviderInterfaceProxy; use Yiisoft\Queue\Debug\QueueWorkerInterfaceProxy; use Yiisoft\Queue\Provider\QueueProviderInterface; +use Yiisoft\Queue\Queue; use Yiisoft\Queue\Worker\WorkerInterface; return [ @@ -21,7 +23,9 @@ ], 'yiisoft/queue' => [ 'handlers' => [], - 'channels' => [], + 'channels' => [ + Queue::DEFAULT_CHANNEL_NAME => AdapterInterface::class, + ], 'middlewares-push' => [], 'middlewares-consume' => [], 'middlewares-fail' => [], From 03b742d598b6436b11310c91b853dce997e7f301 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Mon, 11 Nov 2024 10:30:59 +0300 Subject: [PATCH 21/33] fix cs --- src/Command/ListenAllCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Command/ListenAllCommand.php b/src/Command/ListenAllCommand.php index 021c3c0d..34b4619e 100644 --- a/src/Command/ListenAllCommand.php +++ b/src/Command/ListenAllCommand.php @@ -48,7 +48,7 @@ public function configure(): void 'm', InputOption::VALUE_REQUIRED, 'Maximum number of messages to process in each channel before switching to another channel. ' . - 'Default is 0 (no limits).', + 'Default is 0 (no limits).', 0, ); From 5cd929ba85b5a69d98b911fd63a6c03f7f1ed3ae Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Mon, 11 Nov 2024 10:33:16 +0300 Subject: [PATCH 22/33] Update src/Command/ListenAllCommand.php Co-authored-by: Viktor Babanov --- src/Command/ListenAllCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Command/ListenAllCommand.php b/src/Command/ListenAllCommand.php index 34b4619e..8be6dead 100644 --- a/src/Command/ListenAllCommand.php +++ b/src/Command/ListenAllCommand.php @@ -23,7 +23,7 @@ final class ListenAllCommand extends Command public function __construct( private readonly QueueProviderInterface $queueProvider, private readonly LoopInterface $loop, - private readonly array $channels + private readonly array $channels, ) { parent::__construct(); } From 00ee57d0a8bff38fddb8a54b9c875078cd5a9bf0 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Mon, 11 Nov 2024 10:39:45 +0300 Subject: [PATCH 23/33] Move `DEFAULT_CHANNEL_NAME` to `QueueInterface` --- config/params.php | 3 ++- src/Adapter/SynchronousAdapter.php | 2 +- src/Command/ListenCommand.php | 3 ++- src/Queue.php | 5 +---- src/QueueInterface.php | 3 +++ src/StubQueue.php | 2 +- tests/Unit/StubQueueTest.php | 5 +++-- tests/Unit/SynchronousAdapterTest.php | 3 ++- 8 files changed, 15 insertions(+), 11 deletions(-) diff --git a/config/params.php b/config/params.php index 0d412dcf..0a8d5656 100644 --- a/config/params.php +++ b/config/params.php @@ -11,6 +11,7 @@ use Yiisoft\Queue\Debug\QueueWorkerInterfaceProxy; use Yiisoft\Queue\Provider\QueueProviderInterface; use Yiisoft\Queue\Queue; +use Yiisoft\Queue\QueueInterface; use Yiisoft\Queue\Worker\WorkerInterface; return [ @@ -24,7 +25,7 @@ 'yiisoft/queue' => [ 'handlers' => [], 'channels' => [ - Queue::DEFAULT_CHANNEL_NAME => AdapterInterface::class, + QueueInterface::DEFAULT_CHANNEL_NAME => AdapterInterface::class, ], 'middlewares-push' => [], 'middlewares-consume' => [], diff --git a/src/Adapter/SynchronousAdapter.php b/src/Adapter/SynchronousAdapter.php index 46dca1df..950fbc3e 100644 --- a/src/Adapter/SynchronousAdapter.php +++ b/src/Adapter/SynchronousAdapter.php @@ -20,7 +20,7 @@ final class SynchronousAdapter implements AdapterInterface public function __construct( private WorkerInterface $worker, private QueueInterface $queue, - private string $channel = Queue::DEFAULT_CHANNEL_NAME, + private string $channel = QueueInterface::DEFAULT_CHANNEL_NAME, ) { } diff --git a/src/Command/ListenCommand.php b/src/Command/ListenCommand.php index 752852e9..8a80a625 100644 --- a/src/Command/ListenCommand.php +++ b/src/Command/ListenCommand.php @@ -10,6 +10,7 @@ use Symfony\Component\Console\Output\OutputInterface; use Yiisoft\Queue\Provider\QueueProviderInterface; use Yiisoft\Queue\Queue; +use Yiisoft\Queue\QueueInterface; final class ListenCommand extends Command { @@ -28,7 +29,7 @@ public function configure(): void 'channel', InputArgument::OPTIONAL, 'Queue channel name to connect to', - Queue::DEFAULT_CHANNEL_NAME, + QueueInterface::DEFAULT_CHANNEL_NAME, ); } diff --git a/src/Queue.php b/src/Queue.php index be600317..4ba0d2e0 100644 --- a/src/Queue.php +++ b/src/Queue.php @@ -20,9 +20,6 @@ final class Queue implements QueueInterface { - /** @psalm-suppress MissingClassConstType */ - public const DEFAULT_CHANNEL_NAME = 'yii-queue'; - /** * @var array|array[]|callable[]|MiddlewarePushInterface[]|string[] */ @@ -35,7 +32,7 @@ public function __construct( private LoggerInterface $logger, private PushMiddlewareDispatcher $pushMiddlewareDispatcher, private ?AdapterInterface $adapter = null, - private string $channelName = self::DEFAULT_CHANNEL_NAME, + private string $channelName = QueueInterface::DEFAULT_CHANNEL_NAME, MiddlewarePushInterface|callable|array|string ...$middlewareDefinitions ) { $this->middlewareDefinitions = $middlewareDefinitions; diff --git a/src/QueueInterface.php b/src/QueueInterface.php index 80a5016b..2204a4b1 100644 --- a/src/QueueInterface.php +++ b/src/QueueInterface.php @@ -12,6 +12,9 @@ interface QueueInterface { + /** @psalm-suppress MissingClassConstType */ + public const DEFAULT_CHANNEL_NAME = 'yii-queue'; + /** * Pushes a message into the queue. * diff --git a/src/StubQueue.php b/src/StubQueue.php index 8f06e2da..343c4e93 100644 --- a/src/StubQueue.php +++ b/src/StubQueue.php @@ -15,7 +15,7 @@ final class StubQueue implements QueueInterface { public function __construct( - private string $channelName = Queue::DEFAULT_CHANNEL_NAME, + private string $channelName = QueueInterface::DEFAULT_CHANNEL_NAME, private ?AdapterInterface $adapter = null, ) { } diff --git a/tests/Unit/StubQueueTest.php b/tests/Unit/StubQueueTest.php index 12e49080..314f0915 100644 --- a/tests/Unit/StubQueueTest.php +++ b/tests/Unit/StubQueueTest.php @@ -8,6 +8,7 @@ use Yiisoft\Queue\Adapter\StubAdapter; use Yiisoft\Queue\Message\Message; use Yiisoft\Queue\Queue; +use Yiisoft\Queue\QueueInterface; use Yiisoft\Queue\StubQueue; final class StubQueueTest extends TestCase @@ -20,7 +21,7 @@ public function testBase(): void $this->assertSame($message, $queue->push($message)); $this->assertSame(0, $queue->run()); $this->assertTrue($queue->status('test')->isDone()); - $this->assertSame(Queue::DEFAULT_CHANNEL_NAME, $queue->getChannelName()); + $this->assertSame(QueueInterface::DEFAULT_CHANNEL_NAME, $queue->getChannelName()); $this->assertNull($queue->getAdapter()); $queue->listen(); } @@ -42,7 +43,7 @@ public function testWithChannelName(): void $queue = $sourceQueue->withChannelName('test'); $this->assertNotSame($queue, $sourceQueue); - $this->assertSame(Queue::DEFAULT_CHANNEL_NAME, $sourceQueue->getChannelName()); + $this->assertSame(QueueInterface::DEFAULT_CHANNEL_NAME, $sourceQueue->getChannelName()); $this->assertSame('test', $queue->getChannelName()); } } diff --git a/tests/Unit/SynchronousAdapterTest.php b/tests/Unit/SynchronousAdapterTest.php index 7c369ae7..fae31fe2 100644 --- a/tests/Unit/SynchronousAdapterTest.php +++ b/tests/Unit/SynchronousAdapterTest.php @@ -7,6 +7,7 @@ use Yiisoft\Queue\Enum\JobStatus; use Yiisoft\Queue\Message\Message; use Yiisoft\Queue\Queue; +use Yiisoft\Queue\QueueInterface; use Yiisoft\Queue\Tests\TestCase; use Yiisoft\Queue\Message\IdEnvelope; @@ -51,7 +52,7 @@ public function testIdSetting(): void public function testWithSameChannel(): void { $adapter = $this->getAdapter(); - self::assertEquals($adapter, $adapter->withChannel(Queue::DEFAULT_CHANNEL_NAME)); + self::assertEquals($adapter, $adapter->withChannel(QueueInterface::DEFAULT_CHANNEL_NAME)); } public function testWithAnotherChannel(): void From 80cc195be2ba7555a919710063760457e1f5458a Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Mon, 11 Nov 2024 07:40:14 +0000 Subject: [PATCH 24/33] Apply fixes from StyleCI --- config/params.php | 1 - src/Adapter/SynchronousAdapter.php | 1 - src/Command/ListenCommand.php | 1 - tests/Unit/StubQueueTest.php | 1 - tests/Unit/SynchronousAdapterTest.php | 1 - 5 files changed, 5 deletions(-) diff --git a/config/params.php b/config/params.php index 0a8d5656..fc87d078 100644 --- a/config/params.php +++ b/config/params.php @@ -10,7 +10,6 @@ use Yiisoft\Queue\Debug\QueueProviderInterfaceProxy; use Yiisoft\Queue\Debug\QueueWorkerInterfaceProxy; use Yiisoft\Queue\Provider\QueueProviderInterface; -use Yiisoft\Queue\Queue; use Yiisoft\Queue\QueueInterface; use Yiisoft\Queue\Worker\WorkerInterface; diff --git a/src/Adapter/SynchronousAdapter.php b/src/Adapter/SynchronousAdapter.php index 950fbc3e..d2ee489b 100644 --- a/src/Adapter/SynchronousAdapter.php +++ b/src/Adapter/SynchronousAdapter.php @@ -7,7 +7,6 @@ use InvalidArgumentException; use Yiisoft\Queue\Enum\JobStatus; use Yiisoft\Queue\Message\MessageInterface; -use Yiisoft\Queue\Queue; use Yiisoft\Queue\QueueInterface; use Yiisoft\Queue\Worker\WorkerInterface; use Yiisoft\Queue\Message\IdEnvelope; diff --git a/src/Command/ListenCommand.php b/src/Command/ListenCommand.php index 8a80a625..ecafb837 100644 --- a/src/Command/ListenCommand.php +++ b/src/Command/ListenCommand.php @@ -9,7 +9,6 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Yiisoft\Queue\Provider\QueueProviderInterface; -use Yiisoft\Queue\Queue; use Yiisoft\Queue\QueueInterface; final class ListenCommand extends Command diff --git a/tests/Unit/StubQueueTest.php b/tests/Unit/StubQueueTest.php index 314f0915..4ce91d50 100644 --- a/tests/Unit/StubQueueTest.php +++ b/tests/Unit/StubQueueTest.php @@ -7,7 +7,6 @@ use PHPUnit\Framework\TestCase; use Yiisoft\Queue\Adapter\StubAdapter; use Yiisoft\Queue\Message\Message; -use Yiisoft\Queue\Queue; use Yiisoft\Queue\QueueInterface; use Yiisoft\Queue\StubQueue; diff --git a/tests/Unit/SynchronousAdapterTest.php b/tests/Unit/SynchronousAdapterTest.php index fae31fe2..6e913932 100644 --- a/tests/Unit/SynchronousAdapterTest.php +++ b/tests/Unit/SynchronousAdapterTest.php @@ -6,7 +6,6 @@ use Yiisoft\Queue\Enum\JobStatus; use Yiisoft\Queue\Message\Message; -use Yiisoft\Queue\Queue; use Yiisoft\Queue\QueueInterface; use Yiisoft\Queue\Tests\TestCase; use Yiisoft\Queue\Message\IdEnvelope; From 808bc5a174f64de5bf5392c6fddc18a7772eda38 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Mon, 11 Nov 2024 14:46:27 +0300 Subject: [PATCH 25/33] Extract stubs to separate namespace --- composer.json | 3 ++- {src/Adapter => stubs}/StubAdapter.php | 3 ++- {src/Cli => stubs}/StubLoop.php | 4 +++- {src => stubs}/StubQueue.php | 3 ++- {src/Worker => stubs}/StubWorker.php | 3 ++- tests/Unit/Provider/AdapterFactoryQueueProviderTest.php | 6 +++--- tests/Unit/Provider/CompositeQueueProviderTest.php | 2 +- tests/Unit/Provider/PrototypeQueueProviderTest.php | 2 +- tests/Unit/Provider/QueueFactoryQueueProviderTest.php | 4 ++-- tests/Unit/{Adapter => Stubs}/StubAdapterTest.php | 4 ++-- tests/Unit/{Cli => Stubs}/StubLoopTest.php | 4 ++-- tests/Unit/{ => Stubs}/StubQueueTest.php | 7 +++---- tests/Unit/{Worker => Stubs}/StubWorkerTest.php | 4 ++-- 13 files changed, 27 insertions(+), 22 deletions(-) rename {src/Adapter => stubs}/StubAdapter.php (90%) rename {src/Cli => stubs}/StubLoop.php (80%) rename {src => stubs}/StubQueue.php (96%) rename {src/Worker => stubs}/StubWorker.php (82%) rename tests/Unit/{Adapter => Stubs}/StubAdapterTest.php (87%) rename tests/Unit/{Cli => Stubs}/StubLoopTest.php (86%) rename tests/Unit/{ => Stubs}/StubQueueTest.php (90%) rename tests/Unit/{Worker => Stubs}/StubWorkerTest.php (89%) diff --git a/composer.json b/composer.json index de5d4b2b..0a7ad970 100644 --- a/composer.json +++ b/composer.json @@ -61,7 +61,8 @@ }, "autoload": { "psr-4": { - "Yiisoft\\Queue\\": "src" + "Yiisoft\\Queue\\": "src", + "Yiisoft\\Queue\\Stubs\\": "stubs" } }, "autoload-dev": { diff --git a/src/Adapter/StubAdapter.php b/stubs/StubAdapter.php similarity index 90% rename from src/Adapter/StubAdapter.php rename to stubs/StubAdapter.php index 894a5951..b47c850b 100644 --- a/src/Adapter/StubAdapter.php +++ b/stubs/StubAdapter.php @@ -2,8 +2,9 @@ declare(strict_types=1); -namespace Yiisoft\Queue\Adapter; +namespace Yiisoft\Queue\Stubs; +use Yiisoft\Queue\Adapter\AdapterInterface; use Yiisoft\Queue\Enum\JobStatus; use Yiisoft\Queue\Message\MessageInterface; diff --git a/src/Cli/StubLoop.php b/stubs/StubLoop.php similarity index 80% rename from src/Cli/StubLoop.php rename to stubs/StubLoop.php index a8747365..20a238b5 100644 --- a/src/Cli/StubLoop.php +++ b/stubs/StubLoop.php @@ -2,7 +2,9 @@ declare(strict_types=1); -namespace Yiisoft\Queue\Cli; +namespace Yiisoft\Queue\Stubs; + +use Yiisoft\Queue\Cli\LoopInterface; /** * Stub loop. diff --git a/src/StubQueue.php b/stubs/StubQueue.php similarity index 96% rename from src/StubQueue.php rename to stubs/StubQueue.php index 343c4e93..8436b46a 100644 --- a/src/StubQueue.php +++ b/stubs/StubQueue.php @@ -2,12 +2,13 @@ declare(strict_types=1); -namespace Yiisoft\Queue; +namespace Yiisoft\Queue\Stubs; use Yiisoft\Queue\Adapter\AdapterInterface; use Yiisoft\Queue\Enum\JobStatus; use Yiisoft\Queue\Message\MessageInterface; use Yiisoft\Queue\Middleware\Push\MiddlewarePushInterface; +use Yiisoft\Queue\QueueInterface; /** * Stub queue that does nothing. Job status is always "done". diff --git a/src/Worker/StubWorker.php b/stubs/StubWorker.php similarity index 82% rename from src/Worker/StubWorker.php rename to stubs/StubWorker.php index 2080f893..7a939006 100644 --- a/src/Worker/StubWorker.php +++ b/stubs/StubWorker.php @@ -2,10 +2,11 @@ declare(strict_types=1); -namespace Yiisoft\Queue\Worker; +namespace Yiisoft\Queue\Stubs; use Yiisoft\Queue\Message\MessageInterface; use Yiisoft\Queue\QueueInterface; +use Yiisoft\Queue\Worker\WorkerInterface; /** * Stub worker that does nothing. diff --git a/tests/Unit/Provider/AdapterFactoryQueueProviderTest.php b/tests/Unit/Provider/AdapterFactoryQueueProviderTest.php index 410d6446..24ca9096 100644 --- a/tests/Unit/Provider/AdapterFactoryQueueProviderTest.php +++ b/tests/Unit/Provider/AdapterFactoryQueueProviderTest.php @@ -6,12 +6,12 @@ use PHPUnit\Framework\TestCase; use Yiisoft\Queue\Adapter\AdapterInterface; -use Yiisoft\Queue\Adapter\StubAdapter; -use Yiisoft\Queue\Cli\StubLoop; +use Yiisoft\Queue\Stubs\StubLoop; use Yiisoft\Queue\Provider\AdapterFactoryQueueProvider; use Yiisoft\Queue\Provider\ChannelNotFoundException; use Yiisoft\Queue\Provider\InvalidQueueConfigException; -use Yiisoft\Queue\StubQueue; +use Yiisoft\Queue\Stubs\StubQueue; +use Yiisoft\Queue\Stubs\StubAdapter; use function sprintf; diff --git a/tests/Unit/Provider/CompositeQueueProviderTest.php b/tests/Unit/Provider/CompositeQueueProviderTest.php index 4804870a..9d74e269 100644 --- a/tests/Unit/Provider/CompositeQueueProviderTest.php +++ b/tests/Unit/Provider/CompositeQueueProviderTest.php @@ -7,7 +7,7 @@ use Yiisoft\Queue\Provider\ChannelNotFoundException; use Yiisoft\Queue\Provider\CompositeQueueProvider; use Yiisoft\Queue\Provider\QueueFactoryQueueProvider; -use Yiisoft\Queue\StubQueue; +use Yiisoft\Queue\Stubs\StubQueue; use Yiisoft\Queue\Tests\TestCase; final class CompositeQueueProviderTest extends TestCase diff --git a/tests/Unit/Provider/PrototypeQueueProviderTest.php b/tests/Unit/Provider/PrototypeQueueProviderTest.php index 06fc5e18..601a0f24 100644 --- a/tests/Unit/Provider/PrototypeQueueProviderTest.php +++ b/tests/Unit/Provider/PrototypeQueueProviderTest.php @@ -6,7 +6,7 @@ use PHPUnit\Framework\TestCase; use Yiisoft\Queue\Provider\PrototypeQueueProvider; -use Yiisoft\Queue\StubQueue; +use Yiisoft\Queue\Stubs\StubQueue; final class PrototypeQueueProviderTest extends TestCase { diff --git a/tests/Unit/Provider/QueueFactoryQueueProviderTest.php b/tests/Unit/Provider/QueueFactoryQueueProviderTest.php index 629d04fc..6a569d35 100644 --- a/tests/Unit/Provider/QueueFactoryQueueProviderTest.php +++ b/tests/Unit/Provider/QueueFactoryQueueProviderTest.php @@ -5,12 +5,12 @@ namespace Yiisoft\Queue\Tests\Unit\Provider; use PHPUnit\Framework\TestCase; -use Yiisoft\Queue\Cli\StubLoop; +use Yiisoft\Queue\Stubs\StubLoop; use Yiisoft\Queue\Provider\ChannelNotFoundException; use Yiisoft\Queue\Provider\QueueFactoryQueueProvider; use Yiisoft\Queue\Provider\InvalidQueueConfigException; use Yiisoft\Queue\QueueInterface; -use Yiisoft\Queue\StubQueue; +use Yiisoft\Queue\Stubs\StubQueue; use function sprintf; diff --git a/tests/Unit/Adapter/StubAdapterTest.php b/tests/Unit/Stubs/StubAdapterTest.php similarity index 87% rename from tests/Unit/Adapter/StubAdapterTest.php rename to tests/Unit/Stubs/StubAdapterTest.php index 3903ba84..b7337967 100644 --- a/tests/Unit/Adapter/StubAdapterTest.php +++ b/tests/Unit/Stubs/StubAdapterTest.php @@ -2,11 +2,11 @@ declare(strict_types=1); -namespace Yiisoft\Queue\Tests\Unit\Adapter; +namespace Yiisoft\Queue\Tests\Unit\Stubs; use PHPUnit\Framework\TestCase; -use Yiisoft\Queue\Adapter\StubAdapter; use Yiisoft\Queue\Message\Message; +use Yiisoft\Queue\Stubs\StubAdapter; final class StubAdapterTest extends TestCase { diff --git a/tests/Unit/Cli/StubLoopTest.php b/tests/Unit/Stubs/StubLoopTest.php similarity index 86% rename from tests/Unit/Cli/StubLoopTest.php rename to tests/Unit/Stubs/StubLoopTest.php index 3bb54fe2..c78d3af7 100644 --- a/tests/Unit/Cli/StubLoopTest.php +++ b/tests/Unit/Stubs/StubLoopTest.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace Cli; +namespace Yiisoft\Queue\Tests\Unit\Stubs; use PHPUnit\Framework\Attributes\DataProvider; -use Yiisoft\Queue\Cli\StubLoop; +use Yiisoft\Queue\Stubs\StubLoop; use Yiisoft\Queue\Tests\TestCase; final class StubLoopTest extends TestCase diff --git a/tests/Unit/StubQueueTest.php b/tests/Unit/Stubs/StubQueueTest.php similarity index 90% rename from tests/Unit/StubQueueTest.php rename to tests/Unit/Stubs/StubQueueTest.php index 314f0915..29efe050 100644 --- a/tests/Unit/StubQueueTest.php +++ b/tests/Unit/Stubs/StubQueueTest.php @@ -2,14 +2,13 @@ declare(strict_types=1); -namespace Yiisoft\Queue\Tests\Unit; +namespace Yiisoft\Queue\Tests\Unit\Stubs; use PHPUnit\Framework\TestCase; -use Yiisoft\Queue\Adapter\StubAdapter; use Yiisoft\Queue\Message\Message; -use Yiisoft\Queue\Queue; use Yiisoft\Queue\QueueInterface; -use Yiisoft\Queue\StubQueue; +use Yiisoft\Queue\Stubs\StubQueue; +use Yiisoft\Queue\Stubs\StubAdapter; final class StubQueueTest extends TestCase { diff --git a/tests/Unit/Worker/StubWorkerTest.php b/tests/Unit/Stubs/StubWorkerTest.php similarity index 89% rename from tests/Unit/Worker/StubWorkerTest.php rename to tests/Unit/Stubs/StubWorkerTest.php index 9f8d379d..e61021ec 100644 --- a/tests/Unit/Worker/StubWorkerTest.php +++ b/tests/Unit/Stubs/StubWorkerTest.php @@ -2,12 +2,12 @@ declare(strict_types=1); -namespace Worker; +namespace Yiisoft\Queue\Tests\Unit\Stubs; use PHPUnit\Framework\TestCase; use Yiisoft\Queue\Message\Message; use Yiisoft\Queue\QueueInterface; -use Yiisoft\Queue\Worker\StubWorker; +use Yiisoft\Queue\Stubs\StubWorker; final class StubWorkerTest extends TestCase { From 305d64fd566732f5ecec419dd723d236bb7cfd04 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Mon, 18 Nov 2024 16:40:18 +0300 Subject: [PATCH 26/33] Fix `Queue` --- src/Queue.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Queue.php b/src/Queue.php index 4ba0d2e0..6544c1b9 100644 --- a/src/Queue.php +++ b/src/Queue.php @@ -140,7 +140,7 @@ public function withChannelName(string $channel): self { $instance = clone $this; $instance->channelName = $channel; - + $instance->adapter = $this->adapter?->withChannel($channel); return $instance; } From 136b584c7c30362dc51c0e12fbdab24bcb24dec2 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Mon, 18 Nov 2024 16:42:49 +0300 Subject: [PATCH 27/33] fix exception --- .../AdapterConfiguration/AdapterNotConfiguredException.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Exception/AdapterConfiguration/AdapterNotConfiguredException.php b/src/Exception/AdapterConfiguration/AdapterNotConfiguredException.php index f5eec158..fc6713be 100644 --- a/src/Exception/AdapterConfiguration/AdapterNotConfiguredException.php +++ b/src/Exception/AdapterConfiguration/AdapterNotConfiguredException.php @@ -20,6 +20,7 @@ public function getName(): string public function getSolution(): ?string { $queueClass = Queue::class; + $queueProviderInterface = QueueProviderInterface::class; return << Date: Mon, 18 Nov 2024 16:43:06 +0300 Subject: [PATCH 28/33] fix --- .../AdapterConfiguration/AdapterNotConfiguredException.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Exception/AdapterConfiguration/AdapterNotConfiguredException.php b/src/Exception/AdapterConfiguration/AdapterNotConfiguredException.php index fc6713be..68ae754a 100644 --- a/src/Exception/AdapterConfiguration/AdapterNotConfiguredException.php +++ b/src/Exception/AdapterConfiguration/AdapterNotConfiguredException.php @@ -6,6 +6,7 @@ use RuntimeException; use Yiisoft\FriendlyException\FriendlyExceptionInterface; +use Yiisoft\Queue\Provider\QueueProviderInterface; use Yiisoft\Queue\Queue; class AdapterNotConfiguredException extends RuntimeException implements FriendlyExceptionInterface From 94d854045bca375d70270d66588eb775d95c6bd4 Mon Sep 17 00:00:00 2001 From: viktorprogger Date: Sun, 8 Dec 2024 00:13:37 +0500 Subject: [PATCH 29/33] Remove QueueFactoryQueueProvider --- src/Provider/QueueFactoryQueueProvider.php | 92 ---------------------- 1 file changed, 92 deletions(-) delete mode 100644 src/Provider/QueueFactoryQueueProvider.php diff --git a/src/Provider/QueueFactoryQueueProvider.php b/src/Provider/QueueFactoryQueueProvider.php deleted file mode 100644 index 3b57375b..00000000 --- a/src/Provider/QueueFactoryQueueProvider.php +++ /dev/null @@ -1,92 +0,0 @@ - - */ - private array $queues = []; - - private readonly StrictFactory $factory; - - /** - * @param array $definitions Definitions to create queues with indexed by channel names. - * @param ContainerInterface|null $container Container to use for resolving dependencies. - * @param bool $validate If definitions should be validated when set. - * - * @psalm-param array $definitions - * @throws InvalidQueueConfigException - */ - public function __construct( - array $definitions, - ?ContainerInterface $container = null, - bool $validate = true, - ) { - try { - $this->factory = new StrictFactory($definitions, $container, $validate); - } catch (InvalidConfigException $exception) { - throw new InvalidQueueConfigException($exception->getMessage(), previous: $exception); - } - } - - public function get(string $channel): QueueInterface - { - $queue = $this->getOrTryCreate($channel); - if ($queue === null) { - throw new ChannelNotFoundException($channel); - } - return $queue; - } - - public function has(string $channel): bool - { - return $this->factory->has($channel); - } - - /** - * @throws InvalidQueueConfigException - */ - private function getOrTryCreate(string $channel): QueueInterface|null - { - if (array_key_exists($channel, $this->queues)) { - return $this->queues[$channel]; - } - - if ($this->factory->has($channel)) { - $queue = $this->factory->create($channel); - if (!$queue instanceof QueueInterface) { - throw new InvalidQueueConfigException( - sprintf( - 'Queue must implement "%s". For channel "%s" got "%s" instead.', - QueueInterface::class, - $channel, - get_debug_type($queue), - ), - ); - } - $this->queues[$channel] = $queue->withChannelName($channel); - } else { - $this->queues[$channel] = null; - } - - return $this->queues[$channel]; - } -} From 14401e13a422c90a39a0151762813c237dbc780f Mon Sep 17 00:00:00 2001 From: viktorprogger Date: Sun, 8 Dec 2024 00:13:48 +0500 Subject: [PATCH 30/33] Fix docs --- src/Provider/AdapterFactoryQueueProvider.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Provider/AdapterFactoryQueueProvider.php b/src/Provider/AdapterFactoryQueueProvider.php index feaed434..ffe777f5 100644 --- a/src/Provider/AdapterFactoryQueueProvider.php +++ b/src/Provider/AdapterFactoryQueueProvider.php @@ -14,7 +14,7 @@ use function sprintf; /** - * Queue provider based on adapter definitions. + * This queue provider create new queue objects based on adapter definitions. * * @see https://github.com/yiisoft/definitions/ * @see https://github.com/yiisoft/factory/ @@ -29,9 +29,9 @@ final class AdapterFactoryQueueProvider implements QueueProviderInterface private readonly StrictFactory $factory; /** - * @param QueueInterface $baseQueue Base queue to use for creating queues. - * @param array $definitions Definitions to create adapters with indexed by channel names. - * @param ContainerInterface|null $container Container to use for resolving dependencies. + * @param QueueInterface $baseQueue Base queue for queues creation. + * @param array $definitions Adapter definitions indexed by channel names. + * @param ContainerInterface|null $container Container to use for dependencies resolving. * @param bool $validate If definitions should be validated when set. * * @psalm-param array $definitions @@ -52,7 +52,7 @@ public function __construct( public function get(string $channel): QueueInterface { - $queue = $this->getOrTryCreate($channel); + $queue = $this->getOrTryToCreate($channel); if ($queue === null) { throw new ChannelNotFoundException($channel); } @@ -67,7 +67,7 @@ public function has(string $channel): bool /** * @throws InvalidQueueConfigException */ - private function getOrTryCreate(string $channel): QueueInterface|null + private function getOrTryToCreate(string $channel): QueueInterface|null { if (array_key_exists($channel, $this->queues)) { return $this->queues[$channel]; From 1cc44381eff171a5ccba27807e559ea7ed56e60a Mon Sep 17 00:00:00 2001 From: viktorprogger Date: Sun, 8 Dec 2024 00:13:55 +0500 Subject: [PATCH 31/33] Fix config --- config/di.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/di.php b/config/di.php index 6e1867d5..b9b28033 100644 --- a/config/di.php +++ b/config/di.php @@ -29,12 +29,12 @@ /* @var array $params */ return [ - QueueProviderInterface::class => [ - 'class' => AdapterFactoryQueueProvider::class, + AdapterFactoryQueueProvider::class => [ '__construct()' => [ 'definitions' => $params['yiisoft/queue']['channels'], ], ], + QueueProviderInterface::class => AdapterFactoryQueueProvider::class, QueueWorker::class => [ 'class' => QueueWorker::class, '__construct()' => [$params['yiisoft/queue']['handlers']], From f98268066852a24951f6562285b042340f8d4fe5 Mon Sep 17 00:00:00 2001 From: viktorprogger Date: Sun, 8 Dec 2024 00:37:38 +0500 Subject: [PATCH 32/33] Bugfixes --- README.md | 5 - .../Provider/CompositeQueueProviderTest.php | 26 ++--- .../QueueFactoryQueueProviderTest.php | 94 ------------------- tests/Unit/QueueTest.php | 4 + 4 files changed, 18 insertions(+), 111 deletions(-) delete mode 100644 tests/Unit/Provider/QueueFactoryQueueProviderTest.php diff --git a/README.md b/README.md index 1d0ca5f2..4914175e 100644 --- a/README.md +++ b/README.md @@ -170,7 +170,6 @@ $queue = $provider->get('channel-name'); Out of the box, there are four implementations of the `QueueProviderInterface`: - `AdapterFactoryQueueProvider` -- `QueueFactoryQueueProvider` - `PrototypeQueueProvider` - `CompositeQueueProvider` @@ -195,10 +194,6 @@ use Yiisoft\Queue\Adapter\SynchronousAdapter; For more information about a definition formats available see the [factory](https://github.com/yiisoft/factory) documentation. -### `QueueFactoryQueueProvider` - -Provider is similar to `AdapterFactoryQueueProvider`, but it uses definitions of channel-specific queues. - ### `PrototypeQueueProvider` Queue provider that only changes the channel name of the base queue. It can be useful when your queues used the same diff --git a/tests/Unit/Provider/CompositeQueueProviderTest.php b/tests/Unit/Provider/CompositeQueueProviderTest.php index 9d74e269..491017ee 100644 --- a/tests/Unit/Provider/CompositeQueueProviderTest.php +++ b/tests/Unit/Provider/CompositeQueueProviderTest.php @@ -4,9 +4,10 @@ namespace Yiisoft\Queue\Tests\Unit\Provider; +use Yiisoft\Queue\Provider\AdapterFactoryQueueProvider; use Yiisoft\Queue\Provider\ChannelNotFoundException; use Yiisoft\Queue\Provider\CompositeQueueProvider; -use Yiisoft\Queue\Provider\QueueFactoryQueueProvider; +use Yiisoft\Queue\Stubs\StubAdapter; use Yiisoft\Queue\Stubs\StubQueue; use Yiisoft\Queue\Tests\TestCase; @@ -14,13 +15,16 @@ final class CompositeQueueProviderTest extends TestCase { public function testBase(): void { + $queue = new StubQueue('channel'); $provider = new CompositeQueueProvider( - new QueueFactoryQueueProvider([ - 'channel1' => new StubQueue('channel1'), - ]), - new QueueFactoryQueueProvider([ - 'channel2' => new StubQueue('channel2'), - ]), + new AdapterFactoryQueueProvider( + $queue, + ['channel1' => new StubAdapter()], + ), + new AdapterFactoryQueueProvider( + $queue, + ['channel2' => new StubAdapter()], + ), ); $this->assertTrue($provider->has('channel1')); @@ -34,13 +38,11 @@ public function testBase(): void public function testNotFound(): void { $provider = new CompositeQueueProvider( - new QueueFactoryQueueProvider([ - 'channel1' => new StubQueue(), - ]), + new AdapterFactoryQueueProvider(new StubQueue('channel'), ['channel1' => new StubAdapter()]), ); $this->expectException(ChannelNotFoundException::class); - $this->expectExceptionMessage('Channel "not-exist" not found.'); - $provider->get('not-exist'); + $this->expectExceptionMessage('Channel "not-exists" not found.'); + $provider->get('not-exists'); } } diff --git a/tests/Unit/Provider/QueueFactoryQueueProviderTest.php b/tests/Unit/Provider/QueueFactoryQueueProviderTest.php deleted file mode 100644 index 6a569d35..00000000 --- a/tests/Unit/Provider/QueueFactoryQueueProviderTest.php +++ /dev/null @@ -1,94 +0,0 @@ - StubQueue::class, - ], - ); - - $queue = $provider->get('channel1'); - - $this->assertInstanceOf(StubQueue::class, $queue); - $this->assertSame('channel1', $queue->getChannelName()); - $this->assertTrue($provider->has('channel1')); - $this->assertFalse($provider->has('not-exist-channel')); - } - - public function testGetTwice(): void - { - $provider = new QueueFactoryQueueProvider( - [ - 'channel1' => StubQueue::class, - ], - ); - - $queue1 = $provider->get('channel1'); - $queue2 = $provider->get('channel1'); - - $this->assertSame($queue1, $queue2); - } - - public function testGetNotExistChannel(): void - { - $provider = new QueueFactoryQueueProvider( - [ - 'channel1' => StubQueue::class, - ], - ); - - $this->expectException(ChannelNotFoundException::class); - $this->expectExceptionMessage('Channel "not-exist-channel" not found.'); - $provider->get('not-exist-channel'); - } - - public function testInvalidQueueConfig(): void - { - $definitions = [ - 'channel1' => [ - 'class' => StubQueue::class, - '__construct()' => 'hello', - ], - ]; - - $this->expectException(InvalidQueueConfigException::class); - $this->expectExceptionMessage( - 'Invalid definition: incorrect constructor arguments. Expected array, got string.' - ); - new QueueFactoryQueueProvider($definitions); - } - - public function testInvalidQueueConfigOnGet(): void - { - $provider = new QueueFactoryQueueProvider([ - 'channel1' => StubLoop::class, - ]); - - $this->expectException(InvalidQueueConfigException::class); - $this->expectExceptionMessage( - sprintf( - 'Queue must implement "%s". For channel "channel1" got "%s" instead.', - QueueInterface::class, - StubLoop::class, - ) - ); - $provider->get('channel1'); - } -} diff --git a/tests/Unit/QueueTest.php b/tests/Unit/QueueTest.php index 7a477e66..24a0155f 100644 --- a/tests/Unit/QueueTest.php +++ b/tests/Unit/QueueTest.php @@ -130,6 +130,10 @@ public function testAdapterNotConfiguredExceptionForRun(): void public function testRunWithSignalLoop(): void { + if (!extension_loaded('pcntl')) { + $this->markTestSkipped("This rest requires PCNTL extension"); + } + $this->loop = new SignalLoop(); $queue = $this ->getQueue() From 88370f95eb41f2d31e38dd498eceb7af2c7c0ffd Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Sat, 7 Dec 2024 19:37:49 +0000 Subject: [PATCH 33/33] Apply fixes from StyleCI --- tests/Unit/QueueTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/QueueTest.php b/tests/Unit/QueueTest.php index 24a0155f..1bfe8001 100644 --- a/tests/Unit/QueueTest.php +++ b/tests/Unit/QueueTest.php @@ -131,7 +131,7 @@ public function testAdapterNotConfiguredExceptionForRun(): void public function testRunWithSignalLoop(): void { if (!extension_loaded('pcntl')) { - $this->markTestSkipped("This rest requires PCNTL extension"); + $this->markTestSkipped('This rest requires PCNTL extension'); } $this->loop = new SignalLoop();