Thursday, February 3, 2011

Using Spring AOP to Retry Failed Idempotent Concurrent Operations

There are times when an operation that needs to be performed fails because of problems of concurrency. For example, take the case where there is operation currently in process whose status is stored in a database. If you also need the ability to cancel this task while it is in progress, you would naturally implement a call that would update this status to a 'cancelled' state.

In an environment where transactions are non-blocking, such as is often found in a Spring/Hibernate stack, this introduces a point of contention. If the cancel call loads and modifies the task data concurrently with an attempt by the task executor to modify the status, there is a notable chance that upon attempting to commit the cancel transaction an (in this case, ConcurrencyFailureException) exception would be thrown. The caller of the cancel call, being uninterested with the internal interactions between threads of operation and simply wanting the task cancelled, should not be exposed to such an error. They expect the task to be cancelled.

This is an example of an idempotent concurrent operation that is a good candidate for retrying upon failure. I recently encountered this very problem and will share my solution for it.