mirror of
https://github.com/corda/corda.git
synced 2024-12-19 04:57:58 +00:00
9a2ae8ae19
* CORDA-3722 withEntityManager can rollback its session ## Summary Improve the handling of database transactions when using `withEntityManager` inside a flow. Extra changes have been included to improve the safety and correctness of Corda around handling database transactions. This focuses on allowing flows to catch errors that occur inside an entity manager and handle them accordingly. Errors can be caught in two places: - Inside `withEntityManager` - Outside `withEntityManager` Further changes have been included to ensure that transactions are rolled back correctly. ## Catching errors inside `withEntityManager` Errors caught inside `withEntityManager` require the flow to manually `flush` the current session (the entity manager's individual session). By manually flushing the session, a `try-catch` block can be placed around the `flush` call, allowing possible exceptions to be caught. Once an error is thrown from a call to `flush`, it is no longer possible to use the same entity manager to trigger any database operations. The only possible option is to rollback the changes from that session. The flow can continue executing updates within the same session but they will never be committed. What happens in this situation should be handled by the flow. Explicitly restricting the scenario requires a lot of effort and code. Instead, we should rely on the developer to control complex workflows. To continue updating the database after an error like this occurs, a new `withEntityManager` block should be used (after catching the previous error). ## Catching errors outside `withEntityManager` Exceptions can be caught around `withEntityManager` blocks. This allows errors to be handled in the same way as stated above, except the need to manually `flush` the session is removed. `withEntityManager` will automatically `flush` a session if it has not been marked for rollback due to an earlier error. A `try-catch` can then be placed around the whole of the `withEntityManager` block, allowing the error to be caught while not committing any changes to the underlying database transaction. ## Savepoints / Transactionality To make `withEntityManager` blocks work like mini database transactions, save points have been utilised. A new savepoint is created when opening a `withEntityManager` block (along with a new session). It is then used as a reference point to rollback to if the session errors and needs to roll back. The savepoint is then released (independently from completing successfully or failing). Using save points means, that either all the statements inside the entity manager are executed, or none of them are. ## Some implementation details - A new session is created every time an entity manager is requested, but this does not replace the flow's main underlying database session. - `CordaPersistence.transaction` can now determine whether it needs to execute its extra error handling code. This is needed to allow errors escape `withEntityManager` blocks while allowing some of our exception handling around subscribers (in `NodeVaultService`) to continue to work. |
||
---|---|---|
.. | ||
src | ||
build.gradle |