Please enable JavaScript.
Coggle requires JavaScript to display documents.
Event Sourcing - Coggle Diagram
Event Sourcing
Pros
Audit
We can expose the audit trail to the support group so they can walk through a user's interaction. While Event Sourcing is a good way of doing this, you could also do this with more regular logging mechanisms.
-
Audit Log
An audit log is the simplest, yet also one of the most effective forms of tracking temporal information.
-
Debugging
we usually use log files for debugging production problems. But Event Sourcing can go further, allowing you to create a test environment and replay the events into the test environment to see exactly what happend, with the ability to stop, rewind, and replay just like you can when executing tests in a debugger.
This can be particularly valuable to do parallel testing before putting an upgrade into production. You can replay the actual events in your test system and test that you get the answers you expect.
-
-
Memory image
If I have a log of all my changes - why do I need a relational database? I could keep everything in memory. Have a purely in-memory system.
Lmax was a company that built a retail system which was written in Java, totally in memory on a single core and working with 6 millions of transactions per second. Snapshot was created every day and if one system went down, another was getting up immediately. There was no relational database.
high performance
-
If the system of record is the event log, there is are plenty of options for very high performance since the event log is a purely additive structure that requires minimal locking.
-
allows new applications to be added easily by tapping into the event streams and populating their own models, which don't need to be the same for all systems. It's an approach that fits in very well with a messaging approach to integration.
Event Collaboration
In this style you never have one component asking another to do anything, instead each component signals an event when anything changes. Other components listen to that event and react however they wish to.
-
-
Event Collaboration isn't mandatory when using events in applications, also the choice between Event Collaboration and request/response isn't an exclusive choice.
pros/ cons
pros
Event Collaboration results in very loose coupling which makes it particularly easy to add new components to a system without needing to modify existing components.
Event Collaboration helps keep each component simple. All they need to know of the world is the events they listen to. Whenever anything interesting happens they emit an event - they don't even need to care if anyone else is listening. This allows developers to focus on one component at a time - a component with very well controlled inputs.
The great strength of Event Collaboration is that it affords a very loose coupling between its components; this, of course, is also its great weakness.
A system that uses Event Collaboration is more resilient to breakdowns. Since each component has all it needs to operate it can continue working even if communication to the outside world is lost.
cons
A component may continue operating, but it will be working on out of date information if it's not receiving events as things change. It may therefore initiate actions based on out of date information. With request collaboration, it would just not work - which in some scenarios may be preferable.
With Event Collaboration you don't know who is listening to the events until run-time - which in practice means you can only find the links between the components in configuration data - and there may be multiple areas of configuration data. As a result these interactions are hard to find, understand and debug.
Since each participant stores all the data that it needs, a lot of data will get replicated.
-
Multiple components work together by communicating with each other by sending events when their internal state changes.
If all communication uses Event Collaboration then that removes the need for an event sourced application to use gateways on its inputs to mimic event communication.
Test for truly Event Sourcing Architecture : at any time we can blow application's state and recreate it from logs.
Example of Event Sourced system is Version Control. Application's state is a tree of files and log is a history of commits.
Event sourcing is basically providing to your users a system that works on their data the way version control works on your code.
Snapshot is a joined set of commits/events which e.g. are summaries of bank account balance in a specific year .
The key to Event Sourcing is that we guarantee that all changes to the domain objects are initiated by the event objects.
Here we have Application State (current state of the world) and the Application Log (kind of a history) .
-
Domain event
-
The essence of a Domain Event is that you use it to capture things that can trigger a change to the state of the application you are developing. These event objects are then processed to cause changes to the system, and stored to provide an Audit Log.
Each Domain Event captures information from the external stimulus. Since this is logged and we want to use the log as an audit trail, it's important that this source data is immutable.
it's important to consider two Time Point that could be stored with the event: the time the event occurred in the world and the time the event was noticed, these correspond to the notions of actual and record time.
-
As well as source data the events may also carry processing data which describes what we've done with the event. It's important to distinguish between the two. In particular an event's source data is immutable - it's what we know of what happened, and we can't easily change it.
Cons
-
External systems
You have to think of saving events received from external systems and make it a part of replay mechanism.
-
-
stale data
The reader systems are liable to be out of sync with the master (and each other) due to differences in timing with event propagation
parallel model
Allow an alternative representation of the state of an application, either at a different time or in a hypothetical state.
allows us to easily take our entire information store and represent it as it was in the past or as it might be in some alternative past, present, or future.
to use it what you'll need is a way to process events in a model that's separated from the usual reality. There are broadly two ways to do this. One is to construct a Parallel System which is a separate copy of the application with its own database and environment. The other is to allow a single system to be able to switch between embedded parallel models.
One of the benefits of using a parallel system is that you also have the ability to change the source code of the parallel system. With a parallel system you can make any change you like to the source code of the application and see the consequences of this on the event stream.
Embedded Parallel Models
If you want to embed multiple Parallel Model into an application you'll need to ensure any peristant storage can easily be switched between multiple actual data sources. A good way to do this is to use a Repository and provide a mechanism for the application to be able to switch Repositorys at runtime.
Temporary Repositorys needn't be persistent - since Parallel Model tend to be temporary they can often be assembled in memory.
Reversing Events
-
If the input events don't follow the difference approach, then the event should ensure it stores everything needed for reversal during processing.
You can do this by storing the previous values on any value that is changed, or by calculating and storing differences on the event.
A good place to store this prior data is on the event itself. Since the domain objects have the event to hand, they can easily store information on the event for them.
It's worth remembering that all the capabilities of reversing events can be done instead by reverting to a past snapshot and replaying the event stream. However it may make a big difference to efficiency.
If there's no need to reverse events, then then it's easy to make a Domain Model ignorant of the event log. Reversing logic makes this more tricky since the Domain Model needs to store and retrieve the prior state, which makes it much more handy for the Domain Model to be aware of the event log.
external systems
One of the tricky elements to Event Sourcing is how to deal with external systems that don't follow this approach (and most don't).
External Updates
Another tactic that you might see with external systems is buffering the external notifications by time.
It may be that we don't need to make the external notification right away, instead we only need to do it at the end of the month. In this case we can reprocess more freely until that time appears.
We can deal with this either by having gateways that store external messages till the release date, or triggering the external messages through a notification domain event rather than doing the notification immediately.
Many of the advantages of Event Sourcing stem from the ability to replay events at will, but if these events cause update messages to be sent to external systems, then things will go wrong because those external systems don't know the difference between real processing and replays.
-
External Queries
The primary problem with external queries is that the data that they return has an effect on the results on handling an event.
If I ask for an exchange rate on December 5th and replay that event on December 20th, I will need the exchange rate on Dec 5 not the later one.
It may be that the external system can give me past data by asking for a value on a date. If it can, and we trust it to be reliable, then we can use that to ensure consistent replay.
It also may be that we are using Event Collaboration, in which case all we have to ensure we retain the history of changes.
One approach is to design the gateway to the external system so that it remembers the responses to its queries and uses them during replay. To be complete this means that the response to every external query needs to be remembered.
External Interaction
Both queries and updates to external systems cause a lot of complication with Event Sourcing. You get the worst of both with interactions that involve both. Such an interaction might be an external call that both returns a result (a query) but also causes a state change to the external system, such as submitting an order for delivery that return delivery information on that order.
-
Code Changes
New features
If you want to take advantage of the new features with old events you can just reprocess the events and the new results pop up.
When reprocessing with new features you'll usually want the external gateways turned off, which is the normal case.
Bug fixes
For internal stuff this is really easy to fix, all you need to do is make the fix and reprocess the events.
Again external gateways bring the complexity. Essentially the gateways need to track the difference between what happened with the bug, and what happens without it.
The idea is similar to what needs to happen with Retroactive Events. Indeed if there's a lot of reprocessing to consider it would be worth actually using the Retroactive Event mechanism to replace an event with itself, although to do that you'll need to ensure the event can correctly reverse the buggy event as well as the correct one.
temporal logic
This kind of stuff needs to actually go into the domain model itself. The domain model should be able to run events at any time with the correct rules for the event processing. You can do this with conditional logic, but this will get messy if you have much temporal logic. The better route is to hook strategy objects into a Temporal Property: something like chargingRules.get(aDate).process(anEvent).
Temporal Property
Usually when we see properties on a class, they represent questions we can ask of an object now. However there are times when we don't want to just ask questions about a property of an object now, we also want to ask these questions about some point in the past when things may have changed.
You will always see an accessor function that takes a Time Point as an argument: this allows you to ask "what was Mr Fowler's address on 2 Feb 1998?". In addition you'll usually see an accessor that takes no argument, this is a question about an address according to some default, usually today.
how to implement it
-
temporal collection
The basic representation and interface for a temporal collection is similar to a map: provide a get and put operation that uses a date as an index.
However once you find yourself doing this more than once you'll realize that it may be best to create a special collection class that provides this behavior: a temporal collection. Such a class is quite easy to write and can be used whenever you need a Temporal Property.
You should use a Temporal Property when you have a class that has a few properties that display temporal behavior, and you want easy access to those temporal values.The easiest way to record temporal changes is to use Audit Log. The disadvantage of Audit Log is that you need extra work to process the log. So the first thing you need to know is under what circumstances people will need the history of that property.
-
bi-temporal
bi-temporal property allows us to store historic information over time and retain a full history across both dimensions. When we are storing bi-temporal history the record date is always today.
bi-temporal collection is a temporal collection whose elements are temporal collections. Each temporal collection is a picture of record history.
There is potentially an overlap between dealing with bugs and temporal logic when old events need to be processed using the the buggy code. This may lead into bi-temporal behavior: "reverse this event according to the rules for Aug 1 that we had on Oct 1 and replace it according to the rules for Aug 1 that we have now".
Some of these issues can be handled by putting the code in the data. Using Adaptive Object Models that figure out the processing using configurations of objects is one way to do this. Another might be embed scripts into your data using some directly executable language that doesn't require compilation - embedding JRuby into a Java app for example.
Temporal Object
consider how many properties are temporal. If most of the properties of the class are temporal, then you'll need to use Temporal Object
-
-
aka Version History, aka History on Self
Event handler logic
Transaction Script
Organizes business logic by procedures where each procedure handles a single request from the presentation.
Transaction Scripts are better for simple logic and a Domain Model is better when things get more complicated.
logic
-
-
You can combine these together, essentially this is the Transaction Script approach, but you can also separate them by putting the processing selection logic in the event processing system, and it calls a method in the domain model that contains the processing domain logic.
Once you've made that decision, the next is whether to put the processing selection logic in the event object itself, or have a separate event processor object.
The problem with the processor is that it necessarily runs different logic depending on the type of event, which is the kind of type switch that is abhorrent to any good OOer. All things being equal you want the processing selection logic in the event itself, since that's the thing that varies with the type of event.
Of course all things aren't always equal. One case where having a separate processor can make sense is when the event object is a DTO which is serialized and de-serialized by some automatic means that prohibits putting code into the event. In this case you need to find selection logic for the event. My inclination would be to avoid this if at all possible, if you can't then treat the DTO as an hidden data holder for the event and still treat the event as a regular polymorphic object. In this case it's worth doing something moderately clever to match the serialized event DTOs to the actual events using configuration files or (better) naming conventions.
DTO
the main reason for using a Data Transfer Object is to batch up what would be multiple remote calls into a single call
-
-
If there's no need to reverse events, then then it's easy to make a Domain Model ignorant of the event log. Reversing logic makes this more tricky since the Domain Model needs to store and retrieve the prior state, which makes it much more handy for the Domain Model to be aware of the event log.
-
-
Application State
-
application state is purely derivable from the event log, you can cache it anywhere you like.
-