如何使用带有ndb钩子的异步api ?

时间:2023-01-24 18:12:32

I have some hooks in place, and I thought I could decorate them with @ndb.tasklet in order to use async apis inside the hooks. e.g.

我有一些挂钩,我想我可以用@ndb来装饰它们。在钩子中使用异步api。如。

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

This seemed to work, but every now and then I see "suspended generator" error for the code inside those hooks.

这似乎是可行的,但我偶尔会看到这些钩子中的代码出现“挂起生成器”错误。

Should I be using @ndb.synctasklet instead?

我应该使用@ndb吗?synctasklet呢?

An example of error:

一个错误的例子:

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

The code causing the error occasionally was:

导致错误的代码偶尔是:

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

Now that I've put @ndb.synctasklet it raises an actual exception.

现在我输入了@ndb。synctasklet引发了一个实际的异常。

1 个解决方案

#1


2  

An ndb tasklet returns a future. If calling the tasklet results in an exception, the exception will only be raised if the future's get_result method is called.

一个ndb微线程返回一个未来。如果调用微线程导致异常,那么只有在调用未来的get_result方法时才会引发异常。

ndb.synctasklet automatically calls get_result on the futures yielded by tasklets, causing exceptions to be raised if they occurred, rather than just logged.

ndb。synctasklet在tasklet生成的期货上自动调用get_result,在异常发生时引发异常,而不是仅仅记录日志。

For the error that you are seeing, you may be able to fix it by converting the UserRPCs returned by the taskqueue async methods to tasklets.

对于您正在看到的错误,您可以通过将taskqueue异步方法返回的UserRPCs转换为微线程来修复它。

This untested code is based on ndb.context.urlfetch (link), which converts the UserRPC produced by urlfetch.createRPC into a Future.

这个未测试的代码基于ndb.context。urlfetch (link),它转换urlfetch生成的UserRPC。createRPC变成一个未来。

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

You would need to create a tasklet for each async method that you want to use, or you could extend the taskqueue class and make the async methods tasklets.

您需要为您想要使用的每个异步方法创建一个微线程,或者您可以扩展taskqueue类并使异步方法微线程。

#1


2  

An ndb tasklet returns a future. If calling the tasklet results in an exception, the exception will only be raised if the future's get_result method is called.

一个ndb微线程返回一个未来。如果调用微线程导致异常,那么只有在调用未来的get_result方法时才会引发异常。

ndb.synctasklet automatically calls get_result on the futures yielded by tasklets, causing exceptions to be raised if they occurred, rather than just logged.

ndb。synctasklet在tasklet生成的期货上自动调用get_result,在异常发生时引发异常,而不是仅仅记录日志。

For the error that you are seeing, you may be able to fix it by converting the UserRPCs returned by the taskqueue async methods to tasklets.

对于您正在看到的错误,您可以通过将taskqueue异步方法返回的UserRPCs转换为微线程来修复它。

This untested code is based on ndb.context.urlfetch (link), which converts the UserRPC produced by urlfetch.createRPC into a Future.

这个未测试的代码基于ndb.context。urlfetch (link),它转换urlfetch生成的UserRPC。createRPC变成一个未来。

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

You would need to create a tasklet for each async method that you want to use, or you could extend the taskqueue class and make the async methods tasklets.

您需要为您想要使用的每个异步方法创建一个微线程,或者您可以扩展taskqueue类并使异步方法微线程。