tags:

views:

67

answers:

2

In a pylons controller, I would like to first return the response to the request (so that the user gets a response ASAP), and then perform some additional operations (say, updating view counts, etc.) that didn't need to happen to generate the response. What's the best-practice for doing things like this?

Thanks!

A: 

I did not have the chance to try Python threads yet, but you could do something like:

def controller_method(self):
    # controller logic here
    html = render('/template.mako')
    # start a thread here
    return html

By starting the thread after all the logic, but just before returning, you should avoid conflicts between the threads.

You might also have a look at RabbitMQ or other message queuing software. You could offload your main web application by sending the jobs in a queue.

Antoine Leclair
Thanks! I guess there's no easy way to flush the response and then do a little more work in the same request thread?
Chung Wu
I don't think so. If you look at the the most basic WSGI app you can make, you return the HTML to send to the browser in your function.
Antoine Leclair
Threads might work, but then again they might not. Especially there are issues with long-lived background threads and server shutdown: if you don't make them daemon threads, the server may never shut down; if you do make them daemon threads, they may be interrupted in the middle of a critical operation with weird side effects like all module globals becoming None resulting in weird errors. I've yet to play with threads in a Pylons context, but the Pylons mailing list had some discussions about the issues.
Marius Gedminas
+2  A: 

On most wsgi-based servers (like the standard wsgiref, nwsgi etc) there is a way to send some portion of a body out work a little more and send some more. I guess the "send some more" is optional.

Use yield instead of return. WSGI example (not sure if it translates well into Pylons):

def application(environ, start_response):
    start_response('200 OK', [('Content-type','text/plain')])
    yield 'body starts. You should see this in browser already'
    # do something
    yield 'some more of body'

Once the request handler runs out of code to run, it closes the connection.

Now, this is sure to work on standard wsgi servers I tried. I would like to hear if this works on Pylons.

ddotsenko
Note that a lot of WSGI middleware wait to collect all of the response before passing it on. IIRC WebError act like this, so this kind of backgrounding might not work if you've debug = true in your Pylons development.ini.
Marius Gedminas