0

I am using bugsnag in a symfony 5 project to keep track of exeptions. I also use symfony messenger with rabbit for heavy processing.

Everything works fine overall, except the fact that in some cases, inside a messenger middleware (RejectRedeliveredMessageMiddleware) an exception is thrown in some particular cases in order to trigger a message reque while avoiding a possible infinite loop (RejectRedeliveredMessageException).

The exception should be there, and the behavior is correct. For example if a process stopped unexpectedly (a hard reboot or a kill), the message is requed. The logic works well, autorecovery works perfectly.

The only problem is that bugsnag registers itself as a subscriber for all kernel events, treated or not (code below)

$listeners = [
    KernelEvents::REQUEST => ['onKernelRequest', 256],
    KernelEvents::EXCEPTION => ['onKernelException', 128],

];

Normally exceptions are caught in our app before getting to the general event dispatcher and so they are not reported if they shouldn't. But, because that is in the middleware, and an event is risen it gets reported even though is already treated by the autoretry mechanism and because of that it generates a lot of noise and fake positives.

What I would need to do is unsubscribe for a particular event, but since I can't touch the 3rd party code (bugsnag and messenger) I can't find a way to do it.

Is there a way to programatically remove an event from a subscriber?

zozo
  • 8,230
  • 19
  • 79
  • 134

2 Answers2

1

Inject EventDispatcherInterface and use removeSubscriber() method. You can do this in you custom middleware https://symfony.com/doc/current/messenger.html#middleware

Leprechaun
  • 759
  • 5
  • 14
  • 1
    This would require to be sure that my particular middleware is called before the middleware that trows the exception. I am investigating to see if that is possible. – zozo May 28 '20 at 20:25
0

It's hard to tell if this would work, but it's an angle - when you detect your Event is handled properly, you could invoke $event->stopPropagation(), perhaps from your own listener, which should: "... tell the dispatcher to stop all propagation of the event to future listeners (i.e. to not notify any more listeners)"

https://symfony.com/doc/current/components/event_dispatcher.html#stopping-event-flow-propagation

domagoj
  • 906
  • 1
  • 8
  • 20
  • The stop propagation is only available for listeners, since there is no way to insure subscriber order (at least I don't see any, I may have missed something but don't think so). – zozo May 28 '20 at 20:27
  • It's probably only possible if they use `priority` tag for their subscribers - you could then use your own listener with certain priority and then decide to stop the propagation. You could, perhaps, check this bit of documentation to see how you can override service definition for their subscribers using CompilerPass or service decoration - whichever suits you better: https://symfony.com/doc/current/bundles/override.html#services-configuration – domagoj May 29 '20 at 07:55