我正在尝试在我的数据库框架中管理事务(我使用 MongoDB 和 umongo 而不是 pymongo)。
要使用事务,必须在整个调用链中传递一个session
kwarg。我想提供一个上下文管理器来隔离事务。只有调用链末端的函数需要知道该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
在用户代码中保持操作。