collorg/halfORM

Transaction leaves autocommit mode to False on rollback

Closed this issue · 0 comments

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.