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

Eventsauce Messenger Laravel Package

andreo/eventsauce-messenger

Symfony Messenger integration for EventSauce. Dispatch and consume EventSauce messages via Messenger handlers, with optional autoconfiguration through the AsEventSauceMessageHandler attribute or manual service tagging. Requires PHP 8.2+ and Symfony Messenger 6.2+.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup for Laravel Integration

  1. Install Dependencies:

    composer require andreo/eventsauce-messenger symfony/messenger spatie/laravel-messenger
    
    • Use spatie/laravel-messenger as a bridge for Symfony Messenger in Laravel.
  2. Configure Symfony Messenger: Add to config/messenger.php:

    'buses' => [
        'eventBus' => [
            'default_middleware' => false,
            'middleware' => [
                'send_message',
                'Andreo\EventSauce\Messenger\Middleware\HandleEventSauceMessageMiddleware',
                'handle_message',
            ],
        ],
    ],
    
  3. Register EventSauce Dispatcher: In AppServiceProvider:

    public function register()
    {
        $this->app->bind('eventBus.messenger.handlers_locator', function ($app) {
            return new \Andreo\EventSauce\Messenger\HandlerLocator(
                $app->get('messenger.buses.eventBus.handlers_locator')
            );
        });
    
        $this->app->bind('eventBus.dispatcher', function ($app) {
            return new \Andreo\EventSauce\Messenger\Dispatcher\MessengerMessageDispatcher(
                $app->get('messenger.buses.eventBus'),
                'eventBus'
            );
        });
    }
    
  4. Create First Event Handler:

    use Andreo\EventSauce\Messenger\Attribute\AsEventSauceMessageHandler;
    use EventSauce\EventSourcing\EventConsumption\InflectHandlerMethodsFromType;
    
    class OrderCreatedHandler extends EventConsumer
    {
        use InflectHandlerMethodsFromType;
    
        #[AsEventSauceMessageHandler(bus: 'eventBus')]
        public function onOrderCreated(OrderCreated $event, Message $message): void
        {
            // Handle event logic
        }
    }
    
  5. Dispatch an Event:

    use EventSauce\EventSourcing\Message;
    
    $eventBus = $this->app->get('eventBus.dispatcher');
    $eventBus->dispatch(new Message(
        new OrderCreated('order-123', 'Product A'),
        new UniqueMessageId(),
        new MessageId(),
        new Timestamp()
    ));
    

Implementation Patterns

Workflows

1. Event-Driven Projections

  • Use EventSauce projections to populate Laravel models:
    #[AsEventSauceMessageHandler(bus: 'eventBus')]
    public function onOrderPaid(OrderPaid $event, Message $message): void
    {
        Order::query()->where('id', $event->orderId())
            ->update(['status' => 'paid', 'paid_at' => now()]);
    }
    

2. Union Type Handlers

  • Handle multiple event types in one consumer:
    #[AsEventSauceMessageHandler(bus: 'eventBus')]
    public function onInventoryEvent(InventoryUpdated|InventoryReserved $event, Message $message): void
    {
        if ($event instanceof InventoryUpdated) {
            // Handle update
        }
    }
    

3. Background Processing

  • Offload event handling to Laravel queues:
    # config/messenger.yaml
    buses:
      eventBus:
        middleware:
          - 'send_message'
          - 'Andreo\EventSauce\Messenger\Middleware\HandleEventSauceMessageMiddleware'
          - 'handle_message'
          - 'doctrine' # For transactions
          - 'laravel_queue' # Spatie's queue middleware
    

4. Event Retry Logic

  • Implement custom middleware for retries:
    use Andreo\EventSauce\Messenger\Middleware\HandleEventSauceMessageMiddleware;
    use Symfony\Component\Messenger\Middleware\RetryFailedMessagesMiddleware;
    
    $middleware = new HandleEventSauceMessageMiddleware(
        $handlersLocator,
        new RetryFailedMessagesMiddleware(
            $bus->getRetryStrategy(),
            $bus->getLogger()
        )
    );
    

