Bringing CQRS and Event Sourcing to PHP. Open sourcing Broadway!


Last week we open sourced our toggle library, API and GUI, see our announcements here and here. Today we open source Broadway! Broadway is a project providing infrastructure and testing helpers for creating CQRS and event sourced applications. Broadway tries hard to not get in your way. The project contains several loosely coupled components that can be used together to provide a full CQRS\ES experience.

You can find the code here: https://github.com/qandidate-labs/broadway

And example code here: https://github.com/qandidate-labs/broadway/tree/master/examples

CQRS/ES

CQRS stands for Command Query Responsibility Segregation. It is a design pattern where there is a separate model for writing and reading information. If you want to know more about CQRS, this article by Martin Fowler is a good start. With Event Sourcing (ES) you capture every change in your application as a sequence of events. You only need to store the events and their data so you can use projectors to project read models out of them. This way you can create highly specialized read models to fulfill any specific need.

Components

Broadway consists of several components:

  • Auditing Add an audit trail to your application. Currently enables you to log whether commands were successful or not.
  • CommandHandling Provides the interface and a CommandHandler base class for handling events as well as the Commandbus interface and implementations where commands can be dispatched on.
  • Domain Component that contains the domain abstractions of the Broadway framework including the aggregate root, domain messages and domain events.
  • EventDispatcher The component provides an event dispatcher interface and a simple implementation. In the future it would be great to have integrations with other implementations.
  • EventHandling The component provides interfaces for an event bus and event listeners, but also an implementation of a simple event bus and an event bus that will record published events (useful for testing).
  • EventSourcing Provides base classes for event sourced aggregate roots and entities, an event sourced repository implementation and testing helpers.
  • EventStore It currently has an event store implementation based on doctrine/dbal to store events in a relational database and an in-memory implementation that is useful for using in tests.
  • Processor Provides processor capabilities to your application.
  • ReadModel This component provides storage for your read models, a projector implementation to create read models from event streams and testing helpers.
  • Serializer The component provides a simple serializer interface and a serializer implementation based on "handwritten" serializers. In the future it would be great to have support for more broadly used serializer implementations.

The Broadway project ships with a bundle to use in a Symfony application. It uses doctrine/dbal to store events. So it should work with every DBMS that doctrine/dbal supports. We use it with MySQL and SQLite. For testing we use our in-memory event store. For the storage of read models Broadway ships with Elasticsearch support.

Testing

Broadway is fully tested! It ships with cool helpers that will help you test your own Broadway-based application. Aggregates and projectors can easily be tested with scenarios:

$this->scenario
      ->given([new InvitedEvent($id, 'asm89')])
      ->when(new AcceptCommand($id))
      ->then([new AcceptedEvent($id)]);

The complete example can be found here: https://github.com/qandidate-labs/broadway/blob/master/examples/event-sourced-domain-with-tests/InvitesTest.php.

Acknowledgements

The Broadway project is heavily inspired by other open source project such as AggregateSource, Axon Framework and Ncqrs.

We would like to thank Benjamin, Marijn and Mathias for the conversations we had along the way that helped us shape the Broadway project. In particular Marijn for giving us access to his in-house developed CQRS framework.

Disclaimer

While Broadway is currently used in production, you should know that it isn't perfect (Yet!). So if you come up with any improvements, please send us your feedback and pull requests!

For now check out the project at: https://github.com/qandidate-labs/broadway

And look at the examples at: https://github.com/qandidate-labs/broadway/tree/master/examples

For questions and discussion, join #qandidate on Freenode.