简体   繁体   中英

Using @ndb.tasklet or @ndb.synctasklet in Google App Engine

I have a POST method which calls a few tasklets. These tasklets do have yields in them, and I do have some x.put_async() in my code. So I don't want it to return before all the async stuff is done. So I decorated all my tasklets, which are just small functions with @ndb.tasklet . Also, on top of my POST method, I have:

@ndb.toplevel
def post(self):

However, in the documentation it states:

But if a handler method uses yield, that method still needs to be wrapped in another decorator, @ndb.synctasklet; otherwise, it will stop executing at the yield and not finish.

Indeed my method has a yield. It's already wrapped in @ndb.tasklet. Do I replace this with @ndb.synctasklet or do I use both (if so how would I use both)?

Also, see this thread which has some relevance. I too noticed an issue where my request would return without any output, but is un-reproducible. It happens every 15 minutes or so of constant use. I had app = ndb.toplevel(webapp2.WSGIApplication([..]) only, but now I've added @ndb.toplevel to the main POST methods, but the issue still persists.

Should I put @ndb.tasklet on top of methods that have just put_async() 's too? (Should I put it on top of every method just to be safe? What are the downsides to this?)

Regarding the handler and using @ndb.toplevel and @ndb.synctasklet: The way I understood it was that you need to use both @ndb.synctasklet and @ndb.toplevel on the handler. All the sub-tasklets only need the @ndb.tasklet decorator. eg

class Foo(ndb.Model):
    name = ndb.StringProperty()

    @ndb.tasklet
    def my_async(self):
        ....
        #do something else that yields
        raise ndb.Return("some result")   


@ndb.toplevel
@ndb.synctasklet
def post(self):
    foo = Foo(name="baz")
    yield foo.put_async()
    yield foo.my_async()
    ....

However. looking at the source , it appears that @ndb.toplevel is actually a synctasklet anyway:

def toplevel(func):
  """A sync tasklet that sets a fresh default Context.

  Use this for toplevel view functions such as
  webapp.RequestHandler.get() or Django view functions.
  """

Running a small test with yields in the handler and decorated with @ndb.toplevel still seems to work, and appears that you can remove @ndb.synctasklet from the handler.

Regarding whether you should include @ndb.tasklet on methods that call put_async(): If you're not yielding on the put_async(), then you don't need to include @ndb.tasklet on the surrounding method (@ndb.toplevel will handle getting the results from the put_async())

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM