views:

104

answers:

4

I would like the GAE to do something else once my app has sent a response.

The handler would look like this:

class FooHandler(webapp.RequestHandler):
    def post(self):
        self.response.out.write('Bar')
        send_response()     # this is where I need help!
        do_something_else() # at this point, the response should have been sent

In case you wonder why I try to do this:

I need thread-like behaviour, which is not allowed by GAE's sandboxed environment. So, a function sends several requests whithout caring about the response. Each request starts a time-consuming operation (fetching resources) and saves the result into the datastore, where it can be used by the first function.

Note: The request handler has to send a response. If you do not provide any, it will wait for the post function to complete and then return default headers (which is not the behaviour I'm looking for, of course)

If that can help, the solution might be to use a custom wsgi middeleware, but I have no idea how it works (yet)...

+1  A: 

Presuming you have access to the WSGI layer, you can wrap the WSGI application and provide a callback to be executed once response sent. For how to do this see:

http://code.google.com/p/modwsgi/wiki/RegisteringCleanupCode

Although that is from the mod_wsgi documentation, the cleanup at end of request example should work for any WSGI compliant stack.

Graham Dumpleton
the cleanup function will actually be called prior to the response content being consumed by mod_wsgi and written back to the client
RHicke
Read the referenced document properly. There are two recipes in there, one triggers on initial response from WSGI application and the other when the complete response has been consumed and written back to the client, or in the case of the client connection being aborted, after the connection was lost and everything is being cleaned up. So, use the correct code as documented and it should work as desired.
Graham Dumpleton
@Graham: Irrelevant, because App Engine will not return the response to the user until after the script returns.
Nick Johnson
@Nick: The behaviour is more or less guaranteed by what the WSGI PEP says a WSGI adapter implementation has to do. If GAE says it implements WSGI and it doesn't work in the way that that documentation explains WSGI adapters should, the GAE is not implementing the WSGI specification correctly. See paragraph of WSGI PEP starting with 'If the iterable returned by the application has a close() method' in 'http://www.python.org/dev/peps/pep-0333/#specification-details'. From the perspective of the application, it should be adequate as far as it is the last chance applications get to do something.
Graham Dumpleton
@Nick: Also read paragraphs starting 'WSGI servers, gateways, and middleware must not delay the transmission of any block' in 'http://www.python.org/dev/peps/pep-0333/#buffering-and-streaming'. This is actually the underlying reason. If GAE is, as you suggest, buffering up the complete response and only sending it back to HTTP client when script returns, thereby preventing streaming of response, then that is really what is what is in violation.
Graham Dumpleton
@Graham: I'm well aware of what the WSGI spec says. App Engine doesn't implement WSGI directly, but rather provides a CGI-like interface that WSGI is typically layered on top of. App Engine itself does not return any of the response body to the user until after the user's script (including the WSGI code contained in it) has terminated.
Nick Johnson
A: 

You can't GAE sends it's response when the RequestHandler returns if you actually need Threads you will need to write your web application at another hosting company.

RHicke
+9  A: 

Maybe you can use the Task Queues.

Thilo
The `deferred` library in particular makes this painless, and sounds like exactly you need: http://code.google.com/appengine/articles/deferred.html
Will McCutchen
+1  A: 

As already mentioned, you can use task queues or the deferred API. Another option is outlined by Rafe Kaplan towards the end of his section in this talk here: you can do an asynchronous API call with a result hook function to process the result, and the result hook will be called when the call finishes, after the response is returned to the user!

Nick Johnson