我正在尝试在我的数据库框架中管理事务(我使用基于 pymongo 的 umongo 连接 MongoDB)。
要使用事务,必须沿着整个调用链传递一个 session
关键字参数。我想提供一个上下文管理器来隔离事务。只有在调用链末尾的函数需要知道 session
对象。
我了解到了上下文变量并且已经接近一些内容,但还没有完全理解。
我想要的是:
with Transaction():
# Do stuff
d = MyDocument.find_one()
d.attr = 12
d.commit()
这是我目前为止想到的:
s = ContextVar('session', default=None)
class Transaction(AbstractContextManager):
def __init__(self):
self.ctx = copy_context()
# Create a new DB session
session = db.create_session()
# Set session in context
self.ctx.run(s.set, session)
def __exit__(self, *args, **kwargs):
pass
# Adding a run method for convenience
def run(self, func, *args, **kwargs):
self.ctx.run(func, *args, **kwargs)
def func():
d = MyDocument.find_one()
d.attr = 12
d.commit()
with Transaction() as t:
t.run(func)
但是我没有漂亮的上下文管理器语法。上下文管理器的重点在于说“在那个上下文中运行放置在其中的所有内容”。
我上面所写的并不比仅仅使用函数更好:
def run_transaction(func, *args, **kwargs):
ctx = copy_context()
session = 12
ctx.run(s.set, session)
ctx.run(func)
run_transaction(func)
我是否走错了方向?
我是否误用了上下文变量?
还有其他实现我所需求的方法吗?
基本上,我想要像上下文管理器一样打开一个上下文。
session = ContextVar('session', default=None)
with copy_context() as ctx:
session = db.create_session()
# Do stuff
d = MyDocument.find_one()
d.attr = 12
d.commit()
我会将此嵌入到一个Transaction
上下文管理器中,以管理会话内容并仅在用户代码中保留对d
的操作。