Can Asynchronous Event Distribution Become Transactional?

Hi,

Axon has a very nice and sophisticated asynchronous message
distribution mechanism. Unfortunately, if I understand it correctly,
the
message distribution is not transactional. This limits the use of
this
corner-stone feature in a transactional application to statistical
data
gathering and other non-mission critical usages and leaves it to the
application to implement this feature, which is not a trivial task.

Again, if I understand it correctly, the reason for being non-
transactional
is this: Before a particular message rest in peace, in its life-
cycle, it
participates in two separate consecutive transactions; one for
becoming
persistent, and the othrs to be distributed. The trouble is that
in-between these two transactions, the event sits dock on a
memory-based que and therefore not immune of system failures and
other disasters.

I hope I'm wrong about the above analysis, but if my understanding is
correct, is it not possible to make the que persistent and use it as
a
transient transaction-log?

I understand that due to the dynamic event-listener registrations,
etc.
implementing this capability while keeping all the currently
available
features intact may not be trivial.

If that is the case, is it not possible to implement some
less-sophisticated but more reliable event distribution mechanism
in addition to the existing one? (I have some ideas in this regards.)

Best wishes
Esfand

Hi Esfand,

it is definitely possible to have the event store and the event bus to run in the same transaction. All you need is to configure a transaction manager that supports this. I haven’t tried yet, though.

Cheers,

Allard

Hi Allard,

In the case of synchronous event listener and
synchronous event distribution, only one transaction
is involved and using a distributed transaction
manager such Spring Transacton Manager, etc
there is no problems. Even without a distributed
trans. mgr with some tricks it is possible to have
transactional event distributions.

My problem is with asynchronous event listeners
in which case two different txs separated possibly
by several seconds time-wise -- one under the
control of UOW, the other initiated by the Axon
scheduler later-on.

I really appreciate giving me some pointers as to
how to do this over-encompassing tx and the kind
of transaction-manager I should be looking for.

Regards,
Esfand

Hi Esfand,

the trick is to use a synchronous dispatching mechanism to a messaging system, such as a message broker. When you commit, the broker will make sure the messages will -sooner or later- end up at the listeners.

That mechanism will make the event listeners asynchronous, while keeping all the support for transactional processing. And all you need is a single transaction manager that commits to both the database and the message broker. You’ll probably be safe enough when you just commit one after the other, and not really have a 2PC.

Hope that helps.

Cheers,

Allard

Hi Allard,

Thanks for the explanations, please read in-line:

the trick is to use a synchronous dispatching mechanism to a
messaging system, ...

Yes that would work, This is what I called synchronous
message distribution in my post. The best example of
this approach is the excellent Axon Auction sample provided
by Michael. He is using JMS as the protocol and ActiveMQ
as the messaging broker. This approach is the (only) way
to go when the application is big and distributed among
many computers and/or processes.

But, there are many cases where having asynchronous local
event distribution is a must within a single process
(even in a process which is a part of a distributed application).
Examples are when a long task such as a CPU-heavy task
or i-o heavy task such as sending email is part of the
transaction.

In these situations,
to make the response time shorter, using a lightweight GoF
observer-pattern type of message distributor is much better
because a heavyweight message-broker brings with it
a lot of unnecessary complexities and expenses for
additional CPU and memory and management they require.
Which goes against the lean and mean nature of Axon.

In addition, in the case of RabbitMQ it definitely requires
2PC using Spring Transaction or similar (I'm aware of some
tricks which in some case can optimize away the 2PC in
this case but not without introducing extra complexities
in the application itself)

In the case of ActiveMQ, because it can use the same
JDBC-based SQL engine used by the event-store, it is
possible to use a local common transaction. But ActiveMQ
is a CPU-hungry memory-monster which needs a lot of
nurturing to survive.

What I wished was to enhance the currently existing
asynchronous subsystem of Axon to make it transactional,
by switching the currently memory-based que with a
disk-based que. This would provide Axon applications
with a lightweight local observer pattern class of message
distribution out of the box.

Off course it is always possible to have a heavy-weight
message-broker as one of the local asynchronous event
listeners for distributing the events over and beyond the
current process while local CPU- and IO-heavy
event-listeners can also benefit from less network latency
and no reliance on exogenous message brokers at the
same time.

Best wishes,
Esfand

Hi Esfand,

I have been thinking about a transactional-asynchronous event handler mechanism for a long time. It is very complex. I recon it is a lot better to use a real system for this. RabbitMQ is definitely not heavy weight. It uses about 40MB of memory when idle. The only heaviness about it is the serialization overhead you get. But if you want (durable) transaction support, you’ll need to serialize to disk anyway. And Rabbit vastly outperforms ActiveMQ.

Since a while, there is a ClusteringEventBus in Axon. This implementation supports the publication of events to a variety of (technically) different event listeners. Some of the listeners could have AMQP between them, while others are simply publiished synchronously.

If I have extra time on my hands, I might still decide to create a lightweight durable asynchronous dispatching mechanism. It’s not an absolute no-go, it’s just not high enough on the feature list.

Cheers,

Allard

Hi Esfand,

I have been thinking about a transactional-asynchronous event handler mechanism for a long time. It is very complex. I recon it is a lot better to use a real system for this. RabbitMQ is definitely not heavy weight. It uses about 40MB of memory when idle. The only heaviness about it is the serialization overhead you get. But if you want (durable) transaction support, you’ll need to serialize to disk anyway. And Rabbit vastly outperforms ActiveMQ.

Since a while, there is a ClusteringEventBus in Axon. This implementation supports the publication of events to a variety of (technically) different event listeners. Some of the listeners could have AMQP between them, while others are simply publiished synchronously.

If I have extra time on my hands, I might still decide to create a lightweight durable asynchronous dispatching mechanism. It’s not an absolute no-go, it’s just not high enough on the feature list.

Cheers,

Allard