diff --git a/README.md b/README.md index 25f94f74..1706eaf0 100644 --- a/README.md +++ b/README.md @@ -53,14 +53,16 @@ Each queue task consists of two parts: `Yiisoft\Queue\Message\Message`. For more complex cases you should implement the interface by your own. 2. A message handler is a callable called by a `Yiisoft\Queue\Worker\Worker`. The handler handles each queue message. -For example, if you need to download and save a file, your message may look like the following: +For example, if you need to download and save a file, your message creation may look like the following: +- Message handler as the first parameter +- Message data as the second parameter ```php $data = [ 'url' => $url, 'destinationFile' => $filename, ]; -$message = new \Yiisoft\Queue\Message\Message('file-download', $data); +$message = new \Yiisoft\Queue\Message\Message(FileDownloader::class, $data); ``` Then you should push it to the queue: @@ -93,9 +95,8 @@ class FileDownloader The last thing we should do is to create a configuration for the `Yiisoft\Queue\Worker\Worker`: ```php -$handlers = ['file-download' => [new FileDownloader('/path/to/save/files'), 'handle']]; $worker = new \Yiisoft\Queue\Worker\Worker( - $handlers, // Here it is + [], $logger, $injector, $container @@ -134,6 +135,28 @@ $status->isReserved(); $status->isDone(); ``` +## Custom handler names +### Custom handler names + +By default, when you push a message to the queue, the message handler name is the fully qualified class name of the handler. +This can be useful for most cases, but sometimes you may want to use a shorter name or arbitrary string as the handler name. +This can be useful when you want to reduce the amount of data being passed or when you communicate with external systems. + +To use a custom handler name before message push, you can pass it as the first argument `Message` when creating it: +```php +new Message('handler-name', $data); +``` + +To use a custom handler name on message consume, you should configure handler mapping for the `Worker` class: +```php +$worker = new \Yiisoft\Queue\Worker\Worker( + ['handler-name' => FooHandler::class], + $logger, + $injector, + $container +); +``` + ## Different queue channels Often we need to push to different queue channels with an only application. There is the `QueueFactory` class to make diff --git a/src/Message/MessageHandlerInterface.php b/src/Message/MessageHandlerInterface.php new file mode 100644 index 00000000..7a8ab1f9 --- /dev/null +++ b/src/Message/MessageHandlerInterface.php @@ -0,0 +1,10 @@ +handlersCached)) { + $definition = $this->handlers[$name] ?? null; + if ($definition === null && $this->container->has($name)) { + $handler = $this->container->get($name); + if ($handler instanceof MessageHandlerInterface) { + $this->handlersCached[$name] = $handler->handle(...); + + return $this->handlersCached[$name]; + } + + return null; + } + $this->handlersCached[$name] = $this->prepare($this->handlers[$name] ?? null); } diff --git a/tests/Integration/MessageConsumingTest.php b/tests/Integration/MessageConsumingTest.php index 6c30ba92..e5775ea0 100644 --- a/tests/Integration/MessageConsumingTest.php +++ b/tests/Integration/MessageConsumingTest.php @@ -13,6 +13,7 @@ use Yiisoft\Queue\Middleware\Consume\MiddlewareFactoryConsumeInterface; use Yiisoft\Queue\Middleware\FailureHandling\FailureMiddlewareDispatcher; use Yiisoft\Queue\Middleware\FailureHandling\MiddlewareFactoryFailureInterface; +use Yiisoft\Queue\Tests\Integration\Support\TestHandler; use Yiisoft\Queue\Tests\TestCase; use Yiisoft\Queue\Worker\Worker; @@ -41,4 +42,27 @@ public function testMessagesConsumed(): void $this->assertEquals($messages, $this->messagesProcessed); } + + public function testMessagesConsumedByHandlerClass(): void + { + $handler = new TestHandler(); + $container = $this->createMock(ContainerInterface::class); + $container->method('get')->with(TestHandler::class)->willReturn($handler); + $container->method('has')->with(TestHandler::class)->willReturn(true); + $worker = new Worker( + [], + new NullLogger(), + new Injector($container), + $container, + new ConsumeMiddlewareDispatcher($this->createMock(MiddlewareFactoryConsumeInterface::class)), + new FailureMiddlewareDispatcher($this->createMock(MiddlewareFactoryFailureInterface::class), []) + ); + + $messages = [1, 'foo', 'bar-baz']; + foreach ($messages as $message) { + $worker->process(new Message(TestHandler::class, $message), $this->getQueue()); + } + + $this->assertEquals($messages, $handler->messagesProcessed); + } } diff --git a/tests/Integration/Support/TestHandler.php b/tests/Integration/Support/TestHandler.php new file mode 100644 index 00000000..ce71f7fb --- /dev/null +++ b/tests/Integration/Support/TestHandler.php @@ -0,0 +1,20 @@ +messagesProcessed[] = $message->getData(); + } +}