def run_in_tx(fun, *args, **kwargs): context = context_from_method(fun, args, kwargs) _context.x = context if not _db: raise Exception('DB not initalized') try: transaction.begin() _context.x = None res = fun(*args, **kwargs) if proxy: return make_persistent_proxy(res, context) return res finally: transaction.abort()
def execute(self, args): # we obtained `this` before the action exited from the db.transact decorator # thus we need to reapply the db proxy this.context = make_persistent_proxy(this.context, db.context(self)) return fun(this, self, args)
def run_in_tx(fun, *args, **kwargs): if not _db: raise Exception('DB not initalized') context = context_from_method(fun, args, kwargs) _context.x = context cfg = get_config() def trace(msg, t, force=False): ch = '/' if msg == "BEGINNING": ch = '\\' if cfg.getboolean('debug', 'trace_transactions', False) or force: trace_fun = log.error else: trace_fun = log.debug trace_fun("%s\ttx:%s %s\tin %s from %s, line %s %s" % (msg, t.description, ch, fun, fun.__module__, inspect.getsourcelines(fun)[1], ch)) retries = cfg.getint('db', 'conflict_retries') retrying = False for i in xrange(0, retries + 1): try: t = transaction.begin() t.note("%s" % (random.randint(0, 1000000))) trace("BEGIN", t) result = fun(*args, **kwargs) except RollbackException: transaction.abort() return except: trace("ROLLBACK ON ERROR", t) transaction.abort() raise else: try: if isinstance(result, RollbackValue): trace("ROLLBACK", t) result = result.value transaction.abort() else: trace("COMMIT", t) transaction.commit() if retrying: trace("Succeeded commit, after %s attempts" % i, t) _context.x = None return make_persistent_proxy(result, context) except ReadConflictError as e: trace("GOT READ CONFLICT IN RW TRANSACT, retrying %s" % i, t, force=True) retrying = True time.sleep(random.random() * 0.2) except ConflictError as e: trace("GOT WRITE CONFLICT IN RW TRANSACT, retrying %s" % i, t, force=True) retrying = True time.sleep(random.random() * 0.2) except StorageTransactionError as e: if e.args and e.args[0] == "Duplicate tpc_begin calls for same transaction": # This may happen when an object attached to one connection is used in anther # connection's transaction. Check and compare _p_jar attributes of all objects # involved in this transaction! They all must be the same. trace("DUPLICATE tpc_begin IN RW TRANSACT", t, force=True) raise except: trace('ABORT: bad commit attempt', t) transaction.abort() raise raise e