bodaclick/async-dispatcher-bundle
Installation Add the bundle via Composer:
composer require bodaclick/async-dispatcher-bundle
Register the bundle in config/bundles.php:
return [
// ...
Bodaclick\AsyncDispatcherBundle\AsyncDispatcherBundle::class => ['all' => true],
];
Configuration Publish the default config:
php bin/console config:dump-reference Bodaclick\AsyncDispatcherBundle\Configuration
Configure the queue connection in config/packages/async_dispatcher.yaml:
async_dispatcher:
queue_connection: 'sync' # or 'database', 'redis', etc.
queue_name: 'async_events'
First Use Case Dispatch an event asynchronously in a controller or service:
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Bodaclick\AsyncDispatcherBundle\AsyncDispatcher;
class MyController extends AbstractController
{
public function __construct(
private AsyncDispatcher $asyncDispatcher
) {}
public function handleEvent()
{
$event = new MyEvent();
$this->asyncDispatcher->dispatch($event); // Async dispatch
}
}
Event Dispatching
Replace synchronous EventDispatcherInterface with AsyncDispatcher for non-critical events:
$this->asyncDispatcher->dispatch(new UserRegisteredEvent($user));
Queue Integration
Configure the bundle to use a queue driver (e.g., database, redis):
async_dispatcher:
queue_connection: 'redis'
queue_name: 'async_events'
Ensure the queue worker is running:
php bin/console messenger:consume async_events -vv
Event Listeners
Register listeners as usual in services.yaml or via annotations:
services:
App\EventListener\MyEventListener:
tags:
- { name: 'kernel.event_listener', event: 'app.my_event', method: 'onMyEvent' }
Batching Events For high-volume events, batch them to reduce queue overhead:
$this->asyncDispatcher->dispatchBatch([$event1, $event2, $event3]);
AsyncDispatcher in tests to avoid real queue interactions:
$this->asyncDispatcher = $this->createMock(AsyncDispatcher::class);
$this->asyncDispatcher->method('dispatch')->willReturn(true);
Queue Worker Requirement
php bin/console messenger:consume async_events --time-limit=300
Synchronous Fallback
config/packages/async_dispatcher.yaml:
async_dispatcher:
fallback_on_failure: false # Set to true to throw exceptions
Event Serialization
Serializable or use __serialize()/__unserialize():
class MyEvent implements Serializable {
public function serialize() { /* ... */ }
public function unserialize($data) { /* ... */ }
}
Database Queue Limitations
doctrine) may struggle with high event volumes.php bin/console messenger:failed:list
php bin/console messenger:consume async_events --time-limit=1
async_dispatcher:
debug: true
Custom Queue Handlers
Extend the bundle’s AsyncDispatcher to support custom queue logic:
class CustomAsyncDispatcher extends AsyncDispatcher {
protected function getQueueConnection(): ConnectionInterface {
return new CustomQueueConnection();
}
}
Event Filtering
Filter events before dispatching by overriding the dispatch() method:
$this->asyncDispatcher->setFilter(function ($event) {
return $event instanceof AllowedEvent;
});
Middleware Add middleware to the queue (Symfony Messenger style):
framework:
messenger:
transports:
async_events:
dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
options:
middleware: [validate_event, log_event]
How can I help you explore Laravel packages today?