CQRS AND EVENT SOURCING BASICS
Alexander Miertsch
Founder and CEO of prooph software GmbH
Founder and core contributor prooph components
contact@prooph.de
prooph components
CQRS and Event Sourcing packages for PHP
Supported Web Frameworks
or any other framework/codebase supporting container-interop & interop-config
Problem Space
Complex
Distributed
Chaotic
When to use CQRS & ES ?
Messages
Semantics of Messaging
Types: Command, Query, Event
Immutable DTOs
Unique names according to Domain Language
Command
Imperative Messages
Represent sender's intention
Instruct receiver to perform action
Never return data
Query
Interrogatory Messages
Ask system about it's current state
Do NOT cause stage changes
Can be cached
Domain Events
Informational Message
Named in past tense
Communicate facts that have happened
Relevant to the business
Event Storming
Deeper insights with events
Event Flow
record, publish, react
OrderPlaced
OrderPaid
OrderShipped
Change State, Then Publish
ORM - Publisher
<?php
final class OrderService
{
private $entityManager;
private $orderRepositoy;
private $eventPublisher;
public function placeOrder(string $orderId, OrderItem ...$items): void
{
$order = $this->orderRepostoy->get($orderId);
$this->entityManager->beginTransaction();
try {
$order->place($items);
$this->entityManager->commit();
} catch(\Throwable $error) {
$this->entityManager->rollBack();
throw $error;
}
$event = OrderPlaced::fromOrder($order);
$this->eventPublisher->publish($event);
}
}
Record Event, Then Publish
Event Store - Publisher
<?php
final class PlaceOrderHandler
{
private $eventStore;
private $eventPublisher;
public function handle(PlaceOrder $command): void
{
//Note: Loading/saving is normally done by event sourcing repository
$orderStream = new StreamName('order-'.$command->orderId());
$history = $this->eventStore->load($orderStream);
$order = Order::reconstituteFromHistory($history);
$newEvents = $order->place($command->items());
//Atomic operation
$this->eventStore->appendTo($orderStream, $newEvents);
$this->eventPublisher->publish($newEvents);
}
}
Event Sourcing
State is a left fold of past events
# E1 at t1: UserRegistered
userId: 1
name: John Doe
email: doe@fake.com
# E2 at t2: UsernameChanged
userId: 1
oldName: John Doe
newName: Alex
# E3 at t3: EmailChanged
userId: 1
oldEmail: doe@fake.com
newEmail: contact@prooph.de
_______________________________________________
# current state (t:now) = ((E1 + E2) + E3):
userId: 1
name: Alex
email: contact@prooph.de
version: 3
Time Travel
Debug like a boss
UserRegistered
UsernameChanged
ChangeEmailFailed
{
E1 + E2
Change Email
Temporal Queries
Use time interval as query param
UserRegistered
UsernameChanged
5 min
7 min
Who has changed username within 5 min after registration?
UserRegistered
UsernameChanged
Event Sourcing in PHP
prooph components
CQRS
SRP on system level
Gateway
Write Model
Read Model
CQRS and Event Sourcing
Double Team
Gateway
Write Model
Read Model
Event Store
Projection
Cache
Event Driven Microservices
React on Events
E1
E2
E3
E4
E5
Event Log
Document DB
Message Queue
Process Manager
Search Service
Services
subscribe
consume
CQRS in PHP
prooph components
Just Try It
Join prooph
Event Sourcing Tutorial
Thanks for listening
Questions?
PHP UG Munich 2018 CQRS and ES Basics
By prooph
PHP UG Munich 2018 CQRS and ES Basics
- 1,414