📜 ⬆️ ⬇️

Lazy event sourcing or how to live for today

Translation of an article published on Eventsourcing Publications . The article describes some of the ideas applied in the Eventsourcing project.

If you read the article by Fowler or similar sources on the topic of event sourcing, you could have a picture like this in your brain:

image
')
The general idea of ​​this approach is that the user (or any other external system) generates commands, we process them, adding the received events to the event store and updating the “state of the world” in the database, the data from which is requested by the user.

This approach looks simple and beautiful. We have enough data to "replay" events, we have from where to request data on the state of the world and we can use time-tested databases. On the other hand, I noticed that I wanted a little different from the concept of event sourcing. I wanted to avoid predicting the future and this model was somehow not very suitable, because I had to write the updated state to my database “for reading”.



The very idea that we are collecting intentions for actions and all the accompanying data leads to the idea that you can always look into the past and use information from which there was not much sense in collecting this information (but now there are new observations, new functionality, etc.) What does this mean? Do I need to update my database schema to support new structures? Do I have to replay all the events to refill the database?

To be honest, I would like to avoid such difficulties.

During my career I have developed enough projects to understand a few simple truths. One of these truths - the most constant thing - is change. In fact, there is no normal way to know how your application and data model will look like in a few months. It can only be after all three times from scratch were rewritten, and even that is in question.

What if I can postpone guessing the future until I’m actually in this very future? As I record every event, I can always rebuild the “state of the world”, losing all the old events once again, but, as I noted earlier, this is a very expensive pleasure.

But what if I can just send requests to search for events that fall under the necessary criteria, right during the request from the user? For example, imagine that we have users and they have email addresses. Suppose we created the UserCreated and EmailChanged events. What if instead of replaying all events for all users (or even for one!), We’ll just look for UserCreated (id:) and the last EmailChanged (userId:)?

Hm We can request the necessary information about users only when necessary, without replaying events!

// Pseudocode-ish User's email retrieval public class User { public String email() { return query(equal(EmailChanged.ID, id), descending(EmailChanged.TIMESTAMP)).first(). email(); } 


If the algorithm for determining the user's email has ever changed, all we need to do is change the User # email () method. Moreover, until I write the User # email () method myself, I don’t need to know that this is how I will structure the data for the presentation. I just have to write down all the data in my events, if possible without missing anything.

Even more interestingly, this approach leads to the following conclusion: in fact, there is no universal version of the “state of the world.” Just as we, people, perceive the world and reality around us differently, depending on the context, programs can perceive reality through different prisms and I see no reason why they should be limited in this.

Are there any problems with this approach? Of course. For example, if any of your search requests take a long time. But, when such bottlenecks are detected, they can be optimized through some kind of preprocessing or caching. It would be nice to avoid expensive requests, of course, but we live in the real world.

Does this mean that we should not have event handlers at all that are executed during event recording? I do not think this is a good way to respond to changes, especially in domains that are implemented by third-party components. I just do not see the point in doing this for each event.

Here, by the way, is another interesting consequence of using this approach. With the growing popularity of GraphQL as an API, more and more applications optimize the amount of data transferred and the number of requests, requesting and receiving only the minimum that they need. Together with the "lazy" collection of data from events, we never build a "state of the world" on those parts of the data that are not requested.

The above approach is used in the Events project, including its extension called Domain Protocol. The project also has an adapter to GraphQL . The project is fully open and licensed under the Mozilla Public License 2.0. A non-profit organization, Eventsourcing, Inc., was recently created. for further development and project support.

Source: https://habr.com/ru/post/300956/


All Articles