3.1 KiB
Transaction support
Transaction support is located in module gaphor.transaction
:
>>> from gaphor import transaction
>>> import sys, logging
>>> transaction.log.addHandler(logging.StreamHandler(sys.stdout))
Do some basic initialization, so event emission will work. Since the transaction decorator does not know about the active user session (window), it emits it's events via a global list of subscribers:
>>> from gaphor.core.eventmanager import EventManager
>>> event_manager = EventManager()
>>> transaction.subscribers.add(event_manager.handle)
The Transaction class is used mainly to signal the begin and end of a transaction. This is done by the TransactionBegin, TransactionCommit and TransactionRollback events:
>>> from gaphor.core import event_handler
>>> @event_handler(transaction.TransactionBegin)
... def transaction_begin_handler(event):
... print('tx begin')
>>> event_manager.subscribe(transaction_begin_handler)
Same goes for commit and rollback events:
>>> @event_handler(transaction.TransactionCommit)
... def transaction_commit_handler(event):
... print('tx commit')
>>> event_manager.subscribe(transaction_commit_handler)
>>> @event_handler(transaction.TransactionRollback)
... def transaction_rollback_handler(event):
... print('tx rollback')
>>> event_manager.subscribe(transaction_rollback_handler)
A Transaction is started by initiating a Transaction instance:
>>> tx = transaction.Transaction(event_manager)
tx begin
On success, a transaction can be committed:
>>> tx.commit()
tx commit
After a commit, a rollback is no longer allowed (the transaction is closed):
>>> tx.rollback()
... # doctest: +ELLIPSIS
Traceback (most recent call last):
...
gaphor.transaction.TransactionError: No Transaction on stack.
Transactions may be nested:
>>> tx = transaction.Transaction(event_manager)
tx begin
>>> tx2 = transaction.Transaction(event_manager)
>>> tx2.commit()
>>> tx.commit()
tx commit
Transactions should be closed in the right order (subtransactions first):
>>> tx = transaction.Transaction(event_manager)
tx begin
>>> tx2 = transaction.Transaction(event_manager)
>>> tx.commit()
... # doctest: +ELLIPSIS
Traceback (most recent call last):
...
gaphor.transaction.TransactionError: Transaction on stack is not the transaction being closed.
>>> tx2.commit()
>>> tx.commit()
tx commit
The transactional decorator can be used to mark functions as transactional:
>>> @transaction.transactional
... def a():
... print('do something')
>>> a()
tx begin
do something
tx commit
If an exception is raised from within the decorated function a rollback is performed:
>>> @transaction.transactional
... def a():
... raise IndexError('bla')
>>> a() # doctest; +ELLIPSIS
Traceback (most recent call last):
...
IndexError: bla
>>> transaction.Transaction._stack
[]
Cleanup:
>>> transaction.subscribers.discard(event_manager.handle)