Home > OS >  ndb.put_multi_async with cloud ndb
ndb.put_multi_async with cloud ndb

Time:04-26

The Google cloud ndb documentation doesn't say much about async operations.

In the old days, I would do this

@ndb.toplevel
@flask.route('/', methods=['GET'])
def page():
    for x in xxx:
        ndb.put_multi_async([...])
    return 'Done', 200

and the toplevel decorator would make sure that my async puts were done.

How do I do this with the latest cloud ndb?

The cloud ndb docs for toplevel say

Use of this decorator is largely unnecessary, as you should be using context() which also flushes pending work when exiting the context.

but it would be helpful to have more clarity. When would it still be necessary to use toplevel?

CodePudding user response:

Personally, I've always been in the habit of calling .get_result() on my async tasklets/operations, so this is something that I've never actually used.

The only use case i can think of for toplevel is if you want to force the flush to occur before you reach the end of your request handler (because at the end of your request handler, you should be exiting the context). In the example below, we want the puts in operation_1 to finish before operation_2 begins:

@ndb.toplevel
def operation_1():
    for x in xxx:
        ndb.put_multi_async([...])

@flask.route('/', methods=['GET'])
def page():
    operation_1()
    operation_2()
    return 'Done', 200

This could be useful for request handlers for Google Cloud Tasks which can run for up to 10 minutes, so you could be doing a bunch of things in there.

CodePudding user response:

As stated in the documentation for the NDB Asynchronous Operation:

As a convenience, you can decorate the request handler with @ndb.toplevel. This tells the handler not to exit until its asynchronous requests have finished. ... Using a toplevel application is more convenient than all its handler functions.

This was convenient when using the NDB Client Library with Python 2, as you've said:

the toplevel decorator would make sure that my async puts were done

Nowadays using the Cloud NDB library, as shown in this answer,

each NDB operation needs to be wrapped in a context manager:

 with ndb_client.context(): # <- you need this line
    cls.get_or_insert('master') 

That is why the documentation says that the use of toplevel decorator

is largely unnecessary, as you should be using context()

because context decorator replaced it and it will

flush pending work_ as async operations.

As referred in the Client NDB documentation:

The context is used to manage the connection to Google Cloud Datastore, an event loop for asynchronous API calls, runtime caching policy, and other essential runtime state.

Finally, as referred in the ndb Migration notes:

The biggest difference is in establishing a runtime context for your NDB application. The Google App Engine Python 2.7 runtime had a strong assumption that all code executed inside a web framework request-response cycle, in a single thread per request. In order to decouple from that assumption, Cloud NDB implements explicit clients and contexts.

  • Related