sider.transaction
— Transaction handling¶
Every Persist object provided by Sider can be used within transactions. You can atomically commit multiple operations.
Under the hood, transaction blocks are simply looped until objects
the transaction deals with haven’t been faced any conflicts with
other sessions/transactions. If there are no concurrent touches
to names
in the following transaction:
def block(trial, transaction):
names.append(new_name)
session.transaction(block)
it will be successfully committed. Otherwise, it retries the
whole transaction block
. You can easily prove this by just
printing trial
(the first argument of the block function)
inside the transaction block. It will print one or more retrial
counting numbers.
This means you shouldn’t do I/O in the transaction block. Your I/O could be executed two or more times. Do I/O after or before transaction blocks instead.
There are two properties of every operation: query()
or
manipulative()
or both. For example, Hash.get()
method is a query operation.
On the other hand, Set.add()
method
is manipulative. There is a rule of transaction: query operations
can’t be used after manipulative operations. For example,
the following transaction block has no problem:
# Atomically wraps an existing string value of the specific
# key of a hash.
hash_ = session.get('my_hash', Hash)
def block(trial, transaction):
current_value = hash_['my_key'] # [query operation]
updated_value = '(' + current_value + ')'
hash_['my_key'] = updated_value # [manipulative operation]
session.transaction(block)
while the following raises a CommitError
:
hash_ = session.get('my_hash', Hash)
def block(trial, transaction):
current_value = hash_['my_key'] # [query operation]
updated_value = '(' + current_value + ')'
hash_['my_key'] = updated_value # [manipulative operation]
# The following statement raises CommitError because
# it contains a query operation.
current_value2 = hash_['my_key2'] # [query operation]
updated_value2 = '(' + current_value2 + ')'
hash_['my_key'] = updated_value2 # [manipulative operation]
session.transaction(block)
See also
- Redis Transactions
- The Redis documentation that explains about its transactions.
-
class
sider.transaction.
Transaction
(session, keys=frozenset([]))¶ Transaction block.
Parameters: - session (
Session
) – a session object - keys (
collections.Iterable
) – the list of keys
-
__call__
(block, keys=frozenset([]), ignore_double=False)¶ Executes a
block
in the transaction:def block(trial, transaction): list_[0] = list_[0].upper() transaction(block)
Parameters: - block (
collections.Callable
) – a function to execute in a transaction. see the signature explained in the below:block()
- keys (
collections.Iterable
) – a list of keys to watch - ignore_double (
bool
) – don’t raise any error even if any transaction has already being executed for a session. default isFalse
Raises: sider.exceptions.DoubleTransactionError – when any transaction has already being executed for a session and
ignore_double
isFalse
-
block
(trial, transaction)¶ Parameters: - trial (
numbers.Integral
) – the number of trial count. starts from 0 - transaction (
Transaction
) – the current transaction object
- trial (
- block (
-
__iter__
()¶ You can more explictly execute (and retry) a routine in the transaction than using
__call__()
.It returns a generator that yields an integer which represents its (re)trial count (from 0) until the transaction doesn’t face
ConflictError
.For example:
for trial in transaction: list_[0] = list_[0].upper()
Raises: sider.exceptions.DoubleTransactionError – when any transaction has already being executed for a session
-
__weakref__
¶ list of weak references to the object (if defined)
-
begin_commit
(_stacklevel=1)¶ Explicitly marks the transaction beginning to commit from this. From this to end of a transaction, any query operations will raise
CommitError
.
-
format_commit_stack
(indent=4, title='Traceback of previous begin_commit() call:')¶ Makes
commit_stack
text readable. If itssession.verbose_transaction_error
is notTrue
, it will simply return an empty string.Parameters: - indent (
numbers.Integral
) – the number of space character for indentation. default is 4 - title (
basestring
) – the title string of the formatted traceback. optional
Returns: the formatted
commit_stack
textReturn type: basestring
Note
It’s totally for internal use.
- indent (
-
format_enter_stack
(indent=4, title='Traceback where the transaction entered:')¶ Makes
enter_stack
text readable. If itssession.verbose_transaction_error
is notTrue
, it will simply return an empty string.Parameters: - indent (
numbers.Integral
) – the number of space character for indentation. default is 4 - title (
basestring
) – the title string of the formatted traceback. optional
Returns: the formatted
enter_stack
textReturn type: basestring
Note
It’s totally for internal use.
- indent (
-
watch
(keys, initialize=False)¶ Watches more
keys
.Parameters: - keys (
collections.Iterable
) – a set of keys to watch more - initialize (
bool
) – initializes the set of watched keys if it isTrue
. default isFalse
. option only for internal use
- keys (
- session (
-
sider.transaction.
manipulative
(function)¶ The decorator that marks the method manipulative.
Parameters: function ( collections.Callable
) – the method to markReturns: the marked method Return type: collections.Callable
-
sider.transaction.
query
(function)¶ The decorator that marks the method query.
Parameters: function ( collections.Callable
) – the method to markReturns: the marked method Return type: collections.Callable