public function rollBack($final = false)
    {
        if (!$this->getIsActive()) {
            // do nothing if transaction is not active: this could be the transaction is committed
            // but the event handler to "commitTransaction" throw an exception
            return Reaction\Promise\reject(new Exception("There is no active transactions"));
        }

        //Roll back all transaction with save points
        if ($final && $this->_level > 1) {
            $promises = [];
            while ($this->_level > 0) {
                $promises[] = $this->rollBack(false);
            }
            return !empty($promises)
                ? Reaction\Promise\allInOrder($promises)->then(function() { return true; })
                : Reaction\Promise\resolve(true);
        }

        $connection = $this->getConnection();
        $this->_level--;
        if ($this->_level === 0) {
            Reaction::debug('Roll back transaction');
            return $connection->rollBackTransaction()
                ->thenLazy(function() { $this->closeConnection(); });
        }

        $schema = $this->db->getSchema();
        if ($schema->supportsSavepoint()) {
            Reaction::debug('Roll back to savepoint ' . $this->_level);
            return $connection->rollBackSavepoint('LEVEL' . $this->_level);
        } else {
            Reaction::info('Transaction not rolled back: nested transaction not supported');
            // throw an exception to fail the outer transaction
            return Reaction\Promise\reject(new Exception('Roll back failed: nested transaction not supported.'));
        }
    }