如何将异步 api 与 ndb 挂钩一起使用?

How can you use async apis with ndb hooks?

我有一些挂钩,我想我可以用@ndb.tasklet 装饰它们,以便在挂钩内使用异步 api。 例如

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

这个 似乎 可以工作,但我时不时地看到 "suspended generator" 这些挂钩中的代码出错。

我应该改用@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,它引发了一个实际的异常。

一个 ndb tasklet returns 一个未来。如果调用 tasklet 导致异常,则只有调用 future 的 get_result 方法时才会引发异常。

ndb.synctasklet 自动调用 get_result 对 tasklet 产生的 futures,导致在异常发生时引发异常,而不仅仅是记录。

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

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

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

您需要为每个要使用的异步方法创建一个 tasklet,或者您可以扩展任务队列 class 并制作异步方法 tasklet。