Hi, all:
I’m writing some learning tests to understand CQRS and Axon-framework and I have an question about asynchronous event processing.
Let’s say I have two event handler on CustomerRegisteredEvent, one is synchronous to prevent duplicated customer.
@EventHandler public void on(CustomerRegisteredEvent event) {
CustomerReadModel c = transform(event);
entityManager.persiste(c);//insert a customer in a relational query database
}
The other is to send an email asynchronously.
@EventHandler public void on(CustomerRegisteredEvent event) {
System.err.println(Thread.currentThread().getId() + " sending email async");
}
Ideally, I want the email is send only when the customer is registered(ideally, inserted a row in query database). On the synchronous side, it’s fine when exception occurrs, all data is rolled back(including the event), But once the async handler receives the event, it is impossible to rollback and it makes no sense.
How can I avoid this issue. After pondering for a while, I think it’s a difficult one. when an event is published to the bus, the unit of work is committed. so all the handlers(no matter sync or async) will receives the event. Unless all async handlers subscribe another event bus and the event is dispatched to this bus after all sync (and transactional) handler finish their work.
An alternative solution is eventual consistency, do some compensating when exceptions occurrs.
By the way, it seems only infrastructure error causes this problem, if I add an intentional exception to the sync handler like:
@EventHandler public void on(CustomerRegisteredEvent event) {
CustomerReadModel c = transform(event);
entityManager.persiste(c);//insert a customer in a relational query database
throw new RuntimeException("intentionally throw");
}
Then the async handler is not invoked. Is this just a coincidence?
I would like your opinoins, thank you in advance.