At 01:24 PM 1/8/2011 -0500, Paul Davis wrote:
For contrast, I thought it might be beneficial to have a comparison
with an implementation that didn't use async might look like:

http://friendpaste.com/4lFbZsTpPGA9N9niyOt9PF

Compare your version with this one, that uses my revision of Alice's proposal:

def my_awesome_application(environ):
    # do stuff
    yield b'200 OK', [], ["Hello, World!"]

def my_middleware(app):
    def wrapper(environ):
        # maybe edit environ
        try:
            status, headers, body = yield app(environ)
            # maybe edit response:
            # body = latinize(body)
            yield status, headers, body
        except:
            # maybe handle error
        finally:
            # maybe release resources

def my_server(app, httpreq):
    environ = wsgi.make_environ(httpreq)

    def process_response(result):
        status, headers, body = result
        write_headers(httpreq, status, headers)
        Coroutine(body, body_trampoline, finish_response)

    def finish_response(result):
        # cleanup, if any

    Coroutine(app(environ), app_trampoline, process_response)


The primary differences are that the server needs to split some of its processing into separate routines, and response-processing done by middleware has to happen in a while loop rather than a for loop.


If your implementation requires that people change source code (yield
vs return) when they move code between sync and async servers, doesn't
that pretty much violate the main WSGI goal of portability?

The idea here would be to have WSGI 2 use this protocol exclusively, not to have two different protocols.


IMO, the async middleware is quite more complex than the current state
of things with start_response.

Under the above proposal, it isn't, since you can't (only) do a for loop over the response body; you have to write a loop and a push-based handler as well. In this case, it is reduced to just writing one loop.

I'm still not entirely convinced of the viability of the approach, but I'm no longer in the "that's just crazy talk" category regarding an async WSGI. The cost is no longer crazy, but there's still some cost involved, and the use case rationale hasn't improved much.

OTOH, I can now conceive of actually *using* such an async API for something, and that's no small feat. Before now, the idea held virtually zero interest for me.


Either way this proposal reminds me quite a bit of Duff's device [1].
On its own Duff's device is quite amusing and could even be employed
in some situations to great effect. On the other hand, any WSGI spec
has to be understandable and implementable by people from all skill
ranges. If its a spec that only a handful of people comprehend, then I
fear its adoption would be significantly slowed in practice.

Under my modification of Alice's proposal, nearly all of the complexity involved migrates to the server, mostly in the (shareable) Coroutine implementation.

For an async server, the "arrange for coroutine(result) to be called" operations are generally native to async APIs, so I'd expect them to find that simple to implement. Synchronous servers just need to invoke the waited-on operation synchronously, then pass the value back into the coroutine. (e.g. by returning "pause" from the trampoline, then calling coroutine(value, exc_info) to resume processing after the result is obtained.)


_______________________________________________
Web-SIG mailing list
Web-SIG@python.org
Web SIG: http://www.python.org/sigs/web-sig
Unsubscribe: 
http://mail.python.org/mailman/options/web-sig/archive%40mail-archive.com

Reply via email to