queue icon indicating copy to clipboard operation
queue copied to clipboard

Trunk enhancements branch

Open xepozz opened this issue 5 months ago • 1 comments

Includes:

  • https://github.com/yiisoft/queue/pull/189
  • https://github.com/yiisoft/queue/pull/188
  • https://github.com/yiisoft/queue/pull/182

Differences:

  • Queue messages dispatches through Psr\EventDispatcherInterface
  • SynchronousAdapter triggers on both console and web request end events instead of __destruct() method
  • No more PushDispatcher, ConsomeDispatcher, FailureDispatcher and tens of related classes
  • Eliminated HandlerEnvelope

How to handle messages now:

  1. Create app/config/common/queue.php file
  2. Write the following:
    <?php
    
    declare(strict_types=1);
    
    use App\Queue\HelloMessage;
    use App\Queue\HelloMessageHandler;
    use Yiisoft\Queue\Message\EnvelopeInterface;
    use Yiisoft\Queue\Message\Message;
    
    /** @var array $params */
    
    return [
        HelloMessage::class => [
            fn(HelloMessage $message, HelloMessageHandler $handler) => $handler->handle($message),
        ],
        Message::class => [
            fn(Message $message) => $message instanceof EnvelopeInterface ? $message->getMessage() : $message,
        ],
    ];
    
  3. The keys are Messages to listen. Each message must implement \Yiisoft\Queue\Message\MessageInterface. \Yiisoft\Queue\Message\MessageTrait may help with it
  4. Values are callables, or simply, handlers, like the yiisoft/event-dispatcher ones

There are HelloeMessage itself:

<?php

declare(strict_types=1);

namespace App\Queue;

use Yiisoft\Queue\Message\MessageInterface;
use Yiisoft\Queue\Message\MessageTrait;

class HelloMessage implements MessageInterface
{
    use MessageTrait;

    public function __construct(
        private mixed $message
    ) {
        $this->data = $message;
    }
}

And it's handler:

<?php

declare(strict_types=1);

namespace App\Queue;

use Yiisoft\Aliases\Aliases;
use Yiisoft\Queue\Message\MessageHandlerInterface;
use Yiisoft\Queue\Message\MessageInterface;

class HelloMessageHandler implements MessageHandlerInterface
{
    public function __construct(private Aliases $aliases)
    {
    }

    public function handle(MessageInterface $message): void
    {
        file_put_contents(
            $this->aliases->get('@runtime/hello-queue.log'),
            json_encode($message->getData()) . PHP_EOL,
            FILE_APPEND
        );
    }
}

Now you can use the queue as a regular service in any services or controllers:

<?php

declare(strict_types=1);

namespace App\User\Controller;

use App\Queue\HelloMessage;
use App\Queue\PassMiddleware;
use HttpSoft\Response\TextResponse;
use Yiisoft\Queue\Middleware\MessageHandlerInterface;
use Yiisoft\Queue\Middleware\MiddlewareInterface;
use Yiisoft\Queue\Middleware\Request;
use Yiisoft\Queue\QueueInterface;

class TestController
{
    public function index(QueueInterface $queue): TextResponse 
    {
        $queue->push(
            new HelloMessage('Hello, World!'), // the message gonna be written in the file in the HelloMessageHandler
            new class () implements MiddlewareInterface {
                public function process(Request $request, MessageHandlerInterface $handler): Request
                {
                    return $handler->handle($request); // just to be sure all middlewares still work
                }
            }
        );
        return new TextResponse('Hello, World!');
    }
}

After a \Yiisoft\Yii\Http\Event\AfterRequest event is thrown application event dispatcher can trigger SynchronousAdapter::run() and it process all in-memory messages.

SynchronousAdapter does double un- and serialization to apply all envelopes to the final message. So SynchronousAdapter stores serialized with \Yiisoft\Queue\Message\MessageSerializerInterface, currently it's \Yiisoft\Queue\Message\JsonMessageSerializer. When it starts to handles the stored messages it decodes the ones with the same \Yiisoft\Queue\Message\MessageSerializerInterface and applies all envelopes before it goes to the final queue message handler.

xepozz avatar Jan 14 '24 13:01 xepozz