Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Eventsourcing Xplained

59 views

Published on

... if at first you don't succeed ... primer, patterns and mashup of common problems and solutions

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Eventsourcing Xplained

  1. 1. 1 / 175
  2. 2. Event Sourcing Explained { if at first you don't succeed } 2 / 175
  3. 3. About me EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 3 / 175
  4. 4. About me A journeylist with a passion for well-designed, properly decomposed, working software. Professional experience: 25 years, Mainly building products, In domains such as patient logistics, real estate, manufacturing, construction, transportation, oil & gas, content & collaboration, government, finance Contractor | Consultant | Trainer | Analyst | Designer @ BitTacklr Community experience: DDD community member, Occasional speaker, blogger on the topic of Domain Driven Design, Command and Query Responsibility Segregation, Event Sourcing and Messaging and related topics. Author of AggregateSource / Projac | Contributor to SqlStreamStore (OSS). EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 3 / 175
  5. 5. Half stack developer EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 4 / 175
  6. 6. Half stack developer Guess which part EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 4 / 175
  7. 7. Agenda Primer Principles & Patterns Common Problems & Solutions EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 5 / 175
  8. 8. Primer Messages Event Store EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 6 / 175
  9. 9. Primer - Messages A message is a record of information ... EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 7 / 175
  10. 10. Primer - Messages A message is a record of information ... that captures meaning and data that can be transmitted that can be stored that typically has a header and a body (i.e. an envelope) EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 7 / 175
  11. 11. Primer - Messages A schema describes the shape or structure of messages in a formal language ... EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 8 / 175
  12. 12. Primer - Messages A schema describes the shape or structure of messages in a formal language ... such as XML or JSON schema, Protocol Buffers' Language, etc. that can be shared between parties for which code can be generated that can be interpreted that optionally contains constraints, requirements and/or metadata EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 8 / 175
  13. 13. Primer - Messages Encoding is the conversion of messages into a specific form ... EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 9 / 175
  14. 14. Primer - Messages Encoding is the conversion of messages into a specific form ... such that it can form a protocol with other parties such as XML, JSON, BSON, Protocol Buffers, UTF-8|16|32, which is often classified as either binary or character which is a more general form of serialization https://en.wikipedia.org/wiki/Comparison_of_data_serialization_formats EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 9 / 175
  15. 15. Primer - Messages Why use a schema and encoding to define your messages? EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 10 / 175
  16. 16. Primer - Messages Why use a schema and encoding to define your messages? Your programming language supports things your encoding format does not Your encoding format supports things your programming language does not Your encoding format is dictating your message type system, not your programming language Your code is simply too refactor friendly Generally, people suck at versioning - schema helps you get serious about that Schema allows for up-front design and is a collaboration medium EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 10 / 175
  17. 17. Primer - Types of Messages Commands Events Documents Queries | Requests & Responses EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 11 / 175
  18. 18. Primer - Commands EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 12 / 175
  19. 19. Primer - Commands A command is a request to change state or to invoke behavior ... EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 12 / 175
  20. 20. Primer - Commands A command is a request to change state or to invoke behavior ... that can be classified as a type of message, that can denote the body of a message, that captures meaning and data of something that should happen, that can capture business or domain relevant change requests, uses imperative (think German), uses domain specific language, expressed using verbs, preferably sentences. EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 12 / 175
  21. 21. Primer - Events EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 13 / 175
  22. 22. Primer - Events An event is an immutable record of historical information ... EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 13 / 175
  23. 23. Primer - Events An event is an immutable record of historical information ... that can be classified as a type of message that can denote the body of a message that captures meaning and data of something that has happened that - to the best of our knowledge - happened at a certain instant that can capture business or domain relevant changes uses past tense (think French - passé composé) uses domain specific language, expressed using verbs, preferably sentences. EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 13 / 175
  24. 24. Primer - Documents EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 14 / 175
  25. 25. Primer - Documents A document message acts as a data container and lets the receiver decide what to do with it ... EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 14 / 175
  26. 26. Primer - Documents A document message acts as a data container and lets the receiver decide what to do with it ... is used to integrate / exchange information between systems, is often associated with canonical or stable data models, is also the shape used to communicate the result of a query, the timing of when it's sent or received and the intent is less important, thus differentiating itself from commands and events EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 14 / 175
  27. 27. Primer - Queries EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 15 / 175
  28. 28. Primer - Queries A query is a request to retrieve information ... EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 15 / 175
  29. 29. Primer - Queries A query is a request to retrieve information ... usually represented as the combination of a request and response message that can capture business or domain relevant requests, where the request message often contains criteria to select, filter and page results where the response message often contains the result that meets the request criteria often aligns with the needs of consumers, e.g. the data on a screen or the shape of an API EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 15 / 175
  30. 30. Primer - Commands Example: Reserve a table at a restaurant EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 16 / 175
  31. 31. Primer - Commands Example: Reserve a table at a restaurant Analysis EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 16 / 175
  32. 32. Primer - Commands Example: Reserve a table at a restaurant Analysis Who wants to make the reservation? How many guests are you? When are you coming? Which restaurant? What's the occasion? (optional) Any special request? (optional) EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 16 / 175
  33. 33. Primer - Commands Example: Reserving a table at a restaurant PROTO EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 17 / 175
  34. 34. Primer - Commands Example: Reserving a table at a restaurant PROTO message ReserveTable = { string MemberId = 1; int32 Guests = 2; string Date = 3 string Time = 4; string RestaurantId = 5; string Occasion = 6; string SpecialRequest = 7; } EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 17 / 175
  35. 35. Primer - Commands Example: Reserve a table at a restaurant CSHARP EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 18 / 175
  36. 36. Primer - Commands Example: Reserve a table at a restaurant CSHARP public class ReserveTable { public Guid MemberId { get; set; } public Int32 Guests { get; set; } public DateTime Date { get; set; } public TimeSpan Time { get; set; } public Guid RestaurantId { get; set; } public String Occasion { get; set; } public String SpecialRequest { get; set; } } EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 18 / 175
  37. 37. Primer - Commands Example: Reserving a table at a restaurant SERIALIZATION EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 19 / 175
  38. 38. Primer - Commands Example: Reserving a table at a restaurant SERIALIZATION var message = new ReserveTable { MemberId = Guid.NewGuid(), /* ... */ }; Console.WriteLine(JsonConvert.SerializeObject(message)); EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 19 / 175
  39. 39. Primer - Commands Example: Reserving a table at a restaurant SERIALIZATION DESERIALIZATION var message = new ReserveTable { MemberId = Guid.NewGuid(), /* ... */ }; Console.WriteLine(JsonConvert.SerializeObject(message)); EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 19 / 175
  40. 40. Primer - Commands Example: Reserving a table at a restaurant SERIALIZATION DESERIALIZATION var message = new ReserveTable { MemberId = Guid.NewGuid(), /* ... */ }; Console.WriteLine(JsonConvert.SerializeObject(message)); var serialized = @"{""MemberId"": ""6e98e539-eb01-47e9-8961-efd9728a14df"", /*...*/ }"; var message = JsonConvert.DeserializeObject<ReserveTable>(serialized); EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 19 / 175
  41. 41. Primer - Commands Example: Reserve a table at a restaurant JSON EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 20 / 175
  42. 42. Primer - Commands Example: Reserve a table at a restaurant JSON { "MemberId": "6e98e539-eb01-47e9-8961-efd9728a14df", "Guests": 2, "Date": "2018-01-27", "Time": "19:00:00", "RestaurantId": "200edce7-263e-4799-81fe-834f84fff17a", "Occasion": "Birthday", "SpecialRequest": "Please don't play any birthday music." } EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 20 / 175
  43. 43. Primer - Commands Example: Reserve a table at a restaurant HTTP EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 21 / 175
  44. 44. Primer - Commands Example: Reserve a table at a restaurant HTTP HTTP/1.1 200 OK Content-Type: application/vnd.tableau.reservetableatrestaurant+json Content-Length: 319 { "MemberId": "6e98e539-eb01-47e9-8961-efd9728a14df", "Guests": 2, "Date": "2018-01-27", "Time": "19:00:00", "RestaurantId": "200edce7-263e-4799-81fe-834f84fff17a", "Occasion": "Birthday", "SpecialRequest": "Please don't play any birthday music." } EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 21 / 175
  45. 45. Primer - Events Example: A table was reserved at a restaurant EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 22 / 175
  46. 46. Primer - Events Example: A table was reserved at a restaurant Analysis EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 22 / 175
  47. 47. Primer - Events Example: A table was reserved at a restaurant Analysis Who made the reservation? When was it made? How many guests are you? When are you coming? Which restaurant? Which table was reserved? What's the occasion? (optional) Any special request? (optional) EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 22 / 175
  48. 48. Primer - Events Example: A table was reserved at a restaurant JSON EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 23 / 175
  49. 49. Primer - Events Example: A table was reserved at a restaurant JSON { "MemberId": "6e98e539-eb01-47e9-8961-efd9728a14df", "Guests": 2, "Date": "2018-01-27", "Time": "19:00:00", "RestaurantId": "200edce7-263e-4799-81fe-834f84fff17a", "TableReference": "C2", "Occasion": "Birthday", "SpecialRequest": "Please don't play any birthday music.", "When": "2018-01-07T20:47:00" } EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 23 / 175
  50. 50. Primer - Events Example: A table was reserved at a restaurant HTTP EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 24 / 175
  51. 51. Primer - Events Example: A table was reserved at a restaurant HTTP HTTP/1.1 200 OK Content-Type: application/vnd.tableau.tablereservedatrestaurant+json Content-Length: 319 { "MemberId": "6e98e539-eb01-47e9-8961-efd9728a14df", "Guests": 2, "Date": "2018-01-27", "Time": "19:00:00", "RestaurantId": "200edce7-263e-4799-81fe-834f84fff17a", "TableReference": "C2", "Occasion": "Birthday", "SpecialRequest": "Please don't play any birthday music.", "When": "2018-01-07T20:47:00" } EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 24 / 175
  52. 52. Primer - Documents Example: List of cuisines HTTP EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 25 / 175
  53. 53. Primer - Documents Example: List of cuisines HTTP POST /api/lists HTTP/1.1 Host: tableau.fr Content-Type: application/vnd.tableau.list-of-cuisines+json Content-Length: 483 { "Options": [ "American", "Italian", "Steakhouse", "French", "Pacific Rim", "Indian", "Mexican", "Japanese", "British", "Wine Bar", "Chinese", "Spanish", "Pizzeria", "Greek", "Thai", "South American", "Tapas / Small Plates", "Grill", "Comfort Food", "Turkish", "Argentinean", "Afternoon Tea", "Burgers", "Nepalese", "Wild Game", "Halal", "Café", "Contemporary European", "Southeast Asian" "Dim Sum", "European", "Gastro Pub", "Modern European" ] } EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 25 / 175
  54. 54. Primer - Queries Example: Search for a table to reserve Request Analysis EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 26 / 175
  55. 55. Primer - Queries Example: Search for a table to reserve Request Analysis What date do you want to reserve on? At what time? What type of food / cooking do you want to have? How many guests will you be? Where will you / do you want to be? EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 26 / 175
  56. 56. Primer - Queries Example: Search for a table to reserve Response Analysis EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 27 / 175
  57. 57. Primer - Queries Example: Search for a table to reserve Response Analysis For each restaurant with sufficient capacity indicate whether it's verified or not state its name, type of food served, address, location, relative distance if applicable give an indication of the price range, the rating by other members, its performance statistics offer the available time slots EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 27 / 175
  58. 58. Primer - Queries Example: Search for a table to reserve HTTP - Request EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 28 / 175
  59. 59. Primer - Queries Example: Search for a table to reserve HTTP - Request POST /api/search HTTP/1.1 Host: tableau.fr Authorization: Bearer Content-Type: application/vnd.tableau.searchrequest+json Content-Length: 108 { "Date": "2020-01-27", "Time": "19:00", "Guests": 5, "Location": "Nearby(50.844795,4.356717)", "Cuisine": "Italian" } EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 28 / 175
  60. 60. HTTP - Response HTTP/1.1 200 OK Content-Type: application/vnd.tableau.searchresponse+json Content-Length: 634 [ { "Restaurant": { "Id": "d937eeb1-9ebc-4d0c-a53e-c7ac349adcbd", "Verified": false, "Name": "La Cucina Della Nonna", "Cuisine": "Italian Food", "PriceRange": "€€", "Rating":"***", "TotalReviews": 12, "ReservationStatistics" : { "Total": 3000, "TotalToday": 0, "TotalByMembers": 300 }, "Address": [ "Rue des Bouchers 5", "1000 Brussels", "Belgium" ], "Distance": "500m", "Coordinates": "50.847821,4.354781" }, "AvailableTimeSlots": { "18:30" : [ "A", "B" ], "18:45" : [ "A" ], "19:00" : [ "E" ], "19:15" : [ "B", "D" ], "19:30" : [ "A", "D" ] } } ] EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 29 / 175
  61. 61. Primer - Message Identity EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 30 / 175
  62. 62. Primer - Message Identity A message identifier uniquely identifies a message ... EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 30 / 175
  63. 63. Primer - Message Identity A message identifier uniquely identifies a message ... and is usually transmitted as a header, and is useful for traceability purposes (causation & correlation), and is useful for message deduplication and idempotent processing, the use of global unique identifiers is fairly common (uuid | guid). EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 30 / 175
  64. 64. Primer - Messaging If you want to learn more about messaging I can highly recommend ... EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 31 / 175
  65. 65. Primer - Event Store EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 32 / 175
  66. 66. Primer - Event Store Overview Examples EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 32 / 175
  67. 67. Primer - Event Store An event source is where events come from or took place ... EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 33 / 175
  68. 68. Primer - Event Store An event source is where events come from or took place ... and could be either hardware or software and there could be one or more and is brought to our attention by a producer or publisher or emitter EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 33 / 175
  69. 69. Primer - Event Store An event destination is where events go to and are interpreted or handled ... EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 34 / 175
  70. 70. Primer - Event Store An event destination is where events go to and are interpreted or handled ... and there could be none, one or more than one and is facilitated by a consumer or receiver or sink EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 34 / 175
  71. 71. Primer - Event Store An event middleware decouples sources from destinations ... EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 35 / 175
  72. 72. Primer - Event Store An event middleware decouples sources from destinations ... or said differently, decouples producers from consumers of which Apache Kafka, Event Store, Azure Event Grid, Amazon SNS are examples EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 35 / 175
  73. 73. Primer - Event Store An event middleware decouples sources from destinations ... or said differently, decouples producers from consumers of which Apache Kafka, Event Store, Azure Event Grid, Amazon SNS are examples EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 35 / 175
  74. 74. Primer - Event Store EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 36 / 175
  75. 75. Primer - Event Store An event stream is a sequence of events partitioned by a name or key EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 37 / 175
  76. 76. Primer - Event Store An event stream is a sequence of events partitioned by a name or key EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 37 / 175
  77. 77. Primer - Event Store An event stream is a sequence of events partitioned by a name or key EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 37 / 175
  78. 78. Primer - Event Store Each event appears at a certain version within an event stream EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 38 / 175
  79. 79. Primer - Event Store Each event appears at a certain version within an event stream EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 38 / 175
  80. 80. Primer - Event Store Each event appears at a certain version within an event stream EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 38 / 175
  81. 81. Primer - Event Store An event store is a collection of streams EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 39 / 175
  82. 82. Primer - Event Store An event store is a collection of streams EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 39 / 175
  83. 83. Primer - Event Store Each event appears at a certain position within an event store EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 40 / 175
  84. 84. Primer - Event Store Each event appears at a certain position within an event store EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 40 / 175
  85. 85. Primer - Event Store Example: Online shopping EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 41 / 175
  86. 86. Primer - Event Store Example: Online shopping Events EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 41 / 175
  87. 87. Primer - Event Store Example: Online shopping EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 42 / 175
  88. 88. Primer - Event Store Example: Online shopping John's shopping cart stream EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 42 / 175
  89. 89. Primer - Event Store Example: Online shopping John's shopping cart stream > Guest started shopping EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 42 / 175
  90. 90. Primer - Event Store Example: Online shopping EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 43 / 175
  91. 91. Primer - Event Store Example: Online shopping Jane's shopping cart stream EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 43 / 175
  92. 92. Primer - Event Store Example: Online shopping Jane's shopping cart stream EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 43 / 175
  93. 93. Primer - Event Store Example: Online shopping EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 44 / 175
  94. 94. Primer - Event Store Example: Online shopping All stream EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 44 / 175
  95. 95. Primer - Event Store Example: Online shopping All stream john: Guest started shopping jane: EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 44 / 175
  96. 96. Primer - Event Store EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 45 / 175
  97. 97. Primer - Event Store A subscription is an agreement to be notified when new events are written to a stream ... EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 46 / 175
  98. 98. Primer - Event Store A subscription is an agreement to be notified when new events are written to a stream ... and is typically set up by a consumer and is typically facilitated by an event store's client API and is one of many ways to feed events to projections and starts off at a known position in the all stream or starts off at a known version in a stream EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 46 / 175
  99. 99. Primer - Event Store Example: Online shopping EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 47 / 175
  100. 100. Primer - Event Store Example: Online shopping All stream subscription from the beginning EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 47 / 175
  101. 101. Primer - Event Store Example: Online shopping All stream subscription from the beginning john: Guest started shopping 0 2 4 5 7 jane: 1 3 6 8 EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 47 / 175
  102. 102. Primer - Event Store Example: Online shopping EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 48 / 175
  103. 103. Primer - Event Store Example: Online shopping All stream subscription from a known position EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 48 / 175
  104. 104. Primer - Event Store Example: Online shopping All stream subscription from a known position john: Item was removed from cart 0 2 4 5 7 jane: 1 3 6 8 EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 48 / 175
  105. 105. Primer - Event Store Common Operations EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 49 / 175
  106. 106. Primer - Event Store Common Operations Write Behavior EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 49 / 175
  107. 107. Primer - Event Store Common Operations Write Behavior AppendToStreamAtVersion: append one or more events to a stream, expecting the stream to be at a certain version (OCC), as an atomic operation (ACID) AppendToStreamAtAnyVersion: append one or more events to a stream, regardless of which version the stream is at, as an atomic operation (ACID) AppendToStreamAtNoVersion: append one or more events to a stream, expecting there to be no stream (OCC), as an atomic operation (ACID) EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 49 / 175
  108. 108. Primer - Event Store Common Operations EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 50 / 175
  109. 109. Primer - Event Store Common Operations Read Behavior ReadStreamForwards: read a slice of events from a stream, as of a certain version, progressing towards the end of the stream ReadStreamBackwards: read a slice of events from a stream, as of a certain version, progressing towards the beginning of the stream ReadAllStreamForwards: read a slice of events from the all stream, as of a certain position, progressing towards the end of the all stream ReadAllStreamBackwards: read a slice of events from the all stream, as of a certain position, progressing towards the beginning of the all stream EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 50 / 175
  110. 110. Primer - Event Store Common Operations EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 51 / 175
  111. 111. Primer - Event Store Common Operations Observation Behavior SubscribeToStream: observe events in a stream, as of a certain version SubscribeToAllStream: observe events in a stream, as of a certain position EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 51 / 175
  112. 112. Primer - Event Store Implementations EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 52 / 175
  113. 113. Primer - Event Store Implementations EventStore - https://eventstore.org/ [.NET HTTP] SqlStreamStore - https://sqlstreamstore.io/ [.NET C#] Marten - https://jasperfx.github.io/marten/ [.NET C#] Equinox - https://github.com/jet/equinox [.NET F#] AxonIQ - https://axoniq.io/ [JAVA] PROOPH - http://getprooph.org/ [PHP] Broadway - https://github.com/broadway [PHP] Commanded - https://github.com/commanded/eventstore [ELIXIR] Eventide - https://eventide-project.org/ [RUBY] ... EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 52 / 175
  114. 114. Primer Questions? EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 53 / 175
  115. 115. Principles & Patterns EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 54 / 175
  116. 116. Principles & Patterns Event Sourcing (ES) ... meets Command & Query Responsibility Segregation (CQRS) ... meets Domain Driven Design (DDD) EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 54 / 175
  117. 117. Event Sourcing To capture all state changes as a sequence of events. EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 55 / 175
  118. 118. Event Sourcing To capture all state changes as a sequence of events. captures and carries intent forward, captures semantics and data together, better fit for behavior centric problems, not so much for data centric problems, captures domain specific language, emphasis is on intent, rather than on the data that goes with that intent EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 55 / 175
  119. 119. Event Sourcing Example - Online Shopping EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 56 / 175
  120. 120. Event Sourcing Example - Online Shopping Cart Item Customer EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 56 / 175
  121. 121. Event Sourcing Data Centric State Changes EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 57 / 175
  122. 122. Event Sourcing Data Centric State Changes V1 EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 57 / 175
  123. 123. Event Sourcing Data Centric State Changes V1 V2 EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 58 / 175
  124. 124. Event Sourcing Data Centric State Changes V2 EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 59 / 175
  125. 125. Event Sourcing Data Centric State Changes V2 V3 EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 60 / 175
  126. 126. Event Sourcing Data Centric State Changes V3 EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 61 / 175
  127. 127. Event Sourcing Data Centric State Changes V3 V4 EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 62 / 175
  128. 128. Event Sourcing Data Centric State Changes V4 EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 63 / 175
  129. 129. Event Sourcing Data Centric State Changes V4 V5 EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 64 / 175
  130. 130. Event Sourcing Data Centric State Changes V5 EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 65 / 175
  131. 131. Event Sourcing Data Centric State Changes V5 EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 66 / 175
  132. 132. Event Sourcing Event Centric State Changes EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 67 / 175
  133. 133. Event Sourcing Event Centric State Changes V1 GSS - GSS = Guest Started Shopping EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 67 / 175
  134. 134. Event Sourcing Event Centric State Changes V1 GSS V2 IA - GSS = Guest Started Shopping - IA = Guest Added Item To Shopping Cart EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 68 / 175
  135. 135. Event Sourcing Event Centric State Changes V1 GSS V2 IA V3 IA - GSS = Guest Started Shopping - IA = Guest Added Item To Shopping Cart EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 69 / 175
  136. 136. Event Sourcing Event Centric State Changes V1 GSS V2 IA V3 IA V4 IR - GSS = Guest Started Shopping - IA = Guest Added Item To Shopping Cart - IR = Guest Removed Item From Shopping Cart EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 70 / 175
  137. 137. Event Sourcing Event Centric State Changes V1 GSS V2 IA V3 IA V4 IR V5 IA - GSS = Guest Started Shopping - IA = Guest Added Item To Shopping Cart - IR = Guest Removed Item From Shopping Cart EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 71 / 175
  138. 138. Event Sourcing Event Centric State Changes V1 GSS V2 IA V3 IA V4 IR V5 IA - GSS = Guest Started Shopping - IA = Guest Added Item To Shopping Cart - IR = Guest Removed Item From Shopping Cart EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 72 / 175
  139. 139. Event Sourcing EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 73 / 175
  140. 140. Event Sourcing Focus of Data Centric State Changes V1 V2 V3 V4 V5 EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 73 / 175
  141. 141. Event Sourcing Focus of Data Centric State Changes V1 V2 V3 V4 V5 Focus of Event Centric State Changes V1 GSS V2 IA V3 IA V4 IR V5 IA EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 73 / 175
  142. 142. Event Sourcing Event Centric Story Telling EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 74 / 175
  143. 143. Event Sourcing Event Centric Story Telling Customer started shopping Item added to cart Item added to cart Item removed from cart Customer checked out cart t EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 74 / 175
  144. 144. Primer - Event Sourcing Motivation EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 75 / 175
  145. 145. Primer - Event Sourcing Motivation the software is acting as the book of record, the history needs to be kept, i.e. audit heavy, the history itself brings value, there's a need for pro- and retroactive behavior, there's a need for temporal queries, how we got here is as important as where we are now (intent carried forward), the (sub-)domain itself highly collaborative, driven by behavior rather than data, multiple representation of the same data is required, other pieces of software are interested in our state changes, history of disconnected clients needs to be reconciled. EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 75 / 175
  146. 146. CQRS EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 76 / 175
  147. 147. CQRS To split reading from writing, to create two objects where there used to be one EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 76 / 175
  148. 148. CQRS To split reading from writing, to create two objects where there used to be one at the object level better known as CQS (by Bertrand Meyer, Eiffel | Design by Contract), usually applied at the application or service boundary, rather localized, definitely not system wide, does not require but can benefit from a task based UI event sourcing messaging eventual consistency EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 76 / 175
  149. 149. CQRS - Example Imagine a service to maintain customers ... EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 77 / 175
  150. 150. CQRS - Example Imagine a service to maintain customers ... Before public interface CustomerService { void MakeCustomerPreferred(CustomerId id); Customer GetCustomer(CustomerId id); CustomerSet GetCustomersWithName(Name name); CustomerSet GetPreferredCustomers(); void ChangeCustomerLocale(CustomerId id, Locale locale); void CreateCustomer(Customer customer); void EditCustomerDetails(CustomerDetails details); } EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 77 / 175
  151. 151. CQRS - Example Imagine a service to maintain customers ... After public interface CustomerWriteService { void MakeCustomerPreferred(CustomerId id); void ChangeCustomerLocale(CustomerId id, Locale locale); void CreateCustomer(Customer customer); void EditCustomerDetails(CustomerDetails details); } EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 78 / 175
  152. 152. CQRS - Example Imagine a service to maintain customers ... After public interface CustomerReadService { Customer GetCustomer(CustomerId id); CustomerSet GetCustomersWithName(Name name); CustomerSet GetPreferredCustomers(); } EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 79 / 175
  153. 153. CQRS - Origins Traditional Architecture EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 80 / 175
  154. 154. CQRS - Origins Traditional Architecture Data Store Model Application Services Service Boundary Client Legend Data EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 80 / 175
  155. 155. CQRS - Origins Traditional Architecture EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 81 / 175
  156. 156. CQRS - Origins Traditional Architecture Advantages Simple Repeatable EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 81 / 175
  157. 157. CQRS - Origins Traditional Architecture Advantages Simple Repeatable Disadvantages Noun centric Read & write mismatch resulting in lots of mapping Anemic & structural (*) Little logic / mostly transaction script (*) Loss of intent / decision EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 81 / 175
  158. 158. CQRS - Origins Capture intent EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 82 / 175
  159. 159. CQRS - Origins Capture intent Data Store Model Application Services Service Boundary Client Legend Data Command EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 82 / 175
  160. 160. CQRS - Origins Split writing and reading EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 83 / 175
  161. 161. CQRS - Origins Split writing and reading Data Store Model Command Handling Query Handling Service Boundary Client Legend Data Command EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 83 / 175
  162. 162. CQRS - Origins Split at the service boundary EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 84 / 175
  163. 163. CQRS - Origins Split at the service boundary Data Store Model Command Handling Service Boundary Query Handling Service Boundary Client Legend Data Command EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 84 / 175
  164. 164. CQRS - Origins Split at the data boundary EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 85 / 175
  165. 165. CQRS - Origins Split at the data boundary Data Store Data Store Model Command Handling Query Handling Service Boundary Client Legend Data Command EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 85 / 175
  166. 166. Event Sourcing meets CQRS EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 86 / 175
  167. 167. Event Sourcing meets CQRS Split writing and reading using events EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 86 / 175
  168. 168. Event Sourcing meets CQRS Split writing and reading using events Event Store Data Store Model Command Handling Projections Query Handling Service Boundary Client Legend Data Command Event EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 86 / 175
  169. 169. Event Sourcing meets DDD What changes? EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 87 / 175
  170. 170. Event Sourcing meets DDD What changes? Entities become event sourced, Events become part of the model, Repositories deal with streams, events and event stores. EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 87 / 175
  171. 171. Event Sourcing meets DDD What changes? Entities become event sourced, Events become part of the model, Repositories deal with streams, events and event stores. What remains? EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 87 / 175
  172. 172. Event Sourcing meets DDD What changes? Entities become event sourced, Events become part of the model, Repositories deal with streams, events and event stores. What remains? the importance of language, the focus on the domain one is active in, models to tackle problems, strategic design there of, other tactical patterns (e.g. Value Objects, Services, Factories, etc.) EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 87 / 175
  173. 173. Event Sourcing meets DDD EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 88 / 175
  174. 174. Event Sourcing meets DDD EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 88 / 175
  175. 175. Common Problems & Solutions EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 89 / 175
  176. 176. How do I perform analysis and design for event sourcing? EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 90 / 175
  177. 177. Solution Apply event storming to uncover the events, commands, entities, boundaries, processes at play in your domain - https://www.eventstorming.com/ Apply event modeling if you have a good grasp of the personas, ux and/or ui, integrations, processes at play in your domain - https://eventmodeling.org/ Apply domain story telling if you want to uncover actors, work objects, actions but above all scenarios at play in your domain - https://domainstorytelling.org/ Learn about state machines to model the life cycle of entities - use visual methods to uncover invariants and when each behavior is possible - unravel and challenge accidental complexity Pay attention to the language and temporal aspects in your domain Note: though event sourcing may warrant different analysis and design techniques, that doesn't mean existing methods are obsolete. EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 91 / 175
  178. 178. So ... how do I write event sourced entities? EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 92 / 175
  179. 179. Solution Conceptual Model EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 93 / 175
  180. 180. Solution Conceptual Model CH E ES RS CH = Command Handler (Controller / Actor) E = Entity ES = Event Store (Client / Repository) EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 93 / 175
  181. 181. Solution Flow for a new entity EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 94 / 175
  182. 182. Solution Flow for a new entity CH E ES EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 94 / 175
  183. 183. Solution Flow for an existing entity EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 95 / 175
  184. 184. Solution Flow for an existing entity CH E ES EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 95 / 175
  185. 185. Solution Stream EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 96 / 175
  186. 186. Solution Stream stream-x EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 96 / 175
  187. 187. Solution Stream stream-x E1 T1 EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 97 / 175
  188. 188. Solution Stream stream-x E1 E2 T1 T2 EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 98 / 175
  189. 189. Solution Stream stream-x E1 E2 E3 E4 T1 T2 T3 EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 99 / 175
  190. 190. Solution Stream stream-x E1 E2 E3 E4 ... T1 T2 T3 EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 100 / 175
  191. 191. Great ... but I meant in code ;-) EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 101 / 175
  192. 192. Authoring Abstractions EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 102 / 175
  193. 193. Authoring Abstractions Event Source public interface IEventSource { void RestoreFromEvents(object[] events); object[] TakeEvents(); } EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 102 / 175
  194. 194. Authoring Abstractions Event Recorder public class EventRecorder { private readonly List<object> _recorded = new List<object>(); public bool HasRecordedEvents => _recorded.Count != 0; public object[] RecordedEvents => _recorded.ToArray(); public void Record(object @event) { if (@event == null) throw new ArgumentNullException(nameof(@event)); _recorded.Add(@event); } public void Reset() => _recorded.Clear(); } EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 103 / 175
  195. 195. Authoring Abstractions Event Player public class EventPlayer { private readonly Dictionary<Type, Action<object>> _handlers = new Dictionary<Type, Action<object>>(); public void Register<TEvent>(Action<TEvent> handler) { if (handler == null) throw new ArgumentNullException(nameof(handler)); var typeOfEvent = typeof(TEvent); if (_handlers.ContainsKey(typeOfEvent)) throw new InvalidOperationException( "There's already a handler registered for the event of type " + $"'{typeOfEvent.Name}'"); _handlers.Add(typeOfEvent, @event => handler((TEvent)@event)); } // to be continued ... EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 104 / 175
  196. 196. Authoring Abstractions Event Player public void Play(object @event) { if (@event == null) throw new ArgumentNullException(nameof(@event)); if (_handlers.TryGetValue(@event.GetType(), out Action<object> handler)) { handler(@event); } } } EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 105 / 175
  197. 197. Authoring Abstractions Event Source - Explicit Player / Recorder public abstract class EventSource : IEventSource { private readonly EventPlayer Player = new EventPlayer(); private readonly EventRecorder Recorder = new EventRecorder(); protected void On<TEvent>(Action<TEvent> handler) { Player.Register<TEvent>(handler); } protected void Apply(object @event) { Player.Play(@event); Recorder.Record(@event); } // to be continued ... EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 106 / 175
  198. 198. Authoring Abstractions Event Source - Explicit Player / Recorder // continued ... void IEventSource.RestoreFromEvents(object[] events) { if(events == null) throw new ArgumentNullException(nameof(events)); if(Recorder.HasRecordedEvents) throw new InvalidOperationException( "Restoring from events is not possible when an instance " + "has recorded events."); foreach(var @event in events) Player.Play(@event); } // to be continued ... EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 107 / 175
  199. 199. Authoring Abstractions Event Source - Explicit Player / Recorder // continued ... object[] IEventSource.TakeEvents() { if(!Recorder.HasRecordedEvents) return Array.Empty<object>(); var recorded = Recorder.RecordedEvents; Recorder.Reset(); return recorded; } } EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 108 / 175
  200. 200. Authoring Abstractions Event Source - Explicit Player / Recorder - Usage public class RestaurantService : EventSource { public void ReserveTable(MemberId member, GuestCount guests, TimeSlot timeSlot, Text occasion, Text specialRequest) { // .. guards, conditional and computational logic here Apply(new TableReserved { RestaurantId = this.restaurantId, Date = this.date, Time = timeSlot, TableReference = availableTable, MemberId = member, Guests = guests, Occasion = occasion, SpecialRequest = specialRequest }); } } //continued EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 109 / 175
  201. 201. Authoring Abstractions Event Source - Explicit Player / Recorder - Usage private readonly HashSet<TableReference> tablesTaken = new HashSet<TableReference>(); private RestaurantService() { On<RestaurantTableWasReserved>(@event => { this.tablesTaken.Add(new TableReference(@event.Table)); }); On<RestaurantServiceScheduled>(@event => { this.restaurantId = new RestaurantId(@event.RestaurantId); this.date = @event.Date; this.serviceHours = TimeRange.From(@event.ServiceHours); }) } } EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 110 / 175
  202. 202. Authoring Abstractions Recommendations EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 111 / 175
  203. 203. Authoring Abstractions Recommendations Don't do stream version management in a base / entity class. Do put the expected version on a base / entity class if that's how you go from the read path to the write path. Don't mix command handling and entities. Don't overdo it with too much framework - kills creativity. Be idiomatic with regard to your programming language - e.g. it looks very different in a functional programming language. EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 111 / 175
  204. 204. How come my events look like property sourcing? EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 112 / 175
  205. 205. Pattern Property sourcing is an event sourcing anti-pattern where each change to a field / property causes an event. EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 113 / 175
  206. 206. Pattern Property sourcing is an event sourcing anti-pattern where each change to a field / property causes an event. Forces Any products that require arbitrary or a high degree of customization at the field level (e.g. ERP systems). Solutions If accidental, stop and align your commands / events with the actual use cases instead of this. If on purpose, expect your streams to become very chatty and have low domain relevance - even to the point where you'll have to infer what happened - which kinda defeats the purpose of event sourcing. EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 113 / 175
  207. 207. How come my events only have verbs that sound like I'm building an expensive database? EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 114 / 175
  208. 208. Pattern Event names in event sourcing that have a lot of Create, Update, Delete in them are an anti pattern. EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 115 / 175
  209. 209. Pattern Event names in event sourcing that have a lot of Create, Update, Delete in them are an anti pattern. Solutions Focus on building task based user interfaces that capture use cases an end-user / automated part of the system is trying to achieve. If you focus on UX and domain first, language will follow. Accept that sometimes the domain is not interesting or there's nobody there that can really explain it - maybe you shouldn't be trying to apply event sourcing here. EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 115 / 175
  210. 210. How do I enforce set constraints? EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 116 / 175
  211. 211. Use Case - Email addresses uniqueness EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 117 / 175
  212. 212. Use Case - Email addresses uniqueness Solution EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 117 / 175
  213. 213. Use Case - Email addresses uniqueness Solution EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 118 / 175
  214. 214. Use Case - Monotonic invoice numbers EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 119 / 175
  215. 215. Use Case - Monotonic invoice numbers Solution EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 119 / 175
  216. 216. Use Case - Monotonic invoice numbers Solution EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 120 / 175
  217. 217. How do I handle failure? EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 121 / 175
  218. 218. Unexpected Failure EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 122 / 175
  219. 219. Unexpected Failure Solution EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 122 / 175
  220. 220. Expected Failure EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 123 / 175
  221. 221. Expected Failure Solution EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 123 / 175
  222. 222. How do I deal with validation and authorization? EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 124 / 175
  223. 223. Solution EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 125 / 175
  224. 224. How do I deal with large payloads? EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 126 / 175
  225. 225. Pattern - Claim Check Store message data in another store and pass a Claim Check to subsequent components via commands and/or events. These components can use the Claim Check on the command and/or event to retrieve the stored information. EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 127 / 175
  226. 226. Pattern - Claim Check Store message data in another store and pass a Claim Check to subsequent components via commands and/or events. These components can use the Claim Check on the command and/or event to retrieve the stored information. EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 127 / 175
  227. 227. Pattern - Claim Check - Solution 1 EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 128 / 175
  228. 228. Pattern - Claim Check - Solution 2a EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 129 / 175
  229. 229. Pattern - Claim Check - Solution 2b EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 130 / 175
  230. 230. How do I integrate with other systems? EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 131 / 175
  231. 231. Solution EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 132 / 175
  232. 232. Solution EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 133 / 175
  233. 233. How do I cope with time and scheduling? EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 134 / 175
  234. 234. Pattern Time can be represented as a series of events that mimick the ticking of the clock EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 135 / 175
  235. 235. Pattern Time can be represented as a series of events that mimick the ticking of the clock when the granularity is coarse grained (days, months, years, dates) when the observation of the clock ticking at the right time is less important than knowing the clock ticked, i.e. reduced precision you'll have to think about the timezone the clock is ticking in and whether or not that is important for your observers EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 135 / 175
  236. 236. Solution Time as a stream of events - V1 T1 EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 136 / 175
  237. 237. Solution Time as a stream of events - V1 T1 T2 EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 137 / 175
  238. 238. Solution Time as a stream of events - V1 T1 T2 T3 EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 138 / 175
  239. 239. Solution Time as a stream of events - V1 T1 T2 T3 T4 EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 139 / 175
  240. 240. Solution Time as a stream of events - V1 T1 T2 T3 T4 T5 EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 140 / 175
  241. 241. Solution Time as a stream of events - V2 T1 EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 141 / 175
  242. 242. Solution Time as a stream of events - V2 T1 T2 EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 142 / 175
  243. 243. Solution Time as a stream of events - V2 T2 EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 143 / 175
  244. 244. Solution Time as a stream of events - V2 T2 T3 EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 144 / 175
  245. 245. Solution Time as a stream of events - V2 T3 EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 145 / 175
  246. 246. Solution Time as a stream of events - V2 T3 T4 EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 146 / 175
  247. 247. Solution Time as a stream of events - V2 T4 EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 147 / 175
  248. 248. Solution Time as a stream of events - V2 T4 T5 EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 148 / 175
  249. 249. Solution Time as a stream of events - V2 T5 EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 149 / 175
  250. 250. Help! My stream is too long! EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 150 / 175
  251. 251. Pattern Snapshotting is the act of taking a copy of the state of an entity at a certain version in the stream EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 151 / 175
  252. 252. Pattern Snapshotting is the act of taking a copy of the state of an entity at a certain version in the stream typically implemented as a memento on the entity, can be stored inside the stream or elsewhere, it needs to know what it is a snapshot of, can be negotiated (e.g. different snapshots for different versions of the software), can be performed while appending to the stream or as a separate process, beware that if your entity's state changes, your snapshot might become invalidated. EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 151 / 175
  253. 253. Snapshotting EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 152 / 175
  254. 254. Snapshotting EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 153 / 175
  255. 255. Snapshotting EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 154 / 175
  256. 256. Pattern Superseding is the act of starting off a new stream that only copies the relevant state as its initial event and makes the old stream point to the new stream. EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 155 / 175
  257. 257. Pattern Superseding is the act of starting off a new stream that only copies the relevant state as its initial event and makes the old stream point to the new stream. could be based on last event time, stream age, stream depth, something else ... useful pattern to break up large streams which seem to be never ending only useful if not the entire history is needed to make the next decision EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 155 / 175
  258. 258. Superseding EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 156 / 175
  259. 259. How does testing work with event sourcing? EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 157 / 175
  260. 260. Testing Definition Scenario Scenario Builder Example EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 158 / 175
  261. 261. Testing The act of verifying that a command handler and the event source affected behave as expected ... EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 159 / 175
  262. 262. Testing The act of verifying that a command handler and the event source affected behave as expected ... written as a specification, preferably executed as an integration test with the event store (*), usually integrated with a unit testing framework EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 159 / 175
  263. 263. Testing Anatomy of scenario CommandHandler Givens When Thens / Throws EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 160 / 175
  264. 264. Testing Anatomy of scenario builder EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 161 / 175
  265. 265. EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 162 / 175
  266. 266. EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 163 / 175
  267. 267. Testing Example public class RestaurantReservationScenarios { [Fact] public Task when_reserving_a_table() { return new Scenario() .Given(EmptyRestaurantService.SetupFor(Today)) .When(new ReserveTable { RestaurantId = Restaurants.Default, Date = Today, Time = "19:00", MemberId = Members.Default, Guests = 2, Occasion = Text.None, SpecialRequest = Text.None }) .Then(RestaurantService.Today, new TableReserved { RestaurantId = Restaurants.Default, Date = Today, Time = "19:00", TableReference = Tables.DefaultFor(2), MemberId = Members.Default, Guests = 2, Occasion = Text.None, SpecialRequest = Text.None }).AssertAsync(); } } EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 164 / 175
  268. 268. Testing Example public class RestaurantReservationScenarios { [Fact] public Task when_reserving_a_table_while_fully_booked() { return new Scenario() .Given(FullyBookedRestaurantService.SetupFor(Today)) .When(new ReserveTable { RestaurantId = Restaurants.Default, Date = Today, Time = "19:00", MemberId = Members.Default, Guests = 2, Occasion = Text.None, SpecialRequest = Text.None }) .Throws(new AllTablesTakenAtTimeException( RestaurantService.Today, Today, "19:00" ).AssertAsync(); } } EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 165 / 175
  269. 269. Testing Recommendations Try to find the right level of abstraction to write tests at, For scenario driven tests that means being able to change your implementation without having to touch your tests, Try to assert that only what you expected occurred and nothing else, Keep the boilerplate / distraction out of your tests, Value objects and test data generation help anonymize / randomize valid values. EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 166 / 175
  270. 270. What should I be looking for while applying event sourcing? EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 167 / 175
  271. 271. Stream Patterns Long vs Short Lived EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 168 / 175
  272. 272. Stream Patterns Slow vs Fast Changing EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 169 / 175
  273. 273. Stream Patterns Low vs High Volume EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 170 / 175
  274. 274. Stream Patterns Beginning vs Ending EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 171 / 175
  275. 275. Stream Patterns Cyclic Behavior EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 172 / 175
  276. 276. Common Problems and Solutions Questions? EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 173 / 175
  277. 277. The End Join the DDD-ES-CQRS community http://j.mp/ddd-es-cqrs Reading Material Versioning in an Event Sourced System https://leanpub.com/esversioning EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 174 / 175
  278. 278. EventSourcing Xplained - © BitTacklr 2019 - @yreynhout - yves.reynhout@bittacklr.be 175 / 175

×