Integration Tips

  • Laravel Service Container: Bind EventSauce components to Laravel’s container:

    $this->app->bind('eventsauce.event_store', function ($app) {
        return new \EventSauce\EventSourcing\EventStore(
            new \EventSauce\EventSourcing\Persistence\DoctrineEventRepository(
                $app->make(\Doctrine\DBAL\Connection::class)
            )
        );
    });
    
  • Event Serialization: Ensure EventSauce events are JSON-serializable:

    class OrderCreated implements \JsonSerializable
    {
        public function jsonSerialize(): array
        {
            return [
                'order_id' => $this->orderId,
                'product' => $this->product,
            ];
        }
    }
    
  • Testing: Mock the dispatcher in tests:

    $dispatcher = $this->app->make('eventBus.dispatcher');
    $dispatcher->shouldReceive('dispatch')
        ->once()
        ->withArgs(function ($message) {
            return $message->message() instanceof OrderCreated;
        });
    

Gotchas and Tips

Pitfalls

  1. Middleware Order:

    • Place HandleEventSauceMessageMiddleware before handle_message in Symfony Messenger’s pipeline to ensure events are processed by EventSauce consumers.
  2. Autoconfiguration:

    • If using attributes, ensure RegisterEventSauceMessageHandlerAttribute::register() is called before Symfony’s autowiring kicks in. In Laravel, this may require a custom Kernel or AppServiceProvider extension.
  3. Event Class Naming:

    • EventSauce expects fully qualified class names (e.g., App\Events\OrderCreated). Ensure Laravel’s autoloader includes these paths.
  4. Queue Workers:

    • Laravel’s queue:work must be configured to use the eventBus:
      php artisan queue:work --queue=eventBus
      
  5. Transaction Boundaries:

    • EventSauce projections may conflict with Laravel’s transactions. Use doctrine middleware for transaction management:
      middleware:
        - 'doctrine'
        - 'Andreo\EventSauce\Messenger\Middleware\HandleEventSauceMessageMiddleware'
      

Debugging

  • Handler Not Found:

    • Verify the handles tag in YAML or the attribute’s bus parameter matches the Symfony Messenger bus alias (eventBus).
    • Check var/dump($container->has('eventBus.messenger.handlers_locator')) in a Laravel Tinker session.
  • Event Not Dispatched:

    • Ensure the MessengerMessageDispatcher is bound to the container and injected correctly:
      $dispatcher = $this->app->make('eventBus.dispatcher');
      $dispatcher->dispatch($message);
      
  • PHP 8.2 Attributes:

    • If using PHP 8.1 or lower, manually register handlers via YAML or a compiler pass.

Extension Points

  1. Custom HandleMethodInflector: Override the default inflector for custom event-to-method mapping:

    use EventSauce\EventSourcing\EventConsumption\HandleMethodInflector;
    
    class CustomInflector implements HandleMethodInflector
    {
        public function inflect(string $eventClass): string
        {
            return 'handle' . str_replace('\\', '_', $eventClass);
        }
    }
    
  2. Middleware Decorators: Extend HandleEventSauceMessageMiddleware to add pre/post-processing:

    class LoggingMiddleware extends HandleEventSauceMessageMiddleware
    {
        public function handle(Message $message, callable $next)
        {
            \Log::info('Processing event', ['event' => $message->message()]);
            return parent::handle($message, $next);
        }
    }
    
  3. EventSauce Event Store: Replace the default event store with a custom implementation:

    $eventStore = new \EventSauce\EventSourcing\EventStore(
        new \EventSauce\EventSourcing\Persistence\CustomEventRepository()
    );
    $this->app->bind('eventsauce.event_store', fn() => $eventStore);
    

Laravel-Specific Quirks

  • Service Provider Booting: Ensure the RegisterEventSauceMessageHandlerAttribute is registered after Laravel’s service providers but before Symfony Messenger initializes. Use booted in AppServiceProvider:

    protected function boot()
    {
        if ($this->app->has('kernel')) {
            $this->app['kernel']->registerAttribute();
        }
    }
    
  • Queue Middleware: Spatie’s laravel-messenger may conflict with Symfony’s middleware. Explicitly configure the eventBus to use Laravel’s queue:

    buses:
      eventBus:
        middleware:
          - 'send_message'
          - 'Andreo\EventSauce\Messenger\Middleware\
    
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.
bugban/symfony
beyonder-capi/workflow-extensions-bundle
beyonder-capi/job-queue-bundle
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin