10

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

@ndb.toplevel
def post(self):

但是,在文档中它指出:

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

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

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

我应该把@ndb.tasklet刚刚的方法放在上面put_async()吗?(为了安全起见,我应该把它放在每种方法之上吗?这样做有什么缺点?)

4

1 回答 1

10

关于处理程序和使用@ndb.toplevel 和@ndb.synctasklet:我理解的方式是您需要在处理程序上同时使用@ndb.synctasklet 和@ndb.toplevel。所有子任务只需要 @ndb.tasklet 装饰器。例如

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

然而。查看源代码,看来@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() 获取结果)

于 2012-09-04T05:24:20.737 回答