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