Search code examples
symfonyrabbitmqamqp

Use default transport (skip amqp) for Symfony Messenger


In messenger.yaml, I route my messages to amqp accordingly

routing:
  # Route your messages to the transports
  'App\Message\SendNewsletterMessage': amqp

But in some environments, where I don't have RabbitMQ installed, I want to send the messages directly. I don't want to simply comment out the line, because the code is deployed in multiple places. Instead, I want to set the transport to be the internal call (as if it were commented out), but I can't figure out what the name of that default transport is.

routing:
  # Route your messages to the transports
  'App\Message\SendNewsletterMessage':  '%env(MESSAGE_TRANSPORT)%' # amqp or...

Then my environment variable can either be 'amqp' or direct. What is the transport to use for it to make a direct call?


Solution

  • Looks like it is not possible, as direct messages is not a transport. As a workaround you can rewrite your configuration:

    # config/packages/dev/messenger.yaml
    framework:
        messenger:
            routing: []
    
    # config/packages/prod/messenger.yaml
    framework:
        messenger:
            'App\Message\SendNewsletterMessage': amqp
    
    # config/packages/messenger.yaml
    framework:
        messenger:
            transports:
                amqp: '%env(MESSENGER_TRANSPORT_DSN)%'
    

    If you want to configure transport for one environments you can decorate messenger.senders_locator:

    # config/services.yaml
    services:
        App\DirectSendersLocator:
            decorates: messenger.senders_locator
            arguments:
                - '@App\DirectSendersLocator.inner'
                - '%env(bool:DIRECT_TRANSPORT)%'
    
    namespace App;
    
    use Symfony\Component\Messenger\Envelope;
    use Symfony\Component\Messenger\Transport\Sender\SendersLocatorInterface;
    
    class DirectSendersLocator implements SendersLocatorInterface
    {
        /**
         * @var SendersLocatorInterface
         */
        private $decorated;
    
        /**
         * @var bool
         */
        private $direct;
    
        public function __construct(SendersLocatorInterface $decorated, bool $direct)
        {
            $this->decorated = $decorated;
            $this->direct = $direct;
        }
    
        public function getSenders(Envelope $envelope, ?bool &$handle = false): iterable
        {
            if ($this->direct) {
                $handle = true;
    
                return [];
            }
    
            $this->decorated->getSenders($envelope, $handle);
        }
    }