Unit of Work and Software Transaction Memory

Commandposted(command)
SERVER crashed here

Commandhandler(Command){
SERVER CRASHED HERE
eventBus.publish(CommandDoneEvent)
// OR SERVER CRASHED HERE
}
eventhandler1(CommandDoneEvent)
{
// OR SERVER CRASHED HERE

}
startSaga
eventhandler2(CommandDoneEvent)
// OR SERVER CRASHED HERE
EndSaga
eventhandler3(CommandDoneEvent)
//OR SERVER CRASHED HERE
evenhHandler4(CommandDoneEvent)

I understand unit of work concept available in Axon is there to help. I am not using event repository but traditional RDBMS using JPA repository. I am not doing event sourcing too.
Will unit of work help in ACID property if I put these in a uow block?

Or, are there any other levers available apart from this?

Regards
Udaya

Hi,

the Unit of Work itself doesn’t guarantee any transactional behavior. It is used to coordinate (and time) activities of components. For example, it ensures events aren’t published until the command has been handled completely. For transactional support, you can attach a transaction manager to the unit of work. That transaction manager will guarantee either all, or nothing has been done.

Cheers,

Allard

Thanks Allard. Is it possible to use Transaction manager when there is no database involved. I want the state changes of aggregate and non-aggregate objects that I keep in memory to happen in ACID mode esp when more than one state change is involved for a command. There is no DB involved esp on the event handling side post command handling.

How does one handle command handling and resulting event handling (async) in all on none approach?

You can use a transaction manager for anything that supports a transaction. Not just DB’s. If you use STM, you can hook in that transaction manager in the unit of work as well. You’d have to write a little adapter that implements Axon’s TransactionManager interface.

How do you mean “all in one apprach”? As a single transaction? It’s not a very safe concept to rely on in your code, as it impacts your ability to scale. Instead, try to see command handling (including publication of events) as one transaction, and the handling of events as another.
If you really must have everything in the same transaction, you’re restricted to using the SimpleEventBus.

Cheers,

Allard

Thanks Allard.
Will try this transactionManager interface.

yes. All or none approach is desired. But I need to scale too. Splitting separately in Commandhandling and event handling is fine as long as event handling is guaranteed, even after server failure and not duplicated if part of event hanlders are already executed. (non idempotent event handlers)

I am not using event repository and therefore would not presist events and check on restart of server and replay non consumed events. Ideally would like to have this as part of event infrastructure where events are internally logged by the infrastructure and on successful publishing and successful handling by all event listeners these are flushed out.

Or are these already available in the framework? (Went through the documentation and probably I missed getting it)

Hi Udaya,

persistent event bus implementations aren’t currently part of the framework. Normally, I advise the use of a Message Broker for this, such as RabbitMQ. In Axon you organise event handlers into clusters, where each cluster will process events off a single queue from the broker. For each cluster, you then configure the transactional semantics that you require (at least once, at most once, etc).

Cheers,

Allard

Thanks Allard.

Want to try transactional semantics on an event cluster. Probably that will solve the problem. is there an example code or some documentation around it? or if you could direct by giving a couple of lines of pseudo code that could also help.

The need is more on event handlers are called for the event even when the server goes down.

HI,

there is not much pseudo code to give. Your code shouldn’t contain any logic related to infrastructure at all. Your code should focus on the business logic. Then, you configure the Axon component according to the infrastructure and non-functional requirements.
If you use the AMQP Terminal, you can configure a transaction manager on that. On each Cluster, you can add cluster-specific configuration. See the documentation for more information: http://www.axonframework.org/docs/2.3/event-processing.html#d5e1772.

If you would build a custom terminal, for reliable asynchronous processing, this is the pseudo code:

  • onEvent -> write to disk (e.g. MapDB tree)
  • schedule processing job
  • pass to cluster
  • after successful processing, remove from disk

When recovering from a crash, read all events from the MapDB tree, and schedule processing jobs for them. The processing jobs will clear them when completed.

Hope this helps.
Cheers,

Allard

Thanks Allard.Will try these out.