奇怪的App Engine NDB行为w.r.t. get_or_insert和事务

时间:2014-05-29 06:33:40

标签: google-app-engine transactions app-engine-ndb

我对ndb.Model类的这些辅助方法有所了解:

@classmethod
@ndb.transactional(retries=2)
def new(cls, *args, **kwargs):
  internal_name = kwargs['internal_name']
  new_company = cls.get_or_insert(internal_name, **kwargs)
  new_company.put()
  return new_company

@classmethod
@ndb.transactional(retries=2)
def get(cls, internal_name):
  result = cls.query(cls.internal_name == internal_name)
  if result.count() != 1:
    raise Exception("this is a problem");  
  return result.get()

我写了一个测试来验证我的假设:

def testCanCreateRetrieveCompany(self):
  company = self.models.Company.new(internal_name="google", description="search engine")
  reread_company = self.models.RichCompany.get("internal_name")
  self.assertTrue(True)

但是,这次失败并且每次都有this is a problem例外!

但是,如果我将测试更改为:

def testCanCreateRetrieveCompany(self):
  company = self.models.Company.new(internal_name="google", description="search engine")
  company.put()
  reread_company = self.models.RichCompany.get("internal_name")
  self.assertTrue(True)
这似乎过去了。我绝对不知道为什么当第一个没有时它会通过。此外,删除@ndb.transactional运算符似乎使这项工作。除了我显然希望这是交易性的。

不确定发生了什么。我知道在关于事务读取的文档中有一些警告(只看到事务的原始读取状态),但我不知道有任何这样的写入警告。有没有人有任何见解?

1 个答案:

答案 0 :(得分:1)

因此,经过一番挖掘,我认为我只是看到darn更新可能是事务性的,但实际上仍然是最终的一致 - 也就是说,仅仅因为该方法是事务性的,并不意味着更新制作将是非常一致的。我最终在公司密钥中添加了父/祖先组件(因此所有公司对象共享一个祖先),这给了我想要的效果。参见:

ndb and consistency: Why is happening this behavior in a query without a parent