When does an ndb Model's _post_put_hook have a future different from self?
Asked Answered
P

1

6

Google App Engine's ndb provides a _post_put_hook(self, future), documented as follows:

Hook that runs after put()

To understand this hook better, I am wondering when self will differ from the result of the future argument.

The Model Hooks documentation provides:

If you use post-hooks with asynchronous APIs, the hooks are triggered by calling check_result(), get_result() or yielding (inside a tasklet) an async method's future. Post hooks do not check whether the RPC was successful; the hook runs regardless of failure.

All post- hooks have a Future argument at the end of the call signature. This Future object holds the result of the action. You can call get_result() on this Future to retrieve the result; you can be sure that get_result() won't block, since the Future is complete by the time the hook is called.

However, when I call put asynchronously like this:

from google.appengine.ext import ndb

class MyModel(ndb.Model):
   xyz = ndb.StringProperty()

   def _post_put_hook(self, future):
      print "self.xyz: {}, future.xyz: {}".format(
             self.xyz, future.get_result().get().xyz))

m = MyModel()
f = m.put_async()
f.wait()

m.xyz = 'abc'
f = m.put_async()
f.wait()

Outputs:

self.xyz: None, future.xyz: None
self.xyz: abc, future.xyz: abc

In the context of a 'put_async', I think one might reasonably expect the self to be the model before modification, and the future to be the model as now saved. Otherwise it is not clear what purpose future would have in the put context.

When would self and future be different in the context of a put? What is the purpose of the future here?

Platt answered 31/3, 2013 at 19:24 Comment(0)
K
12

I believe the answer is in the description:

Post hooks do not check whether the RPC was successful; the hook runs regardless of failure.

The future can contain the reason for a failure when doing a put(). You can use this knowledge to handle when a put fails by using a hook. For instance, if your _post_put_hook was responsible for incrementing an associated SUM aggregation model based on properties of the model, it could first check to see if the put succeeded before trying to increment the associated SUM aggregation model. I do not believe the value of self and future.get_result().get() will ever be different, as long as the RPC did not fail.

There is always the possibility that another request updated the model after this request's put but before the _post_put_hook was executed, in which future.get_result().get(use_cache=False) may return a different value.

Kella answered 1/4, 2013 at 13:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.