Transaction leaves autocommit mode to False on rollback
Closed this issue · 0 comments
joel-m commented
Description
There is a bug in the Transaction class. To allow nested call of functions decorated with @Transaction
, we maintain a class attribute __level
. It is incremented by 1 each time a decorated function is called, decremented on exit. When the level reaches 0 the transaction is committed. If an error occurs, we rollback the transaction and set the level to 0.
def __call__(self, relation, *args, **kwargs):
"""Each time a transaction is hit, the level is increased.
The transaction is commited when the level is back to 0 after
the return of the function.
"""
res = None
try:
Transaction.__level += 1
if relation._model._connection.autocommit:
relation._model._connection.autocommit = False
res = self.__func(relation, *args, **kwargs)
Transaction.__level -= 1
if Transaction.__level == 0:
relation._model._connection.commit()
relation._model._connection.autocommit = True
except Exception as err:
sys.stderr.write(f"Transaction error: {err}\nRolling back!\n")
self.__level = 0
relation._model._connection.rollback()
relation._model._connection.autocommit = True
raise err
return res
The line self.__level = 0
should have been Transaction.__level = 0
as __level
is a class attribute.
Consequences
In a rest API, if there is an error during a transaction, the level keeps a value greater than 0, leaving the auto commit mode to False for the subsequent requests.