Symfony: send failed messages via email
Asked Answered
I

2

6

I have a simple messanger config:

framework:
    messenger:
        failure_transport: failed
        transports:
            async:
                dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
                retry_strategy:
                    max_retries: 2
                    delay: 10000
            failed: 'doctrine://default?queue_name=failed'

        routing:
            someInterface: async

I would like to know about every message routed to failed transport f.e. system should send email notification to me when message is redirecting. My only idea is to periodically review messenger_messages table which contains messages stored in failed transport but imao it's not symfony-way solution. Do you know more clever solution for this feature?

I am using symfony/messenger with version 5.*

Iridaceous answered 28/5, 2020 at 16:22 Comment(0)
I
11

Ultimately, I applied the solution below:

<?php
/**
 * Author: writ3it
 */

namespace App\Maintenance\Messenger;


use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Messenger\Event\WorkerMessageFailedEvent;
use Symfony\Component\Messenger\MessageBusInterface;

class FailedMessageListener implements EventSubscriberInterface
{

    /**
     * @var MessageBusInterface
     */
    private MessageBusInterface $bus;

    public function __construct(MessageBusInterface $bus)
    {
        $this->bus = $bus;
    }

    public function onMessageFailed(WorkerMessageFailedEvent $event)
    {
        if ($event->willRetry()) {
            return;
        }
        $envelope = $event->getEnvelope();
        $message = $envelope->getMessage();

        $subject = sprintf("Message added to failed transport. Message: %s", \get_class($message));
        $content = serialize($message);

        $notification = new FailedMessageNotificationEvent();
        $notification->setSubject($subject)
            ->setContent($content);
        $this->bus->dispatch($notification);
    }

    /**
     * @return array
     */
    public static function getSubscribedEvents()
    {
        return [
            WorkerMessageFailedEvent::class => ['onMessageFailed', -256],
        ];
    }
}

FailedMessageNotificationEvent is a message that will be caught by my mailing handler. The FailedMessageListener class should be tagged as kernel.event_subscriber or autoconfigured.

I didn't use middleware because messenger sends messages to the failed transport directly, without middlewares.

Iridaceous answered 17/8, 2020 at 8:7 Comment(3)
Hey, thank you for your solution, could specify why -90 as priority on your event listener ?Mat
This should be marked as the correct answer, it will help more people in the future.Torquay
@Famas23 Today, I have no idea :) I think, the best choice is -256 (or less) because Symfony is using range +/-256 internally and this subscriber should be executed as last.Iridaceous
M
0

I don't think it's possible to do it through configuration, but you create your custom middleware and send email by yourself. https://symfony.com/doc/current/messenger.html#middleware

You can check FailedMessageProcessingMiddleware for reference https://github.com/symfony/messenger/blob/master/Middleware/FailedMessageProcessingMiddleware.php

Musicology answered 28/5, 2020 at 17:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.