Dave
Dave

Reputation: 9

NDB Async access compatibility with Flask in Google App Engine GAE

I have been going through the google cloud NDB Async examles tutorials

https://cloud.google.com/appengine/docs/standard/python/ndb/async

You can specify a whole WSGIApplication as ndb.toplevel. This makes sure that each of the WSGIApplication's handlers waits for all async requests before returning. (It does not "toplevel" all the WSGIApplication's handlers.)

app = ndb.toplevel(webapp2.WSGIApplication([('/', MyRequestHandler)]))

Is this same functionality compatible with Flask? For example my code

app = Flask(__name__)
app.config.update(DEBUG = not SERVER_ISPRODUCTION)
app = ndb.toplevel(app)
...
@app.route('/test')
def testBackfill(): 

Gives me error

Traceback (most recent call last):
   File "/base/data/home/runtimes/python27_experiment/python27_lib/versions/1/google/appengine/runtime/wsgi.py", line 240, in Handle
    handler = _config_handle.add_wsgi_middleware(self._LoadHandler())
   File "/base/data/home/runtimes/python27_experiment/python27_lib/versions/1/google/appengine/runtime/wsgi.py", line 299, in _LoadHandler
    handler, path, err = LoadObject(self._handler)
   File "/base/data/home/runtimes/python27_experiment/python27_lib/versions/1/google/appengine/runtime/wsgi.py", line 85, in LoadObject
    obj = __import__(path[0]) 
    @app.route('/test')
 AttributeError: 'function' object has no attribute 'route'

This error goes away when I move the toplevel back directly to the request handler. I feel either flask doesn't work with this functionality, or I'm doing something wrong in how I'm using toplevel. My intention is for each of my request handlers within my application to wait for all of my async Google DataStore calls to finish before exiting (I'm using yield statements and tasklets within my request handlers).

Upvotes: 0

Views: 179

Answers (1)

Dan Cornilescu
Dan Cornilescu

Reputation: 39824

The error is kind of expected: app is no longer the Flask app you created. I see 2 options to try:

  • rename the top level app (you need to match the change in the app.yaml config file as well):

    app = Flask(__name__)
    app.config.update(DEBUG = not SERVER_ISPRODUCTION)
    my_app = ndb.toplevel(app)  # change .app -> .my_app app.yaml
    
  • rename the flask app and all its references:

    flask_app = Flask(__name__)
    flask_app.config.update(DEBUG = not SERVER_ISPRODUCTION)
    app = ndb.toplevel(flask_app)
    ...
    @flask_app.route('/test')
    def testBackfill(): **strong text**
    

Note: I'm not a Flask user, this may fix the missing route attribute error but I don't know if it will ultimately make the top level stuff work. But I can't write this as a comment.

Upvotes: 0

Related Questions