What is the best way to keep event store and read store in sync. how do I make sure event has been successfully written to the disk on the read side? Is there a prescribed way of dealing with this problem?
If you use the SimpleCommandBus, you can run everything in a single transaction. As soon as you need to scale horizontally, you could use a transactional queue (amqp or jms, for example) to publish the events and handle them on the read side. That should provide enough guarantees.
Does the Axon transaction functionality provide any way to generate a 2 phase commit between the event store (e.g. MongoDB) and a transactional queue (amqp) or any readstore?
Axon doesn’t have any transaction managers by itself. You can attach any transaction manager you like that provides the guarantees that you need.
How to achieve fully consistent CQRS with Axon while still storing events in an Event Store?
Event Sourcing (or the concept of events) and CQRS are closely associated with eventual consistency. But there are cases, where the domain requirements dictate full consistency.
In our project, the domain folks demand our system to be fully consistent, fearing occasional inconsistencies between read (query) model and write model caused by eventual consistency. At the same time, we need all domain objects
(aggregates) to have historical data (e.g. to be able to rebuild a historical version or analyze historical changes). Thus, Event Sourcing and CQRS seem to fit quite well except for the otherwise preferred asynchronous dispatching and processing of events. Due to the full consistency requirement we want to process the command, change the state of the aggregate object and update the query model within the same transaction. We also use Spring (Boot etc.) already.
After going through the Axon docs and forums, I have not found a way how to update teh query model synchronously and still keep the events in an event store. I Could have a Spring @Transaction transaction encompassing the command processing and updating the query model via an event sent through the SimpleEventBus, which is synchronous, right? But the simple SimpleEventBus does not provide for an Event Store. Only the EmbeddedEventStore persists events used in an Event Store, but it is asynchronous. Associating a Transaction Manager I could make the dispatching of events (e.g. in RabbitMQ) synchronous and thus part of my big transaction, but the processing of the event would still happen outside it.
Should we use SimpleEventBus and implement our own Event Store? Are there other options?