我正在尝试读取未通过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'
答案 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'
我将尝试进一步,找到一种直接“连接”队列的方法,这会让您知道。