bbit/async-dispatcher-bundle
Installation:
composer require bbit/async-dispatcher-bundle:2.5.0
Add to config/bundles.php:
return [
// ...
BBIT\AsyncDispatcherBundle\BBITAsyncDispatcherBundle::class => ['all' => true],
];
Enable Async Dispatcher:
Configure in config/packages/bbit_async_dispatcher.yaml:
bbit_async_dispatcher:
enabled: true
First Use Case: Dispatch an event asynchronously in a controller:
use BBIT\AsyncDispatcherBundle\AsyncDispatcherInterface;
use Symfony\Component\HttpKernel\KernelEvents;
public function someAction(AsyncDispatcherInterface $asyncDispatcher)
{
$asyncDispatcher->dispatch(new MyEvent(), KernelEvents::TERMINATE);
}
BBITAsyncDispatcherBundle for configuration options.AsyncDispatcherInterface for available methods.Symfony\Component\HttpKernel\KernelEvents constants for event timing.Dispatch Events Asynchronously:
$asyncDispatcher->dispatch($event, $eventName, $priority = 0);
KernelEvents::TERMINATE.Event Priorities: Use priorities to control dispatch order (higher priority = earlier dispatch):
$asyncDispatcher->dispatch($event, KernelEvents::TERMINATE, 100);
Integration with Symfony Events:
dispatcher->dispatch() with $asyncDispatcher->dispatch() for non-critical events.$asyncDispatcher->dispatch(new TrackUserEvent($user), 'user.track');
$asyncDispatcher->dispatch(new SendWelcomeEmailEvent($user), 'user.welcome_email');
foreach ($users as $user) {
$asyncDispatcher->dispatch(new ProcessUserEvent($user), 'user.process');
}
AsyncDispatcherInterface into services where async dispatch is needed.public static function getSubscribedEvents()
{
return [
'user.created' => ['onUserCreated', 0],
'user.created.async' => ['onUserCreatedAsync', 0], // Async variant
];
}
AsyncDispatcherInterface in tests to verify events are dispatched:
$mockDispatcher = $this->createMock(AsyncDispatcherInterface::class);
$this->container->set('async_dispatcher', $mockDispatcher);
Memory Leaks:
terminate. For long-running requests (e.g., CLI commands), clear the dispatcher manually:
$asyncDispatcher->clear();
Event Ordering:
Terminate Dependency:
KernelEvents::TERMINATE. If your app exits early (e.g., via exit() or exceptions), events may not dispatch.terminate is called or dispatch events synchronously.Thread Safety:
$events = $asyncDispatcher->getQueuedEvents();
// Debug $events to inspect pending dispatches.
$asyncDispatcher->setListener(function ($event) {
// Custom logic (e.g., log to Sentry).
});
enabled: false in config to disable async dispatch entirely (useful for testing).Custom Dispatcher:
Implement AsyncDispatcherInterface to replace the default behavior:
class CustomAsyncDispatcher implements AsyncDispatcherInterface {
public function dispatch($event, $eventName = null, $priority = 0) {
// Custom logic (e.g., database queue).
}
// ... other methods
}
Register it as a service:
services:
async_dispatcher:
class: App\Service\CustomAsyncDispatcher
Pre-Terminate Dispatch:
Trigger async events before terminate by listening to KernelEvents::TERMINATE and calling:
$asyncDispatcher->dispatchNow(); // Dispatches all queued events immediately.
Event Filters: Add a filter to exclude certain events:
$asyncDispatcher->addFilter(function ($event) {
return !str_starts_with($event->getName(), 'system.');
});
How can I help you explore Laravel packages today?