Weave 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

Broadway Saga Laravel Package

micro-module/broadway-saga

Micro Module Broadway Saga brings saga orchestration to Laravel applications using Broadway, helping you coordinate multi-step business workflows across domain events with event-sourced state and clean service-provider integration.

View on GitHub
Deep Wiki
Context7

Getting Started

This package is a thin Laravel adapter around broadway/broadway's saga subsystem (broadway/saga). It does not give you event sourcing — it assumes you already have a Broadway EventBus and CommandBus bound in the container. Treat it as glue, not a framework.

Steps to get productive:

  1. Read the package surface first. Before writing a saga, open:
    • composer.json — confirms which broadway/* version it pins (this dictates the event/command API you code against).
    • src/ — usually one ServiceProvider (e.g. BroadwaySagaServiceProvider) and a config file.
    • config/ — where sagas are registered and where the saga-state repository is chosen.
    • database/migrations/ (if present) — the saga_state table.
  2. Install and publish:
    composer require micro-module/broadway-saga
    php artisan vendor:publish --provider="MicroModule\\BroadwaySaga\\BroadwaySagaServiceProvider"
    php artisan migrate
    
  3. Verify the wiring. Resolve the saga manager from the container (app(SagaManager::class) or whatever the provider aliases) and confirm it is attached to the same event bus your domain publishes to. If your EventBus is a separate binding, the saga will silently never fire.
  4. First use case — a classic order saga. Define one saga that listens for OrderPlaced and issues a ReserveStock command, then listens for StockReserved/StockReservationFailed to either proceed or compensate:
    class OrderSaga extends AbstractSaga
    {
        public function handleOrderPlaced(OrderPlaced $event): void
        {
            $this->commandBus->dispatch(new ReserveStock($event->orderId, $event->items));
        }
    }
    
    Register it in config/broadway-saga.php (or the provider's saga list), migrate, and publish a test event. If nothing happens, that's the event-bus binding issue above, not your saga.

Implementation Patterns

Saga-per-process, correlated by ID. Give each saga a stable getSagaId() derived from the aggregate/order ID. The manager uses it to load the persisted state before handing the event to the handler, so a second OrderPlaced for the same order resumes rather than replays.

Command dispatch from handlers. Sagas should only react and dispatch commands — keep business rules in command handlers, keep the saga as orchestration. Long if/else inside a saga handler is the first smell.

Compensation with explicit state flags. Persist step markers on the saga (or rely on SagaState) so a failure event can branch to a compensating command. This is the whole point of using a saga over a plain event listener.

Registering sagas.

  • Config-driven list (sagas => [OrderSaga::class, ...]) is the normal path in these adapters; resolve via the container so dependencies inject.
  • If the package exposes a SagaManager::addSaga(), you can also register in a boot() method in your own provider — useful when saga registration needs runtime config.

Async processing. If your Broadway event bus is queued, sagas run in the worker. Ensure the saga-state repository is a real database repository (not in-memory) so state survives between jobs. Bind your own SagaRepository if the package's default is not durable.

Testing with Scenario. Broadway ships Broadway\Saga\Testing\Scenario:

Scenario::forSaga(new OrderSaga($commandBus))
    ->when(new OrderPlaced(...))
    ->then(new ReserveStock(...));

This is the fastest feedback loop and avoids booting Laravel at all — use it before the integration test.

Gotchas and Tips

  • Unmaintained since 2021, zero stars/dependents. Pin it exactly ("micro-module/broadway-saga": "1.0.*" style) and budget to fork. The broadway/* API changed across 0.x/1.x, so a fresh composer require today can pull a Broadway version the adapter's reflection-based handler dispatch doesn't match.
  • Silent no-ops are the default failure mode. If a saga isn't registered, its getSagaId() collides, or the event class name doesn't match the handler method (handleOrderPlaced for OrderPlaced), nothing throws — the event is just ignored. Add a log line at the top of every handler while bringing a saga up.
  • Two event bus instances. The most common bug: the package registers the saga manager on its own bus binding, while your app publishes to a different one. Check app()->bound() / the container alias and ensure it's the same singleton.
  • In-memory saga repository hides durability bugs. Defaults often use InMemorySagaRepository for convenience. It works in tests and breaks in production (state lost per request/worker). Explicitly configure a DB-backed repository and confirm the migration ran.
  • At-least-once delivery ⇒ idempotent handlers. Queued event buses can redeliver. Guard commands that aren't naturally idempotent, or track processed event IDs on the saga state.
  • Extension points worth overriding: the SagaRepository binding (swap for your own table/ORM), the saga registry in config, and the SagaManager construction if you need to attach extra middleware. These are the three seams in a package this small.
  • When it breaks, it usually isn't the package. Verify Broadway itself is wired (EventBus and CommandBus resolvable, event store migrated). This adapter has almost no logic of its own — debug Broadway first, then the registration.
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.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle