使用Messenger阅读未与Messenger发送的排队消息

时间:2019-04-08 16:00:45

标签: symfony rabbitmq symfony-messenger

我正在尝试读取未通过Symfony Messenger发送的排队消息(在RabbitMQ中)。 Messenger似乎添加了一些标题,例如

headers: 
    type: App\Message\Transaction

但是在读取外部消息时,此标头不存在。

因此,有没有办法告诉Messenger,必须将队列A中的每条消息都视为消息类型Transaction

我今天有的是:

framework:
    messenger:
        transports:
            # Uncomment the following line to enable a transport named "amqp"
            amqp:
                dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
                options:
                    exchange:
                        name: messages
                        type: direct
                    queue:
                        name: queue_messages

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

我想添加的内容如下:

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

1 个答案:

答案 0 :(得分:0)

Ryan Weaver就symfony的松弛问题回答了类似的问题

  

如果消息不是来自Messenger的,则需要一个自定义的Messenger序列化器:)

     

1)您创建一个自定义序列化(从Messenger中实现SerializerInterface),并在Messenger配置下对其进行配置

     

2)以某种方式在该序列化器中,采用JSON并将其转换为代码中具有的某些“消息”对象。 操作方法,这取决于您-您需要以某种方式查看JSON并确定应将其映射到哪个消息类。然后,您可以手动创建该对象并填充数据,或使用Symfony的序列化器。在返回之前先将其包裹在信封中

     

3)因为您的序列化程序现在正在返回“消息”对象(如果有某种排序),那么Messenger使用其常规逻辑来查找该消息的处理程序并执行它们。


我根据自己的需要进行了快速实施,取决于您的业务逻辑

1-创建一个Serializer来实现SerializerInterface


   // I keeped the default serializer, and just override his decode method.

   /**
     * {@inheritdoc}
     */
    public function decode(array $encodedEnvelope): Envelope
    {
        if (empty($encodedEnvelope['body']) || empty($encodedEnvelope['headers'])) {
            throw new InvalidArgumentException('Encoded envelope should have at least a "body" and some "headers".');
        }

        if (empty($encodedEnvelope['headers']['action'])) {
            throw new InvalidArgumentException('Encoded envelope does not have an "action" header.');
        }

        // Call a factory to return the Message Class associate with the action
        if (!$messageClass = $this->messageFactory->getMessageClass($encodedEnvelope['headers']['action'])) {
            throw new InvalidArgumentException(sprintf('"%s" is not a valid action.', $encodedEnvelope['headers']['action']));
        }

        // ... keep the default Serializer logic

        return new Envelope($message, ...$stamps);
    }

2-使用工厂检索正确的Message

class MessageFactory
{
    /**
     * @param string $action
     * @return string|null
     */
    public function getMessageClass(string $action)
    {
        switch($action){
            case ActionConstants::POST_MESSAGE :
                return PostMessage::class ;
            default:
                return null;
        }
    }
}

3)为Messenger配置新的自定义序列化程序:

framework:
  messenger:
    serializer: 'app.my_custom_serializer'

我将尝试进一步,找到一种直接“连接”队列的方法,这会让您知道。