Search code examples
axondead-letter

Axon FW 4.6 comes with Dead Letter Queue support, but is it possible to still have rollback support in case of exception?


we're looking into using the new feature of Axon, dead letter queue(DLQ). In our previous application (axon 4.5x) we have a lot of eventhandlers updating projections. Our default is to rethrow exceptions when they occur, which will trigger a rollback for the database updates. Perhaps not the best practice to rely on this behaviour (because it can not rollback everything, eg sending an email from event can not be reverted of course) This behaviour seems to get lost when introducing DLQ in our applications, which has big impact on our current application flow (projections are updated when they previously weren't). This makes upgrading not that easy. Is it possible to still get the old behaviour(transaction rolled back in case of exceptions) together with DLQ processing?

What we tried was building a test application to test the new DLQ features. While playing around all looks fine in case of exceptions (they were moved to dlq) but the projections still got updated (not rolled back as before) We throw an exception after the .save() of the projection simulating a database failure to see if events involved (we have multiple eventhandlers for an event updating projections) got rolled back.


Solution

  • You need to choose here, @davince. Storing a dead-letter in the dead-letter queue similarly requires a database transaction. To ensure the token still progresses and the dead letter is entered, the framework uses the existing transaction.

    Furthermore, in practical terms event handling was successful. Hence, a rollback for some of the parts wouldn't be feasible.

    The best way to deal with this, as is mentioned in the Reference Guide, is to make your event handlers idempotent:

    Before configuring a SequencedDeadLetterQueue it is vital to validate whether your event handling functions are idempotent. As a processing group consists of several Event Handling Components (as explained in the intro of this chapter), some handlers may succeed in event handling while others will not. As a configured dead-letter queue does not stall event handling, a failure in one Event Handling Component does not cause a rollback for other event handlers. Furthermore, as the dead-letter support is on the processing group level, dead-letter processing will invoke all event handlers for that event within the processing group.

    Thus, if your event handlers are not idempotent, processing letters may result in undesired side effects. Hence, we strongly recommend making your event handlers idempotent when using the dead-letter queue. The principle of exactly-once delivery is no longer guaranteed; at-least-once delivery is the reality to cope with.

    I understand this requires some rework on your end, @davince. Although the feature is powerful, it comes with a certain level of responsibility before you use it. I hope the above clarifies this for you.

    Added, I'd like to point out that the version upgrade in itself does not require you to use the dead-letter queue. Hence, this change shouldn't impose any strains for updating to the latest release.

    Update 1

    Sometimes you need to think about an issue a bit longer.. I was just wondering the following things about your setup. Perhaps I can help out on that front:

    • What storage mechanism do you use to store projections in?
    • Where are you storing your tokens?
    • Where are you planning to store your dead-letters?
    • How are you invoking the storage layer from your event handlers?

    Update 2

    Thanks for sharing that you're using PostgreSQL for your projections, tokens, and dead letters. And that you're using JPA entities for storage. It gives more certainty about your setup, as it may impact how your system would react in case of a rollback. However, as it's rather vanilla/regular, the shared comment from the Reference Guide still applies.

    This, sadly enough, means some work on your end, @davince. I hope the road forward to start using the SequencedDeadLetterQueue from Axon Framework is clear. By the way, if you ever have recommendations on how the framework or the documentation may be improved, be sure to file issues in GitHub here and here, respectively.