Neo Transactions
From NeoWiki
[edit] Nested transactions
As of current version Neo does not support true nested transactions meaning a nested transaction cannot rollback while the parent transaction commits. Consider the following example:
Method A performs some transactional work and also calls method B (that opens a nested transaction) in a try-catch block. Now if all the work done directly in method A succeeded, but the call to B failed with an exception, the transaction should still commit. This is the goal and we can achieve this with our API. But it places some additional demands on the contract (and/or documentation) of method B. Lets say that B performs two operations. If the first operation completes but the second operation fails, then B has 3 options:
- Throw an exception right away and document that "If I throw this exception and I didn't open the transaction, then it's up to you to rollback". No rollback equals inconsistency where only the first operation in B will be committed.
- Call tx.failure() then throw an exception. This will block A from being able to commit other work performed in the transaction.
- Undo the first operation performed then throw an exception. This will allow A to commit the transaction and everything will be consistent.
When we evaluated the pros and cons of nested transactions we decided not to support "true" nested transactions because of their impact on performance. It is not very common that you run into the example above, typically all checks that needs to be done can be done before any actual additional work is performed and if something fails "in the middle" it usually an indication of a much more serious error that should result in a complete rollback.
In the future, we can add true nested transaction support to Neo quite easily and we may do so. Ideal would be to make it configurable. The developer could decide if the behavior should be to hook up to an already existing transaction or open a nested transaction depending on the situation (performance penalty or not having to write some additional code).
So to sum things up:
When a method wraps the code inside a transaction, there are three possibilities to consider.
- The code that invokes the method has not started a transaction.
- The code that invokes the method has started a transaction.
- The code inside the method calls other methods. These methods may start transactions of their own.
All these scenarios need to consider and handle the nesting of transactions.
Basically, there are two main ways to nest transaction.
First the top level transaction must succeed for all nested transactions to succeed as well. This is supported by Neo.
The failure of a nested transaction will fail the top level transaction and all other nested transactions. This is supported by Neo, but the transaction design need to be carefully considered. We will explain how this is achieved below.
The failure of a nested transaction will only fail the local transaction, not the top level transaction, nor the other nested transactions. This is not supported by Neo as of today unless you manually code the rollback mechanism for the nested work.

