【问题标题】:Odd App Engine NDB behavior w.r.t. get_or_insert and transactions奇怪的 App Engine NDB 行为 w.r.t. get_or_insert 和事务
【发布时间】:2014-05-29 06:33:40
【问题描述】:

我在 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 运算符似乎可以完成这项工作。除了我显然希望这是事务性的。

不知道发生了什么。我知道文档中有关于事务读取的警告(只看到事务的原始读取状态),但我不知道写入有任何此类警告。有人有什么见解吗?

【问题讨论】:

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


    【解决方案1】:

    所以经过更多的挖掘,我想我只是看到该死的更新可能是事务性的,但实际上仍然是最终一致的——也就是说,仅仅因为方法是事务性的,并不意味着更新made 将保持高度一致。我最终向公司键添加了父/祖先组件(因此所有公司对象共享一个祖先),这给了我想要的效果。见:

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

    【讨论】:

    • 是的,你已经解决了。第二个示例始终有效的原因是因为您执行的 get 始终是一致的,而第一个示例使用的查询仅在使用祖先查询时才一致。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多