How to achieve full consistency between read (query) model and write(command) model

Hi,

Scenario:
I have 2 spring-boot services acting as command and query as below.

  1. Command-Service: Responsible for handling commands, events, maintaining aggregate’s state and storing data into database.
  2. Query-Service: Responsible for handling queries in order to fetch data from databse.

Please note that both services are sharing the same instance of axon-server and also the same databse(in this case ElsaticSearch).

My UI is designed in such a way that when user submits the form to create data, an ajax call happens which in turn performs 2 rest calls in below order:

  1. First call is a post request which goes to Command-Service which performs below:
  • Creates a CreateDataCommand object with formdata and fires the same as below: org.axonframework.commandhandling.gateway.CommandGateway.sendAndWait( CreateDataCommand).
  • The CreateDataCommand is handled in the aggregate which fires DataCreatedEvent:
    @CommandHandler
    private DataAggregate(CreateDataCommand createDataCommand ) {
    AggregateLifecycle.apply(new DataCreatedEvent ());
    }
  • DataCreatedEvent is handled at 2 places,
    1. In the Aggraget itself, where the Aggregate updates its state:
      @EventSourcingHandler
      private void on(AppCreatedEvent appCreatedEvent) {
      // updated aggregate’s state
      }
    2. In the Projection, Which saves data into the database.
      @EventHandler
      private void on(AppCreatedEvent appCreatedEvent) {
      // Saves data to database.
      }
  1. Upon sucessful execution of above the ajax immediately sends a get request to Query-Service which performs below:
  • Fires GetDataQuery query as below: org.axonframework.queryhandling.QueryGateway.query(GetDataQuery, ResponseType).
  • The GetDataQuery is handled to fetch data from database as below:
    @QueryHandler
    List getData(GetDataQuery getDataQuery){
    // hits the databse and returns data.
    }

Problem:
Even though the data is being saved into the database by Command-Service, the call to Query-Service is triggred and it always returns empty list. On second call onwards it returns the correct data. This is happening because Query-Service hits the database before Command-Service finishes*.*

While going through some posts on the forum i learnt that axon never wait for an event being handled when sending a command. The responsibility of the command stops at publishing the results of that command (i.e. events).

Can someone help me in achieving the full consistency or find a way to eradicate the side effects that are occurring on account of above phenomenon.

Hi Rohit,

First and foremost I feel obliged to tell you this mailing list will be discontinued as of the 28th of September 2020.
Instead, we’ve set up https://discuss-next.axoniq.io/, as it provides us a better means to help anyone who’s searching for Axon information.
On top of that, the forum style should promote a more free format so that other users (outside of the AxonIQ work pool) can also help out people.

Having said that, let us move over to your consistency question.
Using a message driven set up like this, embracing CQRS so to say, somewhat enforces you to cope with the eventual consistency you are pointing out.
The most optimal way to deal with this, is to embrace that fact exactly, and deal with information retrieval in a different way.

Thus instead of immediately performing a query after a command, you should subscribe yourself to the results of the updates on the query model.

You could for example build a solution based on WebSockets where you subscribe to a given model.

Use SSE to share the fact the data is present.
Or use the more recent Reactive movement, and utilizes Mono’s and Flux’ to tap into the results as they go.

Especially the latter is something Axon supports more directly with it’s subscription query, and more recently as well with the Reactor Extension.

Hope this helps you further Rohit!

Cheers,
Steven

Hi Steven,

Thanks for the response.

Can i use something like org.axonframework.extensions.reactor.queryhandling.gateway.ReactorQueryGateway.subscriptionQuery(FindDataByIdQuery, ResponseType, ResponseType).repeatWhen() inside the Command-Service to check whether the data has been created in the database or not and will return success response to ajax only if the data is created.

please reply.

thanks