在Google App Engine中使用@ ndb.tasklet或@ ndb.synctasklet

时间:2012-09-04 02:34:13

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

我有一个调用几个tasklet的POST方法。这些tasklet确实有产量,我的代码中确实有一些x.put_async()。所以我不希望它在所有异步内容完成之前返回。所以我装饰了所有的tasklet,它们只是@ndb.tasklet的小函数。此外,除了POST方法之外,我还有:

@ndb.toplevel
def post(self):

然而,在documentation中声明:

  

但是如果处理程序方法使用yield,那么该方法仍然需要   包装在另一个装饰器中,@ ndb.synctasklet;否则,它会   停止执行收益而不是完成。

确实我的方法有收益率。它已经包含在@ ndb.tasklet中。我是否用@ ndb.synctasklet替换它或者我同时使用它们(如果是这样,我将如何使用它们)?

另外,请参阅this thread,它具有一定的相关性。我也注意到一个问题,我的请求将返回没有任何输出,但是不可重现。它每15分钟左右就会持续使用。我只有app = ndb.toplevel(webapp2.WSGIApplication([..]),但现在我已将@ndb.toplevel添加到主POST方法,但问题仍然存在。

我是否应该将@ndb.tasklet放在仅有put_async()的方法之上? (为了安全起见,我应该把它放在每个方法的顶部吗?这有什么缺点?)

1 个答案:

答案 0 :(得分:10)

关于处理程序并使用@ndb.toplevel和@ndb.synctasklet: 我理解它的方式是你需要在处理程序上使用@ ndb.synctasklet和@ ndb.toplevel。所有子tasklet只需要@ ndb.tasklet装饰器。 e.g。

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()
    ....

然而。看source,似乎@ ndb.toplevel实际上是一个synctasklet:

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.
  """

在处理程序中运行带有yield并用@ ndb.toplevel修饰的小测试似乎仍然有效,并且似乎可以从处理程序中删除@ ndb.synctasklet。

关于是否应该在调用put_async()的方法中包含@ ndb.tasklet: 如果你没有屈服于put_async(),那么你不需要在周围的方法中包含@ ndb.tasklet(@ ndb.toplevel将处理从put_async()获取结果)