Symfony Messenger:使用消息接口作为处理程序时重试失败的消息__invoke type-hint
Posted
技术标签:
【中文标题】Symfony Messenger:使用消息接口作为处理程序时重试失败的消息__invoke type-hint【英文标题】:Symfony Messenger: Retrying failed messages when using a message interface as the handler __invoke type-hint 【发布时间】:2020-12-08 09:53:25 【问题描述】:我在 Symfony 4.4 应用程序中使用 Symfony Messenger 组件。我正在通过 RabbitMQ 异步处理消息,并通过 Doctrine 传输将失败的消息存储在数据库中。
这是信使配置:
framework:
messenger:
failure_transport: failed
buses:
command_bus:
middleware:
- doctrine_ping_connection
transports:
failed: 'doctrine://default?queue_name=failed'
async_priority_high:
dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
retry_strategy:
delay: 2000
max_retries: 5
multiplier: 2
options:
exchange:
name: high
queues:
messages_high: ~
async_priority_low:
dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
retry_strategy:
delay: 3000
max_retries: 3
multiplier: 2
options:
exchange:
name: low
queues:
messages_low: ~
routing:
'App\SampleMessageButHighPriority': async_priority_high
'App\SampleMessageInterface': async_priority_low
'App\OtherMessage': async_priority_low
这是一个示例处理程序,它处理实现SampleMessageInterface
接口的消息。
final class SampleMessageHandler implements MessageHandlerInterface
private ProjectRepository $projectRepository;
public function __construct(ProjectRepository $projectRepository)
$this->projectRepository = $projectRepository;
public function __invoke(SampleMessageInterface $message): void
$project = $this->projectRepository->find($message->getProjectId()->toString());
if ($project === null)
return;
$this->someProcessor->__invoke($project);
在遇到任何消息失败之前一切正常。尝试重试或显示失败消息时,问题在失败后开始显示。让我们试试php bin/console messenger:failed:show
命令:
结果:
In PhpSerializer.php line 64:
Cannot instantiate interface App\SampleMessageInterface
我猜Symfony需要反序列化失败的消息,之前序列化并存储在数据库中,但是因为它是一个接口,所以不能这样做。
我该如何解决这个问题?有没有办法使用类实现而不是接口来序列化失败的消息?
【问题讨论】:
请不要将代码放入图片中。使用```code``来发布你的格式化代码 对此我很抱歉,我刚刚更新了我的问题。谢谢你告诉我。 github.com/opengento/magento2-gdpr/issues/43 这里说这是一个缓存问题。也许您已经尝试清理缓存?你为什么用final
这个关键词?
Doc : symfony.com/doc/current/… 没有使用final关键字
可能的帮助下一个配置:``` messenger serializer: default_serializer: "messenger.transport.symfony_serializer" ``` 为我工作。在 4.2 中有它,但是在 4.4 之后(可能更早,没有检查),它默认更改为 phpSerializer。所以只需设置它,应该可以工作
【参考方案1】:
失败的消息被序列化地存储在数据库中。当您重试或显示这些消息时,它们会被反序列化。
只需将接口SampleMessageInterface
替换为类SampleMessage
。
【讨论】:
但是我怎样才能从只创建一个处理程序来处理所有SampleMessageInterface
消息中受益呢?或者这是不可能的,我应该开始为每个SampleMessageInterface
实现创建一个处理程序?
可以,但看起来 Messenger 的传输失败功能中存在错误。您能否检查一下包含失败消息的数据库并说出headers
列中的type
是什么?是SampleMessageInterface
还是别的什么?
它是SampleMessageInterface
,所以我想这就是为什么它无法反序列化到发送的消息实施。我不知道这是一个错误还是预期的行为。
我认为这是一个错误。使用实际的类名而不是接口名进行序列化应该不是问题。
我刚刚报道了,让我们看看Symfony的人怎么说。谢谢!以上是关于Symfony Messenger:使用消息接口作为处理程序时重试失败的消息__invoke type-hint的主要内容,如果未能解决你的问题,请参考以下文章
Symfony Messenger 如何确定应由哪个处理程序处理每种类型的消息?
在 Symfony Messenger 异步消息处理程序上使用选民/权限的最佳方式? [关闭]
使用 RMQ 在 Symfony Messenger 中处理来自不同命名空间的消息
Symfony Messenger 4.3 - 从理论传输中消费消息失败(抛出异常)