CQRS AND EVENT SOURCING BASICS

Alexander Miertsch

Founder and CEO of prooph software GmbH

Founder and core contributor prooph components

 

 

contact@prooph.de

@codeliner

@prooph_software

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/

event-sourcing

Event sourcing basics

Event store integration

 

prooph/

event-store

Append-only streams

Persistent projections

Event stream queries

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/

service-bus

Lightweight message bus

Supporting CQRS

 

prooph/

psb-*-producer

Messaging adapters

Async processing

RPC support

prooph components

Just Try It

Join prooph

Event Sourcing Tutorial 

Thanks for listening

Questions?

Made with Slides.com