Posting to an API and returning result of a command when the backend is event sourced


We have a situation where we have a very low traffic endpoint (few transaction per day) where people can post new versions of some data. The endpoint accepts the data and calculates a new version number (to prevent users from accidentally miscalculating the version number incorrectly) which it will return to the user. The backend behind this API we want to make event sourced (there is a requirement to output an event to say that a new version of this resource has been created and having the events be the source of truth here makes this easier), but we would rather not enforce all clients to post to the API then eventually receive the event to say that the update has been done (as this complicates the usage patterns for all clients) but would rather have client be able to call to POST and get the new version number back.

To solve this we have been considering a pattern where when the API controller recieves the POST call it sends a command to do the actual update, then subscribes to the stream where the event will be created, When the event arrives it reads the version number, and returns this t the client. Obviously some timeout needs to exist etc.

Is this a reasonable solution? Is there a better way to handle this situation?



Here’s what we do. On return of the POST we redirect to the view with an additional query parameter for the commit log position of the written events. A generic request filter detects the parameter on GET and asks a service which always subscribe to events to wait until the given position has been seen, at least. The GET then proceeds, knowing that it will have read your writes semantics.

This is how event store works internally.

Out of curiosity can a command ever result in multiple events? If so
you might consider something more like returning a location reference
to an atom feed where the events will later appear.

Don’t know if it’s a better solution necessarily, but we return a 200 to the front end as soon as the command has been added to the command log and queued for handling. We then use SignalR to inform the front end once the read model has been updated by our event handlers. Depending on the specific situation, this either contains the read model data in the event (in which case, no further call is needed to get the read model) or is just a signal that it’s now safe to make the call to get the read model.