Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Event Sourcing - El valor de la información

Diego Martin
September 28, 2019

Event Sourcing - El valor de la información

Esta es una presentación de Diego Martín, fundador de Sunny Attic Software (https://sunnyatticsoftware.com) presentada en la DotNetMalaga 2019.
En ella se habla del concepto de eventos como hechos inmutables y de los sistemas Event Sourcing donde el estado, que es transitorio, no es el que se guarda, sino que se infiere a partir del histórico de eventos.
Después se habla de CQRS y de cómo CQRS sirve de herramienta para conseguir escalado horizontal, caché infinita, optimización del proceso de lectura, etc. Se explica por qué CQRS nos permite utilizar Event Sourcing y cómo Domain Driven Design nos ayuda a modelar el dominio para utilizar la consistencia eventual en nuestro favor.
Finalmente se discute una técnica de versionado de eventos con weak-schema y una forma de implementar protección de datos (i.e: ley GDPR) en sistemas Event Sourcing.

Diego Martin

September 28, 2019
Tweet

More Decks by Diego Martin

Other Decks in Programming

Transcript

  1. EVENT SOURCING
    El valor de la información
    Diego Martín
    [email protected]
    https://sunnyatticsoftware.com

    View Slide

  2. Algunos autores de cabecera
    2
    Robert C. Martin
    Martin Fowler
    Diego Martín
    …y otros
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  3. Evento
    es un hecho ocurrido
    3
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  4. 4
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  5. Account-123
    # Event
    1 AccountCreated
    2 SalaryReceived
    3 PaymentMade
    4 PaymentMade
    5 InterestReceived
    6 PaymentReverted
    Balance Account-123
    3050
    Event Stream
    Agrupa eventos
    Dentro de un Event Log
    Estado
    5
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  6. Account-123
    # Event
    1 AccountCreated
    2 SalaryReceived
    3 PaymentMade
    4 PaymentMade
    5 InterestReceived
    6 PaymentReverted
    {
    “AggregateId”: “123”,
    “EventId”: “abc”
    }
    Balance Account-123
    0
    6
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  7. Account-123
    # Event
    1 AccountCreated
    2 SalaryReceived
    3 PaymentMade
    4 PaymentMade
    5 InterestReceived
    6 PaymentReverted
    {
    “AggregateId”: “123”,
    “EventId”: “abd”,
    “Company”: “Iberodev S.L”,
    “Amount”: 4000.00,
    “CurrencyCode”: EUR
    }
    Balance Account-123
    4000
    7
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  8. Account-123
    # Event
    1 AccountCreated
    2 SalaryReceived
    3 PaymentMade
    4 PaymentMade
    5 InterestReceived
    6 PaymentReverted
    {
    “AggregateId”: “123”,
    “EventId”: “abe”
    “Destination”: “Amazon”,
    “IsDebited”: true,
    “Amount”: 500.00,
    “CurrencyCode”: EUR
    }
    Balance Account-123
    3500
    8
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  9. Account-123
    # Event
    1 AccountCreated
    2 SalaryReceived
    3 PaymentMade
    4 PaymentMade
    5 InterestReceived
    6 PaymentReverted
    {
    “AggregateId”: “123”,
    “EventId”: “abf”,
    “Destination”: “Telepizza”,
    “IsDebited”: true,
    “Amount”: 1000.00,
    “CurrencyCode”: EUR
    }
    Balance Account-123
    2500
    9
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  10. Account-123
    # Event
    1 AccountCreated
    2 SalaryReceived
    3 PaymentMade
    4 PaymentMade
    5 InterestReceived
    6 PaymentReverted
    {
    “AggregateId”: “123”,
    “EventId”: “abg”,
    “Reason”: “Acc 3.75% TAE”,
    “Amount”: 50.00,
    “CurrencyCode”: EUR
    }
    Balance Account-123
    2550
    10
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  11. Account-123
    # Event
    1 AccountCreated
    2 SalaryReceived
    3 PaymentMade
    4 PaymentMade
    5 InterestReceived
    6 PaymentReverted
    {
    “AggregateId”: “123”,
    “EventId”: “abh”,
    “RefersToEventId”: “abe”,
    “Reason”: “Mistake”,
    “Amount”: 500.00,
    “CurrencyCode”: EUR
    }
    Balance Account-123
    3050
    Estado actual
    11
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  12. WORM
    Write Once Read Many
    Inmutabilidad
    12
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  13. CarritoCreado
    ProductoAñadido
    Los eventos son
    Append-Only
    ProductoAñadido
    ProductoAñadido
    0
    ProductoQuitado
    CarritoConfirmado
    1
    2
    3
    2
    y… venta creada!!
    13
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  14. Carrito
    Venta
    Producto
    *
    Esto es un modelo
    Entidad-Relación
    de toda la vida
    2
    0..1
    14
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  15. CarritoCreado
    ProductoAñadido
    ProductoAñadido
    ProductoAñadido
    ProductoQuitado
    CarritoConfirmado
    Todo estado
    es transitorio
    Replay
    2
    Carrito
    Venta
    Producto
    *
    0..1
    15
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  16. Replay
    CarritoCreado
    ProductoAñadido
    ProductoAñadido
    ProductoAñadido
    ProductoQuitado
    CarritoConfirmado
    CarritoCreado
    ProductoAñadido
    ProductoAñadido
    CarritoConfirmado
    ¿No es lo mismo?
    VS
    2
    Carrito
    Venta
    Producto
    *
    0..1
    16
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  17. CarritoCreado
    ProductoAñadido
    ProductoAñadido
    ProductoAñadido
    ProductoQuitado
    CarritoConfirmado
    Qué vs Cómo
    Replay
    ¿Quién conoce el
    valor futuro de la
    información?
    17
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  18. CarritoCreado
    ProductoAñadido
    ProductoAñadido
    ProductoAñadido
    ProductoQuitado
    CarritoConfirmado
    Replay
    Carrito
    id ventaId fechaCreacion
    1 9923 27/09/2019
    Producto
    id carritoId codigo nombre
    123 1 ma001123 Mesa azul
    124 1 sa098443 Silla azul
    Venta
    id carritoId importe moneda
    9923 1 275.26 EUR
    18
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  19. CarritoCreado
    ProductoAñadido
    ProductoAñadido
    ProductoAñadido
    ProductoQuitado
    CarritoConfirmado
    Replay
    Carrito
    id fechaCreacion productos total
    1 27/09/2019 ma001123, sa098443 257.26
    2 28/09/2019 Libro Eric Evans DDD 42.50
    VentaCompleta
    id fechaCreacion productos total
    1 27/09/2019 ma001123, sa098443 257.26
    19
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  20. CarritoCreado
    ProductoAñadido
    ProductoAñadido
    ProductoAñadido
    ProductoQuitado
    CarritoConfirmado
    Replay
    ProductoQuitado
    id producto msHastaOk precio email
    1 vb157486 4302 423.25 [email protected]
    Las Proyecciones son reportes
    que tienen en cuenta todo el
    histórico de eventos
    20
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  21. Con Event Sourcing
    no se pierde información
    Create
    Read
    Update
    Delete Concurrencia problemática
    Optimización de escritura y
    concurrencia optimística
    21
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  22. ¿Coste de sistemas append-only?
    22
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  23. 23
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  24. ¿Consultas en bases de datos de eventos?
    24
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  25. “Asking a question should not change the answer”
    Bertrand Meyer
    void DoSomething(arg); // command
    object GetSomething(arg); // query
    CQRS
    Command Query Responsibility
    Segregation
    CQS
    Command Query Separation
    25
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  26. Base de Datos
    Objeto de
    Dominio
    Objeto de
    Dominio
    Aplicación
    Façade Remota
    Cliente
    Envío DTO
    return status
    Petición DTO
    return DTO
    Esto es una arquitectura
    CRUD de DTO up/down
    de toda la vida
    26
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  27. Base de Datos
    Objeto de
    Dominio
    Objeto de
    Dominio
    Aplicación
    Façade Remota
    Command
    Base de Datos
    Aplicación
    Façade Remota
    Cliente
    Query
    27
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  28. Façade Remota
    Command Handler
    Domain Object
    Repository
    Command
    Event
    Command Service
    Façade Remota
    Query
    Event Handler
    Repository
    Query Service
    28
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  29. ¿CQRS + Event Sourcing?
    29
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  30. Façade Remota
    Command Handler
    Domain Object
    Repository
    Command
    Event
    Store Events
    Command Service
    Façade Remota
    Query
    Event Handler
    Repository
    Query Service
    30
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  31. Command Service
    Event
    Store
    Query Service
    Query Service
    Query Service
    Nuevo Read Model
    subscriptor
    publicador
    Replay de eventos
    desde posición 0
    31
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  32. Pero.. ¿y si el query service tarda
    demasiado en recibir el evento?
    32
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  33. Consistencia Eventual
    33
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  34. CQRS consigue AP
    y
    consistencia eventual
    “Consistency, Availability, Partition Tolerance. Choose only two”
    Eric Brewer – CAP Theorem
    CQRS + Event Sourcing
    DDD
    34
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  35. ¿Y los cambios en la
    estructura (versionado)?
    Más info
    Menos info
    Diferente info
    35
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  36. {
    “AggregateId”: “123”,
    “Fecha”: “2003-04-21”,
    “Codigo”: 500
    }
    EventLog
    # Event
    … …
    96852 ProductoAñadido
    96852 ProductoAñadido
    … …
    102656 ProductoAñadido
    … …
    113584 ProductoAñadido
    … …
    {
    “AggregateId”: “123”,
    “CodigoProducto”: 650,
    “Tienda”: “Llevatelo S.L”
    }
    = Más info
    Menos info
    Diferente info
    36
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  37. Hay muchas estrategias…
    Double-Write
    Upcasting
    Weak-Schema mapping
    “A new version of an event must be convertible from the old version of the event.
    If not, it is not a new version of the event but rather a new event”
    Greg Young
    37
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  38. Cliente
    Event Store
    Cliente
    Cliente
    Diferentes “versiones”
    del mismo evento
    Conoce la
    primera versión
    class ProductoAñadido
    {
    string AggregateId {get;set;}
    DateTime Fecha {get;set;}
    int Codigo {get;set;}
    }
    Conoce la
    segunda versión
    Conoce la
    última versión
    class ProductoAñadido
    {
    string AggregateId {get;set;}
    int Codigo {get;set;}
    string Tienda {get;set;}
    }
    class ProductoAñadido
    {
    string AggregateId {get;set;}
    int CodigoProducto {get;set;}
    string Tienda {get;set;}
    }
    38
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  39. Cliente
    Event Store
    class ProductoAñadido
    {
    string AggregateId {get;set;} // “123”
    DateTime Fecha {get;set;} // 2003-04-21
    int Codigo {get;set;} // 500
    }
    {
    “AggregateId”: “123”,
    “Fecha”: “2003-04-21”,
    “Codigo”: 500
    } Cliente
    Cliente
    class ProductoAñadido
    {
    string AggregateId {get;set;} // “123”
    int Codigo {get;set;} // 500
    string Tienda {get;set;} // null (default)
    }
    class ProductoAñadido
    {
    string AggregateId {get;set;} // “123”
    int CodigoProducto {get;set;} // 0 (default)
    string Tienda {get;set;} // null (default)
    }
    v1
    39
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  40. Cliente
    Event Store
    class ProductoAñadido
    {
    string AggregateId {get;set;} // “123”
    DateTime Fecha {get;set;} // 0001-01-01 (default)
    int Codigo {get;set;} // 500
    }
    {
    “AggregateId”: “123”,
    “Codigo”: 500,
    “Tienda”: “Llevatelo S.L”
    } Cliente
    Cliente
    class ProductoAñadido
    {
    string AggregateId {get;set;} // “123”
    int Codigo {get;set;} // 500
    string Tienda {get;set;} // “Llevatelo S.L”
    }
    class ProductoAñadido
    {
    string AggregateId {get;set;} // “123”
    int CodigoProducto {get;set;} // 0 (default)
    string Tienda {get;set;} // “Llevatelo S.L”
    }
    v2
    40
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  41. Cliente
    Event Store
    class ProductoAñadido
    {
    string AggregateId {get;set;} // “123”
    DateTime Fecha {get;set;} // 0001-01-01 (default)
    int Codigo {get;set;} // 0 (default)
    }
    {
    “AggregateId”: “123”,
    “CodigoProducto”: 650,
    “Tienda”: “Llevatelo S.L”
    } Cliente
    Cliente
    class ProductoAñadido
    {
    string AggregateId {get;set;} // “123”
    int Codigo {get;set;} // 0 (default)
    string Tienda {get;set;} // “Llevatelo S.L”
    }
    class ProductoAñadido
    {
    string AggregateId {get;set;} // “123”
    int CodigoProducto {get;set;} // 650
    string Tienda {get;set;} // “Llevatelo S.L”
    }
    v3
    41
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  42. Al versionar eventos
    Sin problema para añadir
    Cuidado al borrar
    Cuidado al renombrar (= borrar + añadir)
    42
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  43. ¿Si no quiero perder
    información al renombrar?
    43
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  44. Event Store
    {
    “AggregateId”: “123”,
    “Codigo”: 500,
    “Tienda”: “Llevatelo S.L”
    } Cliente
    v2
    class ProductoAñadido
    {
    string AggregateId {get;} // “123”
    int CodigoProducto => Codigo // 500
    string Tienda {get;} // “Llevatelo S.L”
    [Obsolete]
    int Codigo {get;}
    public ProductoAñadido(
    string aggregateId,
    int codigo,
    int codigoProducto,
    string tienda)
    {
    AggregateId = aggregateId;
    Codigo = codigoProducto != 0 ?
    codigoProducto : codigo;
    Tienda = tienda
    }
    }
    mapping
    44
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  45. ¿Y si los cambios son muy
    drásticos?
    45
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  46. Event Store
    EventLog o Stream
    Event

    ProductoAñadido

    New EventLog o Stream
    Event

    ReservaProductoAñadido

    copy & replace Event Store
    46
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  47. ¿ Cómo borrar información
    de eventos?
    47
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  48. Event Storage
    Encriptación clave
    simetrica
    Key Storage
    DataSubjectId EncryptionKey IsDeleted
    123 Ab7…9fsFs= false
    124 gRR…vs3Ag= true
    125 R2f…5sGfl= false
    class ClienteAñadido
    {
    string Nombre {get;} // Diego Martin
    DateTime Nacimiento {get;} // 1984-01-01
    string CodigoPais {get;} // ES
    }
    {
    “nombre”: “GFfsd4afREWsfsgfadsdf=”,
    “nacimiento”: “fhh4gsdVgasgr65fGG=”,
    “codigoPais”: ES
    }
    {
    “nombre”: “GFfsd4afREWsfsgfadsdf=”,
    “nacimiento”: “fhh4gsdVgasgr65fGG=”,
    “codigoPais”: ES
    }
    Desencriptación
    clave simetrica
    class ClienteAñadido
    {
    string Nombre {get;} // ******,
    DateTime Nacimiento {get;} // 0001-01-01
    string CodigoPais {get;} // ES
    }
    48
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  49. ¿Existe alguna base de datos de eventos?
    49
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  50. https://eventstore.org
    Base de datos open source para streams de eventos
    Multiplataforma, implementado en un mix de C# (con Mono), C++ y Javascript
    50
    HTTPS://SUNNYATTICSOFTWARE.COM

    View Slide

  51. View Slide