Skip to content
Snippets Groups Projects
api_transaction.py 3.24 KiB
Newer Older
# copyright 2022-2023 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact https://www.logilab.fr -- mailto:contact@logilab.fr
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 2.1 of the License, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
Frank Bessou's avatar
Frank Bessou committed
from typing import cast, Dict
from cubicweb.entities.authobjs import CWUser
from cubicweb.server.repository import Repository
Frank Bessou's avatar
Frank Bessou committed
from cubicweb.server.session import Connection


class ApiTransaction:
    def __init__(self, repo: Repository, user: CWUser):
        """
        Class defining transactions.
        A transaction allows to make several request which only take effect
        when the changes are committed.

        :param repo: The CubicWeb repository
        :param user: The user initiating the transaction
        """
Frank Bessou's avatar
Frank Bessou committed
        self.cnx = Connection(repo, user)
        self.cnx.__enter__()
        self._uuid = cast(str, self.cnx.transaction_uuid(set=True))

    @property
    def uuid(self) -> str:
        """
        :return: The unique identifier for this transaction
        """
Frank Bessou's avatar
Frank Bessou committed
        return self._uuid

    def execute(self, rql: str, params: Dict[str, any]):
        """
        Executes the given rql query on this transaction.

        :param rql: The RQL query string
        :param params: The parameters for the RQL query
        :return: The result from executing the query
        """
Frank Bessou's avatar
Frank Bessou committed
        return self.cnx.execute(rql, params)

    def commit(self):
        """
        Commits the current transaction to apply all changes.
        """
Frank Bessou's avatar
Frank Bessou committed
        self.cnx.commit()

    def rollback(self):
        """
        Rollback the current transaction to cancel all changes.
        """
Frank Bessou's avatar
Frank Bessou committed
        self.cnx.rollback()

    def end(self):
        self.cnx.__exit__(None, None, None)


class ApiTransactionsRepository:
    def __init__(self, repo: Repository):
        """
        Class holding all active transactions from all users.

        :param repo: The CubicWeb repository
        """
Frank Bessou's avatar
Frank Bessou committed
        self._transactions: Dict[str, ApiTransaction] = dict()
        self._repo = repo

    def begin_transaction(self, user: CWUser) -> str:
        """
        Starts a new transaction for the given user.

        :param user: The user initiating the transaction
        :return: The transaction uuid
        """
Frank Bessou's avatar
Frank Bessou committed
        transaction = ApiTransaction(self._repo, user)
        self._transactions[transaction.uuid] = transaction
        return transaction.uuid

    def end_transaction(self, uuid: str):
        """
        Ends a transaction identified by its uuid.

        :param uuid: The id of the transaction to end.
        """
Frank Bessou's avatar
Frank Bessou committed
        transaction = self._transactions.pop(uuid)
        transaction.end()

    def __getitem__(self, uuid: str) -> ApiTransaction:
Frank Bessou's avatar
Frank Bessou committed
        return self._transactions[uuid]