2

I'd like to ask for some help in understanding how event-sourcing systems are used when it comes to web applications and POST requests. I understand how events are stored and the event-driven architecture of eventual consistency. I understand CQRS etc, but I cannot imagine how an event store mechanism handles something like a HTML POST request when the web application in the browser has to return the changed state on the following page we're redirected to, meaning:

  1. I fill in a HTML form on a page to update some resource.

  2. I press submit to POST the data to a web application.

  3. An event is created with the data to update and the resource ID.

  4. The event is raised and will be saved in the event store eventually.

  5. The browser takes me to a different page in the web application.

  6. I issue a query request to retrieve the updated resource (through replaying events) because I want to present the user with the latest state of the resource.

  7. The query does not return the latest state because the eventual consistency hasn't taken place yet and the system still needs few milliseconds to update the event store.

  8. I see the update never took place. The resource still looks the same.

  9. The event store has saved the resource and now I can refresh the browser and see that the update has actually taken place.

What I am missing, please? It seems that there's something really simple here, but I cannot see how a web application can work with event sourcing. Are we relying on the event-sourcing being faster than the web application and assuming that the data will always be consistent before the user hits the next page? Wouldn't that be a bit risky during heavy system use?

Thank you

  • If eventual consistency is acceptable, I'd expect the response to be either a reference to the process or a redirect back to another page. Event sourcing absolutely works in a web application if it's been built with it in mind. – mgw854 Jan 25 '17 at 23:55
1

The event is raised and will be saved in the event store eventually.

That's wrong -- the event should be written into the event store immediately. The edge case that you need to be careful of here is two conflicting writes being made concurrently -- if either of those writes fails, then the caller should be notified that the command failed, making them aware of the problem and allowing them to consider the appropriate strategy.

You are correct that the read models are updated eventually, rather than immediately, which introduces some challenges.

What I am missing, please? It seems that there's something really simple here, but I cannot see how a web application can work with event sourcing. Are we relying on the event-sourcing being faster than the web application and assuming that the data will always be consistent before the user hits the next page? Wouldn't that be a bit risky during heavy system use?

There are a couple of approaches to take. One is, as you described POST-REDIRECT-GET. But we get a bit more clever about the resource that is the target of the redirection. Rather than redirecting to an arbitrary "latest" endpoint, we instead redirect to an endpoint that can identify where in event stream we should be

/foo?asOf={sequenceNumber}

Then that endpoint can block, waiting for the event to show up, or it can pro-actively create a new representation of the resource by fetching the history from the event store, or.... There are a lot of variations, but they all start from thinking about being specific about where in the history you want the representation to be created from.

(Depending on your needs, the implementation might return a representation, or might redirect to a representation once the results are available. You might be wanting to return a representation at that exact point in the history, or at any convenient point after.)

Another alternative is to construct a representation in the POST handler. The application just updated the event stream successfully, so it has all of the events in the history up to that point. You can pass that history to a bit of code that knows how to generate the view (possibly reading in other histories from the write model, or cached copies from the read model).

Another approach, useful in some circumstances, is to just return the events themselves, and let the caller reconstruct the view they expect. This approach might make sense if you were writing a single page app, you let the app update its own non-authoritative copy of the model, and work from there.

1

It all really boils down to the nature of the data you're presenting to your user. If it's transactional in nature and consistency is of paramount importance, then you're correct: An eventually consistent model likely won't work. However, if it's acceptable for the nature of the data to be latent, then eventual consistency will work fine.

For example, think of a banking system. The most recent state of a user's account and transaction history is obviously very important. Therefore, eventual consistency is likely something that won't work. However, messages that result from consistent transactions may be something that is acceptable to have (an acceptable amount of) latency. Something like, maybe a user wants to be alerted any time a transaction of over $100 has been made. That's something that /could/ be achieved through eventual consistency.

So in answer to your question, yes, eventually consistent systems /can/ absolutely work brilliantly for a web application. It all depends on the data you're dealing with.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.