Save 37% off PRO during our Black Friday Sale! »

Event Sourcing - El valor de la información

D900aefa2f8ee52f162599fab2fb0448?s=47 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.

D900aefa2f8ee52f162599fab2fb0448?s=128

Diego Martin

September 28, 2019
Tweet

Transcript

  1. EVENT SOURCING El valor de la información Diego Martín diego.martin@sunnyatticsoftware.com

    https://sunnyatticsoftware.com
  2. Algunos autores de cabecera 2 Robert C. Martin Martin Fowler

    Diego Martín …y otros HTTPS://SUNNYATTICSOFTWARE.COM
  3. Evento es un hecho ocurrido 3 HTTPS://SUNNYATTICSOFTWARE.COM

  4. 4 HTTPS://SUNNYATTICSOFTWARE.COM

  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
  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
  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
  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
  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
  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
  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
  12. WORM Write Once Read Many Inmutabilidad 12 HTTPS://SUNNYATTICSOFTWARE.COM

  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
  14. Carrito Venta Producto * Esto es un modelo Entidad-Relación de

    toda la vida 2 0..1 14 HTTPS://SUNNYATTICSOFTWARE.COM
  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
  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
  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
  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
  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
  20. CarritoCreado ProductoAñadido ProductoAñadido ProductoAñadido ProductoQuitado CarritoConfirmado Replay ProductoQuitado id producto

    msHastaOk precio email 1 vb157486 4302 423.25 want_but_cant@test.com Las Proyecciones son reportes que tienen en cuenta todo el histórico de eventos 20 HTTPS://SUNNYATTICSOFTWARE.COM
  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
  22. ¿Coste de sistemas append-only? 22 HTTPS://SUNNYATTICSOFTWARE.COM

  23. 23 HTTPS://SUNNYATTICSOFTWARE.COM

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

  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
  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
  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
  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
  29. ¿CQRS + Event Sourcing? 29 HTTPS://SUNNYATTICSOFTWARE.COM

  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
  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
  32. Pero.. ¿y si el query service tarda demasiado en recibir

    el evento? 32 HTTPS://SUNNYATTICSOFTWARE.COM
  33. Consistencia Eventual 33 HTTPS://SUNNYATTICSOFTWARE.COM

  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
  35. ¿Y los cambios en la estructura (versionado)? Más info Menos

    info Diferente info 35 HTTPS://SUNNYATTICSOFTWARE.COM
  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
  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
  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
  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
  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
  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
  42. Al versionar eventos Sin problema para añadir Cuidado al borrar

    Cuidado al renombrar (= borrar + añadir) 42 HTTPS://SUNNYATTICSOFTWARE.COM
  43. ¿Si no quiero perder información al renombrar? 43 HTTPS://SUNNYATTICSOFTWARE.COM

  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
  45. ¿Y si los cambios son muy drásticos? 45 HTTPS://SUNNYATTICSOFTWARE.COM

  46. Event Store EventLog o Stream Event … ProductoAñadido … New

    EventLog o Stream Event … ReservaProductoAñadido … copy & replace Event Store 46 HTTPS://SUNNYATTICSOFTWARE.COM
  47. ¿ Cómo borrar información de eventos? 47 HTTPS://SUNNYATTICSOFTWARE.COM

  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
  49. ¿Existe alguna base de datos de eventos? 49 HTTPS://SUNNYATTICSOFTWARE.COM

  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
  51. None