File: transaction.py

package info (click to toggle)
gaphor 0.13.0-1
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 3,692 kB
  • ctags: 2,971
  • sloc: python: 19,981; xml: 247; makefile: 54; sh: 40
file content (70 lines) | stat: -rw-r--r-- 1,969 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
"""
Transation support for Gaphor
"""

from zope import interface, component
from gaphor.interfaces import ITransaction
from gaphor.event import TransactionBegin, TransactionCommit, TransactionRollback

def transactional(func):
    def _transactional(*args, **kwargs):
        tx = Transaction()
        try:
	    func(*args, **kwargs)
        except Exception, e:
            log.error('Transaction terminated due to an exception, performing a rollback', e)
            try:
                tx.rollback()
            except Exception, e:
                log.error('Rollback failed', e)
            raise
        else:
            tx.commit()
    return _transactional

class TransactionError(Exception):
    """
    Errors related to the transaction module.
    """


class Transaction(object):
    interface.implements(ITransaction)

    _stack= []

    def __init__(self):
        self._need_rollback = False
        if not self._stack:
            component.handle(TransactionBegin())
        self._stack.append(self)

    def commit(self):
        self._close()
#        if self._need_rollback:
#            log.warning('Tried to commit a transaction already marked for rollback.')
        if not self._stack:
            if self._need_rollback:
                component.handle(TransactionRollback())
            else:
                component.handle(TransactionCommit())

    def rollback(self):
        self._close()
        # Mark every tx on the stack for rollback
        for tx in self._stack:
            tx._need_rollback = True
        if not self._stack:
            component.handle(TransactionRollback())

    def _close(self):
        try:
            last = self._stack.pop()
        except IndexError:
            raise TransactionError, 'No Transaction on stack.'
        if last is not self:
            self._stack.append(last)
            raise TransactionError, 'Transaction on stack is not the transaction being closed.'


# vim: sw=4:et:ai