如何将异步 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.urlfetch
(link),它将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。
我有一些挂钩,我想我可以用@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.urlfetch
(link),它将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。