Matster2
Matster2

Reputation: 147

Client Interaction With Event Sourcing

I have been recently looking into event sourcing and have some questions about the interactions with clients.

So event-sourcing sounds great. decoupling all your microservices, keeping your information in immutable events and formulating a stored states off of that to fit your needs is really handy. Having event propagate through your system/services and reacting to events in their own way is all fine.

The issue i am having lies with understanding the client interaction.

So you want clients to interact with the system, but they need to do this now by events. They can not longer submit a state to mutate your existing one.

So the question is how do clients fire off specific event and interact with (not only an event based system) but a system based on event sourcing.

My understanding is that you no longer use the rest api as resources (which you can get, update, delete, etc.. handling them as a resource), but you instead post to an endpoint as an event.

So how do these endpoint work?

my second question is how does the user get responses back? for instance lets say we have an event to place an order. your going to fire off an event an its going to do its thing. Again my understanding is that you dont now validate the request, e.g. checking if the user ordering the order has enough money, but instead fire it to be place and it will be handled in the system. e.g. it will not be - order placed - this will be picked up by the pricing service and it will either fire an reserved money or money exceeded event based on if the user can afford it. - The order service will then listen for those and then mark the order as denied or not enough credit.

So because this is a async process and the user has fired and forgotten, how do you then show the user it has either failed or succeeded? do you show them an order confirmation page with the order status as it is (even if its pending) or do you poll it until it changes (web sockets or something).

I'm sorry if a lot of this is all nonsense, I am still learning about this architecture and am very much in the mindset of a monolith with REST responses.

Any help would be appreciated.

Upvotes: 1

Views: 904

Answers (2)

iTollu
iTollu

Reputation: 1069

So you want clients to interact with the system, but they need to do this now by events.

Clients don't have to. Client may even not be aware of the underlying event store.

There are a number of trade-offs to consider and decisions to take when implementing an event-sourced system. To start with you can try to name a few pre computer era examples of event-sourced systems and look at their non-functional characteristics.

So the question is how do clients fire off specific event

Clients don't send events. They rather should express an intent (a command). Then it is the responsibility of the event-sourced system to validate the intent and either reject it or accept and store the corresponding event. It would mean that an intent to change the system's state was accepted and the stored event confirms the change.

My understanding is that you no longer use the rest api as resources REST is one of the options. You just consider different things as resources. A command can be a REST resource. An event-sourced entity can be a resource, to which you POST a command. If you like it async - you can later GET the command to check its status. You can GET an entity to know its current state. You cant GET events from a class of entities as a means of subscription.

If we are talking about an end user, then most likely it doesn't deal with the event store directly. There is some third tier in between, which does CQRS. From a user client perspective it can be provided with REST, GraphQL, SOAP, gRPC or event e-mail. Whatever transport solution you find suitable. Command-processing part from CQRS is what specifically domain-driven. It decides which intent to accept and which to reject.

Event store itself is responsible for the data consistency. I.e. it should not allow two concurrent event leading to invalid state be published. This is what pre-computer event-sourced systems are good at. You usually have some physical object as an entity, so you lock for update by just getting hand of it.

Then an end-user client usually reads from some prepared read model. The responsibility of a read (R in CQRS) component is to prepare read-optimised data for clients. This data may come from multiple event-sourced of the same or different classes. Again, client may interact with a read model with whatever transport is suitable.

While an event-store is consistent and consistent immediately, a read model is eventually consistent. But it's up to you to tune this eventuality.

Just try to throw REST out of the architecture for a while. Consider it a one of available transport options - that may help to look at the root.

Upvotes: 1

VoiceOfUnreason
VoiceOfUnreason

Reputation: 57194

The issue i am having lies with understanding the client interaction.

Some of the issue may be understanding, but I promise you a fair share of the issue is that the literature sucks.

In particular, the word "Event" gets re-used a lot of different ways. If you aren't paying very careful attention to which meaning is being used, you are going to get knotted.

Event Sourcing is really about persistence - how does a micro-server store its private copy of state for later re-use? Instead of destructively overwriting our previous state, we write new information that links back to the previous state. If you imagine each microservice storing each change of state as a commit in its own git repository, you are in the right ballpark.

That's a different animal from using Event Messages to communicate information between one microservice and another.

There's some obvious overlap, of course, because the one message that you are likely to share with other microservices is "I just changed state".

So how do these endpoint work?

The same way that web forms do. I send you a representation of a form, the client displays the form to you. You fill in your data and submit the form, the client processes the contents of the form, and sends back to me an HTTP request with a "FormSubmitted" event in the message body.

You can achieve similar results by sending new representations of the state, but its a bit error prone to strip away the semantic intent and then try to guess it again on the server. So you are more likely to instead see task based user interfaces, or protocols that clearly identify the semantics of the change.

When the outside world is the authority for some piece of data (a shopper's shipping address, for example), you are more likely to see the more traditional "just edit the existing representation" approach.

So because this is a async process and the user has fired and forgotten, how do you then show the user it has either failed or succeeded?

Fire and forget really doesn't work for a distributed protocol on an unreliable network. In most cases, at-least-once delivery is important, so Fire until verified is the more common option. The initial acknowledgement of the message might be something like 202 Accepted -- "We received your message, we wrote it down, here's our current progress, here are some links you can fetch for progress reports".

It doesnt seem to me that event-sourcing fits with the traditional REST model where you CRUD a resource.

Jim Webber's 2011 talk may help to prune away the noise. A REST API is a disguise that your domain model wears; you exchange messages about manipulating resources, and as a side effect your domain model does useful work.

One way you could do this that would look more "traditional" is to work with representations of the event stream. I do a GET /08ff2ec9-a9ad-4be2-9793-18e232dbe615 and it returns me a representation of a list of events. I append a new event onto the end of that list, and PUT /08ff2ec9-a9ad-4be2-9793-18e232dbe615, and interesting side effects happen. Or perhaps I instead create a patch document that describes my change, and PATCH /08ff2ec9-a9ad-4be2-9793-18e232dbe615.

But more likely, I would do something else -- instead of GET /08ff2ec9-a9ad-4be2-9793-18e232dbe615 to fetch a representation of the list of events, I'd probably GET /08ff2ec9-a9ad-4be2-9793-18e232dbe615 to fetch a representation of available protocols - which is to say, a document filled with hyper links. From there, I might GET /08ff2ec9-a9ad-4be2-9793-18e232dbe615/603766ac-92af-47f3-8265-16f003ce5a09 to obtain a representation of the data collection form. I fill in the details of my event, submit the form, and POST /08ff2ec9-a9ad-4be2-9793-18e232dbe615 the form data to the server.

You can, of course, use any spelling you like for the URI.

In the first case, we need something like an HTTP capable document editor; the second case uses something more like a web browser.

If there were lots of different kinds of events, then the second case might well have lots of different form resources, all submitting POST /08ff2ec9-a9ad-4be2-9793-18e232dbe615 requests.

(You don't have to have all of the forms submitting to the same URI, but there are advantages to consider).

In a non event sourcing pattern I guess that would be first put into the database, then the event gets risen.

Even when you aren't event sourcing, there may still be some advantages to committing events to your durable store before emitting them. See Pat Helland: Data on the Outside versus Data on the Inside.

Upvotes: 1

Related Questions