Google app engine 冗余的ndb.Model.put\u async()调用是否只发送一次到数据存储?

Google app engine 冗余的ndb.Model.put\u async()调用是否只发送一次到数据存储?,google-app-engine,app-engine-ndb,Google App Engine,App Engine Ndb,我有一个NDB模型,它公开了一些实例方法来操纵它的状态。在一些请求处理程序中,我需要调用其中一些实例方法。为了防止在同一个实体上多次调用put(),我目前使用的模式与此类似: Foo类(ndb.Model): prop_a=ndb.StringProperty() prop_b=ndb.StringProperty() prop_c=ndb.StringProperty() 定义某些方法(自身): self.prop_a=“某些计算的结果” 返回真值 定义某些方法(自身): 如果出现以下情况:

我有一个NDB模型,它公开了一些实例方法来操纵它的状态。在一些请求处理程序中,我需要调用其中一些实例方法。为了防止在同一个实体上多次调用
put()
,我目前使用的模式与此类似:

Foo类(ndb.Model):
prop_a=ndb.StringProperty()
prop_b=ndb.StringProperty()
prop_c=ndb.StringProperty()
定义某些方法(自身):
self.prop_a=“某些计算的结果”
返回真值
定义某些方法(自身):
如果出现以下情况:
self.prop_b=“一些新值”
返回真值
返回错误
定义某些方法(自身):
如果出现以下情况:
self.prop_b=“一些新值”
返回真值
如果出现某些或其他情况:
self.prop_b=“一些新值”
self.prop_c=“一些新值”
返回真值
返回错误
def(f):
更新=错误
更新=f.某些方法\u 1()或更新
更新=f.某些方法2()或更新
更新=f.某些方法3()或更新
如有更新:
f、 put()
基本上,每个可能更新实体的方法都会返回一个bool,以指示实体是否已更新,因此是否需要保存。当按顺序调用这些方法时,如果有任何方法返回
True
,我确保调用
put()

但是,在涉及其他子例程的情况下,此模式可能很复杂,难以实现。在这种情况下,我需要将从子例程返回的更新布尔值冒泡到顶级方法

我现在正在优化我的许多请求处理程序,试图尽可能限制AppStat报告的瀑布,尽可能多地使用异步API,并将许多方法转换为Tasklet

这项工作让我阅读了,其中提到NDB实现了一个AutoWatcher,它在对数据存储的单个RPC调用中组合了多个请求。我知道这适用于涉及不同密钥的请求,但它是否也适用于对同一实体的冗余调用

换句话说,我的问题是:上面的代码模式是否可以被这个模式取代

类fooancy(ndb.Model):
prop_a=ndb.StringProperty()
prop_b=ndb.StringProperty()
prop_c=ndb.StringProperty()
@微线程
定义某些方法(自身):
self.prop_a=“某些计算的结果”
屈服self.put_async()
@微线程
定义某些方法(自身):
如果出现以下情况:
self.prop_b=“一些新值”
屈服self.put_async()
@微线程
定义某些方法(自身):
如果出现以下情况:
self.prop_b=“一些新值”
屈服self.put_async()
如果出现某些其他情况:
self.prop_b=“一些新值”
self.prop_c=“一些新值”
屈服self.put_async()
@微线程
def(f):
收益率f.某些方法(1)
收益率f.某些方法(2)
收益率f.某些方法(3)

put\u async()
的所有调用是否都会合并到对实体的单个
put
调用中?如果是,与坚持手动检查更新的返回值并在调用序列结束时调用
put
一次相比,使用这种方法是否有任何警告?

尝试注释对象本身,并在返回响应之前进行检查。就像Zope中的_p_changed属性。另一种选择是在返回之前需要写入修改对象的请求/线程本地注册表。有关GAE中threadlocal的示例,请检查google/appengine/runtime/request_environment.py 好吧,我咬紧牙关,在一个启用AppStat的测试GAE应用程序中测试了这3个场景,以查看正在进行的RPC调用:

Foo类(ndb.Model):
prop_a=ndb.DateTimeProperty()
prop_b=ndb.StringProperty()
prop_c=ndb.IntegerProperty()
类3PutsHandler(webapp2.RequestHandler):
def post(自我):
foo=foo.get\u或\u insert('singleton')
foo.prop_a=datetime.utcnow()
foo.put()
foo.prop_b=str(foo.prop_a)
foo.put()
foo.prop_c=foo.prop_a.微秒
foo.put()
类3PutsAsSynchandler(webapp2.RequestHandler):
@顶级
def post(自我):
foo=foo.get\u或\u insert('singleton')
foo.prop_a=datetime.utcnow()
foo.put_async()
foo.prop_b=str(foo.prop_a)
foo.put_async()
foo.prop_c=foo.prop_a.微秒
foo.put_async()
类ThreePutsTaskletHandler(webapp2.RequestHandler):
@微线程
def更新_a(自我,foo):
foo.prop_a=datetime.utcnow()
yield foo.put_async()
@微线程
def更新_b(自身,foo):
foo.prop_b=str(foo.prop_a)
yield foo.put_async()
@微线程
def更新_c(自身,foo):
foo.prop_c=foo.prop_a.微秒
yield foo.put_async()
@顶级
def post(自我):
foo=foo.get\u或\u insert('singleton')
自我更新_a(foo)
自我更新(foo)
自我更新(foo)
app=webapp2.WSGIApplication([
('/ndb批处理/3-puts',三个PUTSHANDLER),
('/ndb batching/3-put-async',ThreePutsAsyncHandler),
('/ndb批处理/3-puts-tasklet',ThreePutsTaskletHandler),
],debug=True)
第一个是
ThreePutsHandler
,显然最后调用了
Put
3次

但是,调用
put_async()
的另外两个测试最终只调用了
put

因此,我的问题的答案是:是的,冗余的ndb.Model.put\u async()调用由ndb的自动匹配功能进行批处理,最终成为单个
数据存储\u v3.put
调用。确实如此