[Cross posted between the source of the discussion and the Web-SIG for additional discussion there.]

On 2011-03-15 14:54:18 -0700, Mike Orr said:

There has been an ongoing discussion between the WSGI developers and Twisted about how to be more compatible. The upshot is that asynchronous servers need some kind of token in the output stream that means "I'm not ready; come back later." Other middleware would have to pass this token through unchanged. And of course, the application would have to use non-blocking libraries such as non-blocking database executors. I'm not sure if ordinary file access is "blocking" enough to require that too.

Not just Twisted; have a gander at the Web-SIG mailing list for December and January.[1]

Unfortunately the amount of interconnectedness (and thus complexity) needed for a working solution takes the concept of async completely out of the domain of a low-level specification like WSGI.

An "I'm not ready; come back later" token, which in marrow.server.http is already implemented—yield None from your body iterator—would, as an example, add an immediate (or slightly delayed) callback in the reactor[2] which will then poll the application for real data. That's not async; that's no better than AJAX polling! (And is unidirectional to boot.)

Non-blocking libraries… how do they determine how to be non-blocking? Socket and file operations, which can be easily made non-blocking through the use of select/epoll/kqueue/libevent/libev, have the distinction of being handled (and likely already used) at the WSGI server's reactor level. How would a third-party library interface to an existing reactor in an agnostic way? I'm fairly confident that it just wouldn't be feasible.

If non-blocking libraries implemented their own async reactors… how would you coordinate the mess of having, potentially, half a dozen reactors?

Futures objects take some of the headache away, allowing for the WSGI application to ask for some work to be performed by a third-party library, returning a Future, then being suspended pending the result of the Future. Futures are easy to detect (through duck typing) and can be easily ignored (and passed along) by middleware.

Still, Futures are usually bound to an Executor (reactor), and that executor instance would need to be passed to the third-party libraries somehow. marrow.server.http provides a 'wsgi.executor' environment variable which is, usually, a thread pool worker, which still doesn't quite qualify for async status.

A PEP extending Futures for use with true async models would be a great start, and could likely be combined with a simple extension to WSGI to add the appropriate environment variables. Alex Grönholm, Graham Dumpleton, everyone on the (excellent, if lacking in bloody combat ;) WSGI panel at PyCon, and I seem to all agree that async has no part in core WSGI. There would simply be no way to get a consensus on a single API with so many disparate implementations already in the wild.

The upshot has been that Twisted runs WSGI applications in a thread anyway because it can't be sure they won't block.

As does marrow.server.http if requested to do so. Extremely small or efficient applications can choose not to.

And there hasn't been enough interest from WSGI developers to actually pursue using it with asynchronous servers.

I've been interested, as has my partner in crime. We've actually fiddled around with futures-based core IO reactors, different return / yield styles for WSGI applications, and all sorts of crazy things, and always came to the same conclusion. :(

I think Python has a future object now which standardizes Twisted's Deferred and the equivalent in other asynchronous servers. So that's a start.

The core Futures implementation (concurrent.futures; core in Python 3.2 with a portable back-port maintained, I believe, by Alex) utilizes a thread pool or process pool, has referential limitations (i.e. don't pass the executor to a future running in a process pool… deadlocks are bad), and I simply have no idea at this time how difficult it would be to create a true async reactor under that model.


The end result of all of this is that async support should be its own PEP, extending WSGI (333, now 3333) and potentially extending Futures, PEP 3148[3], to create an acceptable generalized API for async interfaces, not just worker pools. I've abandoned the idea for my own WSGI 2 WIP, PEP 444[3], which marrow.server.http is the reference implementation (and idea sandbox) of/for.

        — Alice.

P.s. If anyone has information I don't have, or simply can't remember at midnight after a very long day, feel free to correct me! :)

[1] http://mail.python.org/pipermail/web-sig/

[2] I know, 'reactor' isn't exactly an accurate term. I just can't remember the right one right now.

[3] http://www.python.org/dev/peps/pep-3148/

[4] http://bit.ly/fRyMJ2


--
You received this message because you are subscribed to the Google Groups 
"pylons-devel" group.
To post to this group, send email to pylons-devel@googlegroups.com.
To unsubscribe from this group, send email to 
pylons-devel+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/pylons-devel?hl=en.

Reply via email to