Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Async Dispatcher Bundle Laravel Package

bbit/async-dispatcher-bundle

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture Fit

  • Event-Driven Workflow: The bundle aligns well with Symfony/Laravel applications requiring asynchronous event dispatching (e.g., background jobs, deferred processing, or decoupled services). It bridges the gap between immediate event handling and delayed execution by buffering events until kernel.terminate.
  • Symfony Ecosystem: Designed for Symfony (via bundles), but can be adapted for Laravel via Symfony Bridge or Lumen (if kernel lifecycle is compatible). Requires manual integration for vanilla Laravel due to differing event dispatchers.
  • Use Cases:
    • Deferred Processing: Offload heavy tasks (e.g., analytics, notifications) post-request.
    • Decoupled Services: Fire events to external systems (e.g., queues, APIs) without blocking the response.
    • Testing: Simulate async behavior in synchronous tests by replaying buffered events.

Integration Feasibility

  • Low Coupling: Leverages Symfony’s EventDispatcher interface, making it pluggable into Laravel via:
    • Symfony Bridge: Use symfony/event-dispatcher + symfony/http-kernel in Laravel.
    • Wrapper Layer: Create a Laravel-specific facade to translate between Laravel’s Events and Symfony’s EventDispatcher.
  • Dependencies:
    • Requires Symfony Components (e.g., EventDispatcher, HttpKernel), which are compatible with Laravel via Composer.
    • No database or external service dependencies (self-contained).

Technical Risk

  • Laravel Compatibility:
    • High Risk: Laravel’s event system (Illuminate\Events\Dispatcher) differs from Symfony’s. Direct integration may require custom event listeners or a proxy dispatcher.
    • Mitigation: Abstract Symfony’s EventDispatcher behind an interface to allow swapping implementations.
  • Stale Codebase:
    • Last release: 2016. Risk of deprecated Symfony versions (e.g., PSR-15, Symfony 6+ changes).
    • Mitigation: Fork and modernize if critical, or use as inspiration for a custom solution.
  • Thread Safety:
    • Events are buffered in-memory until kernel.terminate. Not thread-safe in multi-process environments (e.g., Laravel Horizon).
    • Mitigation: Use a queue-backed buffer (e.g., Redis) for distributed setups.

Key Questions

  1. Why Async?
    • Are events truly non-blocking (e.g., analytics) or idempotent (retry-safe)?
    • Could Laravel’s queues or jobs suffice instead?
  2. Symfony vs. Laravel:
    • Is the team already using Symfony components? If not, what’s the cost of abstraction?
  3. Failure Modes:
    • How are unhandled exceptions in async events logged/monitored?
    • What’s the recovery strategy if kernel.terminate fails (e.g., crashes)?
  4. Alternatives:
    • Compare with:
      • Laravel’s native queue:work + delayed jobs.
      • spatie/laravel-async-jobs.
      • Symfony’s Messenger component (if migrating to Symfony).

Integration Approach

Stack Fit

  • Laravel Compatibility:
    • Option 1: Symfony Bridge (Recommended for existing Symfony users):
      • Install symfony/event-dispatcher, symfony/http-kernel.
      • Use Symfony\Component\HttpKernel\HttpKernelInterface to hook into terminate.
      • Example:
        // app/Providers/EventServiceProvider.php
        public function boot()
        {
            $dispatcher = new Symfony\Component\EventDispatcher\EventDispatcher();
            $dispatcher->addListener('kernel.terminate', function () {
                // Flush buffered events via AsyncDispatcherBundle
            });
        }
        
    • Option 2: Laravel Facade Wrapper:
      • Create a AsyncDispatcher facade that adapts Laravel’s Events to Symfony’s EventDispatcher.
      • Example:
        class AsyncDispatcher implements AsyncDispatcherInterface {
            public function dispatch($event) {
                // Buffer event for later dispatch
            }
        }
        
  • Dependencies:
    • Required:
      • symfony/event-dispatcher (^6.0).
      • symfony/http-kernel (for terminate hook).
    • Optional:
      • psr/log for error handling.

