Google app engine ndb.toplevel和ndb.transactional的交互
有没有可能让Google app engine ndb.toplevel和ndb.transactional的交互,google-app-engine,transactions,google-cloud-datastore,app-engine-ndb,google-app-engine-python,Google App Engine,Transactions,Google Cloud Datastore,App Engine Ndb,Google App Engine Python,有没有可能让@ndb.toplevel与@ndb.transactional配合得很好 我想要实现的是一个包含entity.put_async()调用的事务,但不必显式地等待未来@ndb.toplevel通常会这样做,但另一个SO问题似乎表明它不能与事务相结合: 我在App Engine文档中的任何地方都找不到明确的文档。我们可以重现该问题中显示的断言错误,但是我们编写了一些测试来查看put\u async()调用是否失败,并且没有看到任何问题。然而,由于有可能丢失数据,因此最好能从熟悉ndb的
@ndb.toplevel
与@ndb.transactional
配合得很好
我想要实现的是一个包含entity.put_async()
调用的事务,但不必显式地等待未来@ndb.toplevel
通常会这样做,但另一个SO问题似乎表明它不能与事务相结合:
我在App Engine文档中的任何地方都找不到明确的文档。我们可以重现该问题中显示的断言错误,但是我们编写了一些测试来查看put\u async()
调用是否失败,并且没有看到任何问题。然而,由于有可能丢失数据,因此最好能从熟悉ndb的人那里得到更具体的答案
下面是我们的简单测试代码。
如果我们同时删除ndb.toplevel
和ndb.transactional
装饰器,测试将失败,正如预期的那样。
但是,如果我们只使用ndb.transactional
decorator,而不使用ndb.toplevel
decorator,那么测试就通过了,这是不期望的。这让我担心,ndb.transactional
中的开销可能刚好足够put\u async()
调用有足够的时间来完成,但没有任何gaurantee,因此它可能会意外失败
class AsyncTestModel(ndb.Model):
data = ndb.StringProperty(indexed=True)
@ndb.toplevel
def start_test():
for _ in range(100):
test()
# Check we wrote all the entities
time.sleep(30)
entities = AsyncTestModel.query().fetch()
assert(len(entities) == 1000)
@ndb.transactional(xg=True)
def test():
for _ in range(10):
x = AsyncTestModel()
x.data = make_random_string(1000)
x.put_async()
当您仅使用
@ndb.transactional
时,测试通过这一事实是预期的结果:为了确保从不部分应用事务,@ndb.transactional
等待所有请求完成
因此,范围内(100):test()的代码等待事务在每次迭代时结束
因此,以下测试通过:
@ndb.transactional(xg=True)
def test():
for _ in range(10):
x = AsyncTestModel()
x.data = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(1000))
x.put_async()
for x, _ in enumerate(range(100)):
test()
assert(AsyncTestModel.query().count() == (x + 1) * 10)
注意:如果您在事务中使用异步查询,您可以查看@ndb.transactional\u async
(文档)。当您仅使用@ndb.transactional
时,测试通过的事实是预期的组件:确保从不部分应用事务,@ndb.transactional
等待所有请求完成
因此,范围内(100):test()的代码等待事务在每次迭代时结束
因此,以下测试通过:
@ndb.transactional(xg=True)
def test():
for _ in range(10):
x = AsyncTestModel()
x.data = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(1000))
x.put_async()
for x, _ in enumerate(range(100)):
test()
assert(AsyncTestModel.query().count() == (x + 1) * 10)
注意:如果在事务中使用异步查询,可以查看@ndb.transactional\u async
(文档)