Configuration
The configuration for this bridge is defined under the messageBus
namespace for the Laminas\ConfigAggregator
.
It holds multiple path variables, mapping arrays and a failure transport definition.
Any message that is apssed through a messenger middleware or through a command (working asynchronously) will be logged
with the Monolog library. Some of the Symfony commands to handle
the worker need a cache. Both of these paths can be defined with following configuration. The default configuration
will store files in the data/cache/message-bus
and data/logs/message-bus
directories.
'messageBus' => [
'logPath' => dirname(__DIR__, 2).'/data/logs/message-bus',
'cachePath' => dirname(__DIR__, 2).'/data/cache',
// ...
],
Transports
A ‘transport’ defines the channels, where asynchronous messages can be send to. This can be a database and delegated via Doctrine, a Redis instance or a RabbitMQ. Maybe more to come. To define multiple channels, simply create multiple DSNs within this configuration.
'messageBus' => [
'transportDSNs' => [
// name => DSN,
'default' => 'amqp://guest:password@rabbitmq.tld:5672/%2f/default',
'failure' => 'amqp://guest:password@rabbitmq.tld:5672/%2f/failure',
'doctrine' => 'doctrine://guest:password@mariadb10:3306/default',
'redis' => 'redis://redis5:6379/default',
],
// ...
],
For each configured transport DSN, a service named Transport::$name
will be added to the service container, holding
an instance of Symfony\Component\Messenger\Transport\TransportInterface
with the necessary connection to the broker.
To get a transport from the container, you can either pass the string - e.g. Transport::default
- or use the helper
MessageBus\Factory\Transporthelper::createTransportName($name)
for the $container->get(...)
instruction.
One of those transports should be defined as the ‘failure transport’. Symfony messenger will put any message that has failed 3 times onto this transport. It also offers commands to display and retry failed messages or remove them savely. This transport does not have to be named ‘failure’.
'messageBus' => [
'failureTransport' => MessageBus\Factory\TransportHelper::createTransportName('failure'),
// ...
],
Delegating the messages
Each message needs a ‘Worker’ to handle it. You can find out more in the “How to use the bridge” section or in the Symfony documentation. The bridge handles the associations via array maps, defining message to worker(s) and message to transport(s). You can pass a string or array as value.
'messageBus' => [
// ...
'handlersLocatorMap' => [
App\Worker\ImportantSyncMessage::class => [App\Worker\ImportantWorker::class],
App\Worker\UnimportantAsyncMessage::class => App\Worker\UnimportantWorker::class,
],
'sendersLocatorMap' => [
App\Worker\UnimportantAsyncMessage::class => 'Transport::default',
],
// ...
],
A message not listed in the ‘sendersLocatorMap’ will be handle synchronously on request.
Custom middlewares
As described in the official Symfony docs, you can define
custom middlewares by adding classes that implement the MiddlewareInterface
. To add your custom middlewares in
Mezzio, create such a class and use the factory method, to configure this service in Psr\Container
.
class MyMiddleware implements MiddlewareInterface
{
private MyService $service;
public function __construct(MyService $service)
{
$this->service = $service;
}
public function handle(Envelope $envelope, StackInterface $stack): Envelope
{
// implement you middleware
return $stack->next()->handle($envelope, $stack);
}
}
class ConfigProvider
{
public function __invoke(): array
{
return [
'dependencies' => $this->getDependencies(),
];
}
public function getDependencies(): array
{
return [
'factories' => [
MyMiddleware::class => MyMiddlewareFactory::class,
//...
],
];
}
//...
}
Then add the middleware class to messenger configuration:
'messageBus' => [
// ...
# define custom middlewares
'customMiddlewares' => [
MyMiddleware::class,
],
],