Search code examples
google-app-enginegoogle-cloud-datastorendb

ndb.put_multi_async with cloud ndb


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?


Solution

  • 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.