Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

In the above example, we separate the transactional processing into two phases: the data transmission phase, and the commit phase. In data transmission phase, any exception thrown would be an indication of the ongoing transaction failure, so that we got a clear signal for the next stage whether to commit or abort the ongoing transaction.

In the commit phase, we should decide whether to commit or abort transaction based on the signal from last state. In here, commitTransaction() will be acting like abortTransaction() where it no longer throws non-fatal exceptions anymore. This means any exception caught during the commit phase will be fatal which could simplify user's error handling.

If the commit failed internally with non-fatal exception but wasn't throwing, the next beginTransaction() will fail non-fatally, causing the `shouldCommit` flag set false, which means the abortTransaction will be triggered automatically in the next iteration.

The only debatable exceptional case is a timeout within commit/abort transaction. It could be treated either fatal or not, as strictly speaking producer would have already done the retrying for max.block.ms, so a timeout here may be suggesting a fatal state. We include the timeout handling in the template here just for example, usually caller level could have more sophisticated handling to do an application level retry if necessary.  

Unify Wrapped Exception in Commit Phase

...