Symfony/Messenger
Un nouveau composant à votre service !

Stéphane Hulard

CTO, Formateur, Contributeur.

Messenger ?

Pour communiquer !

Oui mais on a déjà les Event

PSR14: Event Manager, Adapter ≠ Informer

Abstraction

Interfaces……et configuration !

Vue d'ensemble…

Take the red pill…

Ok, c'est quoi un Message ?

                            
class DeleteExamFromSearch
{
    private $exam_uid;

    public function __construct(Exam $exam)
    {
        $this->exam_uid = $exam->id();
    }

    public function getExamUid(): ExamUid
    {
        return $this->exam_uid;
    }
}
                            
                        

Comment le diffuser ?

                            
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Messenger\MessageBusInterface;

class FlagExam extends Controller
{
    public function __invoke(Exam $exam, MessageBusInterface $bus): Response
    {
        // Mise à jour de l'examen et sauvegarde du flag.

        $bus->dispatch(new DeleteExamFromSearch($exam));
    }
}
                            
                        

Message Bus ?

Configuration messenger.yaml

                            
framework:
    messenger:
        transports:
            default: '%env(MESSENGER_ADAPTER_DSN)%'

        routing:
            # Route your messages to the transports
                            
                        

Un Message voyage…

Protocole AMQP, broker

…avec un Adapter…

queue-interop/queue-interop

enqueue/messenger-adapter

enqueue/enqueue-bundle

enqueue/*

… sur la bonne route !

                            
framework:
    messenger:
        transports:
            default: enqueue://redis
            log: enqueue://file

        routing:
            'App\Domain\Exam\Message\DeleteExamFromSearch': [default, log]
            '*': default
                            
                        

Contrôler la diffusion

Middlewares

                            
namespace Symfony\Component\Messenger\Middleware;

interface MiddlewareInterface
{
    public function handle($message, callable $next);
}
                            
                        
                            
use Psr\Log\LoggerInterface;
use Symfony\Component\Messenger\Middleware\MiddlewareInterface;

class LoggingMiddleware implements MiddlewareInterface
{
    private $logger;

    public function __construct(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }

    public function handle($message, callable $next)
    {
        $this->logger->debug(
            'Starting handling message {class}',
            get_class($message)
        );
        return $next($message);
    }
}
                            
                        

Configuration

                            
# config/packages/messenger.yaml
framework:
    messenger:
        buses:
            messenger.bus.default:
                middleware:
                    - 'App\Middleware\LoggingMiddleware'
                            
                        

Traitement des messages

Définition d'un Handler

                            
use Symfony\Component\Messenger\Handler\MessageHandlerInterface;

class DeleteFlaggedExam implements MessageHandlerInterface
{
    /** @var ElasticsearchConnection */
    private $connection;

    public function __invoke(DeleteExamFromSearch $message)
    {
        $this->connection->removeExam($message->getExamUid());
    }
}
                            
                        

Configuration

                            
services:
    App\Domain\Exam\Message\Handler\DeleteFlaggedExam:
        tags: [messenger.message_handler]
                            
                        

Exécution

Synchrone, ou asynchrone

bin/console messenger:consume-messages [amqp]

Handler, Sender, Receiver

Sender personnalisé

                            
class SmtpSender implements SenderInterface
{
    /** @var SmtpConnection */
    private $connection;

    public function send($message): void
    {
        $this->connection->send(
            // Transformer le message en e-mail
        );
    }
}
                            
                        

Configuration


# config/services.yaml
services:
    App\Transport\SmtpSender:
        tags:
            - { name: 'messenger.sender', alias: 'custom_email' }
                        

# config/packages/messenger.yaml
framework:
    messenger:
        routing:
            App\Domain\Exam\Message\Handler\DeleteFlaggedExam:
                senders: ['custom_email']
                send_and_handle: true
                        


https://joind.in/24671