Migration Path

  1. Phase 1: Proof of Concept
    • Integrate the bundle in a non-production environment.
    • Test with critical events (e.g., user signups) to validate async behavior.
    • Compare performance vs. synchronous dispatch.
  2. Phase 2: Abstraction Layer
    • If using Laravel, build a wrapper class to hide Symfony dependencies.
    • Example:
      class LaravelAsyncDispatcher {
          private $symfonyDispatcher;
      
          public function __construct() {
              $this->symfonyDispatcher = new Symfony\Component\EventDispatcher\EventDispatcher();
              // Register AsyncDispatcherBundle listeners
          }
      
          public function dispatchLaravelEvent($event) {
              $this->symfonyDispatcher->dispatch(new SymfonyEvent($event));
          }
      }
      
  3. Phase 3: Rollout
    • Gradually replace synchronous event listeners with async variants.
    • Monitor event processing lag and failure rates.

Compatibility

  • Symfony Versions:
    • Bundle targets Symfony 2.7–3.x. Test with:
      • symfony/event-dispatcher:^6.0 (PSR-15 compatible).
      • symfony/http-kernel:^6.0.
  • Laravel Versions:
    • Works with Laravel 8+ (PHP 7.4+) via Symfony Bridge.
    • Laravel 7: May require polyfills for Symfony 6+.
  • Event Format:
    • Symfony events must implement Symfony\Component\EventDispatcher\Event. Laravel events (Illuminate\Contracts\Events\Dispatcher) need adaptation.

Sequencing

  1. Install Dependencies:
    composer require symfony/event-dispatcher symfony/http-kernel bbit/async-dispatcher-bundle
    
  2. Configure Bundle (Symfony):
    # config/bundles.php
    return [
        BBIT\AsyncDispatcherBundle\BBITAsyncDispatcherBundle::class => ['all' => true],
    ];
    
  3. Laravel Setup:
    • Bind the dispatcher in a service provider:
      $this->app->singleton('asyncDispatcher', function ($app) {
          $dispatcher = new Symfony\Component\EventDispatcher\EventDispatcher();
          $dispatcher->addSubscriber(new AsyncDispatcherSubscriber());
          return $dispatcher;
      });
      
  4. Dispatch Events:
    • Replace event(new MyEvent()) with:
      app('asyncDispatcher')->dispatch(new SymfonyEvent(new MyEvent()));
      

Operational Impact

Maintenance

  • Pros:
    • Minimal Boilerplate: Bundle handles buffering/dispatching logic.
    • Symfony Ecosystem: Leverages battle-tested components.
  • Cons:
    • Stale Codebase: No updates since 2016. Requires monitoring for Symfony breaking changes.
    • Debugging Complexity:
      • Async events may fail silently (e.g., unhandled exceptions in terminate).
      • Solution: Add logging middleware to track buffered events.
    • Testing:
      • Async behavior requires mocking kernel.terminate in unit tests.
      • Example:
        $kernel = $this->createMock(HttpKernelInterface::class);
        $kernel->expects($this->once())->method('terminate');
        

Support

  • Documentation:
    • Limited: README lacks Laravel-specific guidance.
    • Action: Create internal docs for:
      • Event adaptation patterns.
      • Debugging async failures.
  • Community:
    • No active maintainers. Issues may go unanswered.
    • Mitigation: Engage with Symfony/Laravel communities for alternatives.
  • Vendor Lock-in:
    • Low risk if wrapped behind an interface, but forking may be necessary for long-term use.

Scaling

  • Performance:
    • In-Memory Buffer: Safe for single-process apps (e.g., PHP-FPM).
    • Multi-Process (Horizon/Queues):
      • Risk: Events may be lost if terminate fails before flushing.
      • Solution: Use a persistent queue (e.g., Redis) as the buffer.
    • Throughput:
      • Benchmark against Laravel’s native queues. AsyncDispatcherBundle adds minimal overhead (~1–5ms per event).
  • Horizontal Scaling:
    • Stateless: Works in scaled environments if events are idempotent.
    • Stateful: If buffering events per request, ensure no race conditions in distributed setups.

**Failure

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle