如何在ndb挂钩中使用异步apis?

时间:2018-03-09 11:40:55

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

我有一些钩子,我想我可以使用@ndb.tasklet来装饰它们,以便在钩子中使用异步apis。 e.g。

@classmethod
@ndb.tasklet
def _post_delete_hook(cls, key,future):
    yield do_something_async()

似乎可以正常工作,但我偶尔会看到这些挂钩内的代码出现“暂停生成器”错误。

我应该使用@ ndb.synctasklet吗?

错误的一个例子:

suspended generator _post_put_hook(data_field.py:112) raised TypeError(Expected Future, received <class 'google.appengine.api.apiproxy_stub_map.UserRPC'>: <google.appengine.api.apiproxy_stub_map.UserRPC object at 0x09AA00B0>)

偶尔导致错误的代码是:

           t, d = yield (queue.add_async(task), queue.delete_tasks_async(taskqueue.Task(name=existing_task_name)))

现在我已经放了@ndb.synctasklet它引发了一个实际的异常。

1 个答案:

答案 0 :(得分:2)

ndb tasklet返回未来。如果调用tasklet导致异常,则只有在调用将来的get_result方法时才会引发异常。

ndb.synctasklet会自动调用由tasklet产生的期货get_result,如果发生异常则会引发异常,而不是仅记录。

对于您看到的错误,您可以通过将taskqueue异步方法返回的UserRPC转换为tasklet来修复它。

此未经测试的代码基于ndb.context.urlfetchlink),可将UserRPC生成的urlfetch.createRPC转换为Future

  @ndb.tasklet
  def add_async(queue, **taskqueue_kwargs):
      rpc = queue.add_async(**taskqueue_kwargs)
      result = yield rpc
      raise ndb.Return(result)

您需要为要使用的每个异步方法创建一个tasklet,或者您可以扩展taskqueue类并生成异步方法tasklet。