0

I need to have multiple bus in my application written on Symfony. To do so I'm using messenger bundle.

So I need to have:

  • external_events_bus - which receiving messages from external systems, which using sqs transport
  • application_events_bus - for application events (using database driver for now)
  • domain_events_bus - for domain events (using database driver for now)
  • command_bus - for commands and queries (CQRS) (currently sync)

so in my messenger.yaml I have:

framework:
    messenger:
        default_bus: command.bus
        buses:
            command.bus: ~
            domain_event.bus: ~
            application_event.bus: ~
            external_event.bus: ~
        transports:
            command_bus: '%env(COMMAND_BUS_DSN)%'
            internal_event_bus: '%env(INTERNAL_EVENT_BUS_DSN)%'
            external_event_bus: '%(EXTERNAL_EVENT_BUS_DSN)%'
        routing:
            'App\Application\CommandBus\Command': command_bus
            'App\Domain\EventBus\DomainEvent': internal_event_bus
            'App\Application\EventBus\ApplicationEvent': internal_event_bus
            'App\Infrastructure\ExternalEventBus\ExternalEvent': external_event_bus

and in my services.yaml

services:
    _defaults:
        autowire: true      
        autoconfigure: true subscribers, etc.
        public: false
    _instanceof:
        # use tags to avoid coupling handler classes to Messenger's interface
        App\Application\CommandBus\CommandHandler:
            tags: [ { name: messenger.message_handler, bus: command.bus } ]
        App\Interfaces\ExternalEventBus\ExternalEventHandler:
            tags: [ { name: messenger.message_handler, bus: external_event.bus } ]
        App\Domain\EventBus\DomainEventHandler:
            tags: [ { name: messenger.message_handler, bus: domain_event.bus } ]
        App\Application\EventBus\ApplicationEventHandler:
            tags: [ { name: messenger.message_handler, bus: application_event.bus } ]

     ... // some other services here

    App\Application\CommandBus\CommandBus:
        class: App\Infrastructure\CommandBus\CommandBus
        arguments: [ "@command.bus" ]

    App\Domain\EventBus\DomainEventBus:
        class: App\Infrastructure\DomainEventBus\DomainEventBus
        arguments: [ "@domain_event.bus" ]

    App\Application\EventBus\ApplicationEventBus:
        class: App\Infrastructure\ApplicationEventBus\ApplicationEventBus
        arguments: [ "@application_event.bus" ]

    App\Infrastructure\ExternalEventBus\ExternalEventBus:
        class: App\Infrastructure\ExternalEventBus\ExternalEventBus
        arguments: [ "@external_event.bus" ]

Want to clarify before I had only command bus and external bus and all was fine, but after I added domain and application bus, somethinkg went wrong.

When in tests I'm using ExternalEventBus, to test if external event handled correctly, like this:

    $this->eventBus = self::$container->get(PlatformEventBus::class);
    $this->eventBus->dispatch(new SomeExternalEvent());

I'm getting error like

Symfony\Component\Messenger\Exception\NoHandlerForMessageException: No handler for message "SomeExternalEvent".

but when I'm running bin/console debug:messenger for both dev and test env, I can see correct mapping between all events and their handlers.

But when I'm debugging it can see that HandlersLocator::getHandlers() for that SomeExternalEvent for some reason returning list of handlers related to command bus instead of external event bus (maybe because command bus set as a default bus)

I know it's a bit hard to explaing and show topic, but I spend already whole day truing to find what is wrong with it. Any help appreciated, thank you!!!

Sorry for any kind of typos, I'm a bit change name of classes for this example and may did some typos

Bogdan Dubyk
  • 4,756
  • 7
  • 30
  • 67
  • as I told, it uses command bus as it's set as a default one, if i set `external_event.bus` as a default bus, tests passing... but why it's not guessing bus correctly? – Bogdan Dubyk Jul 31 '21 at 12:21
  • okay, I figured it out, messenger using autowireing when you injecting `MessageBusInterface` depends on variable name, so in case of external event bus it should be `externalEventBus` and same for other buses. But I do not understand how it worked before, as I mentioned I have command and external bus for a while and it stop working only when I add more buses... – Bogdan Dubyk Jul 31 '21 at 12:53

1 Answers1

0

okay, I figured it out, messenger using autowiryng when you injecting MessageBusInterface depends on variable name, so in case of external event bus it should be $externalEventBus and same for other buses. But I do not understand how it worked before, as I mentioned I have command and external bus for a while and it stop working only when I add more buses...

Bogdan Dubyk
  • 4,756
  • 7
  • 30
  • 67