Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom exception from Messenger handler

I try Symfony 4.3.0-dev version to get some new features from Messenger component. My command bus works in sync mode.

Before upgrading I could easily throw my custom exception ConflictException from handler. But for 4.3.0-dev I get a Symfony\Component\Messenger\Exception\HandlerFailedException.

How can I catch my custom exception again?

like image 923
akor Avatar asked Oct 19 '25 03:10

akor


1 Answers

Starting with Symfony 4.3, if a handler throws any exception, it will be wrapped in a Symfony\Component\Messenger\Exception\HandlerFailedException.

This is reflected here in the changelog:

[BC BREAK] A HandlerFailedException exception will be thrown if one or more handler fails.

In places where you are dealing with a synchronous transport and you want to deal with the original exception, you can do something similar to what Api-Platform does in this DispatchTrait:

namespace App\Infrastructure\Messenger;

use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\Exception\HandlerFailedException;
use Symfony\Component\Messenger\MessageBusInterface;
use Throwable;

trait DispatchTrait
{

    private ?MessageBusInterface $messageBus;

    /**
     * @param object|Envelope $message
     * @return Envelope
     * @throws Throwable
     */
    private function dispatch($message): ?Envelope
    {
        try {
            return $this->messageBus->dispatch($message);
        } catch (HandlerFailedException $e) {
            while ($e instanceof HandlerFailedException) {
                /** @var Throwable $e */
                $e = $e->getPrevious();
            }

            throw $e;
        }
    }
}

(This version has no backwards compatibility, and does away with the MessageBus check, since I'm only using for internal applications I'm in control of).

In whatever class you are dispatching your message, you could do:

class FooController
{
    use DispatchTrait;

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

    public function __invoke(Request $request)
    {
        // however you create your message
        $command = Command::fromHttpRequest(); 

        try {
                $this->dispatch($command);
        }
        catch (ConflictException $e) {
            // deal with the original exception
        }
    }
}
like image 195
yivi Avatar answered Oct 21 '25 16:10

yivi