On Oct 7, 2004, at 1:28 AM, Phillip J. Eby wrote:
- For async applications, with the proposed API, that may not be an option, because the iterable returned is the special wrapper, not a user-created class. Although, actually, I guess the app can return its own iterable whose __iter__ calls through and returns the wrapper's __iter__.
Not if the server wants to be able to handle that iterable specially. But anyway, it seems that the wrapper's constructor should take a close method, or have a way to set one.
As already discussed, the server cannot really expect to actually get the iterable back anyhow. But yes, I'd say either the init should take a close argument, or else the use of something like "wrapper.close = myCloseFunction" should be part of the API.
Hmm, yes. I totally missed the option of just yielding ''. Of course it's a very bad idea to repeatedly yield '' to a server if you don't know the server can properly handle it (by e.g. delaying longer and longer), but, in this case, since the server itself is providing the special iterable, that should be fine.
Yes. Also, when we finally settle on an async API, I do want to cover the issue of backing off iteration when empty strings are yielded. I'm actually inclined to suggest that an async application should take responsibility for doing the delaying if it's called repeatedly, and the async API isn't available.
If the async API isn't available, and I'm an async application, I would assume I'm running on a synch server, and thus am allowed to block the request thread indefinitely, and do so, waiting for a wakeup notification from the reactor loop. It doesn't seem to me that any iterator back-off behavior is needed, or desirable. I can fabricate an async wrapper that uses threads
It seems like it should be possible to make a generic class that implements this async API for use with sync servers that do not support it natively. That would allow async apps to run on a sync server without modification, which is potentially useful. To do that, though, I think the it'd have to spawn an extra thread per request that is waiting to read data, for the read() call to block on. Unless, of course, the app never needs to yield outgoing data while waiting for incoming data.
Well, with Twisted you could deferToThread the read() operations, though it's hard for me to think straight about that scenario because I keep finding it hard to imagine an async web app that isn't just written to the Twisted API to start with... ;)
Right -- but deferToThread'ing a read() operation is essentially the same as spawning an extra thread per request to read the data, just with nicer thread management.
[thread stuff]
I haven't really thought about these thready questions much either, so maybe the answers are obvious, but in my experience, that's usually not the case when it comes to threads.
Yep. :) However, the more I think about it, the more it seems to me that WSGI should emulate single-threadedness with respect to any function/method/iterator invocations associated with a given application invocation. However, it is *not* guaranteed that all such invocations will occur from the same thread.
Basically, it means "no multitasking with the other guy's objects", and puts the locking burdens on whoever's trying to mix multitasking into the works.
That does sound good. No multitasking means it's impossible to write a response while already waiting for incoming data. But actually I think it's probably fine for an async app running on a sync server to not be able to simultaneously read data and write data, so I take back anything about needing to call wsgi server methods from more than one thread. In the compat wrapper, calling on_get can just block writing until the read has occurred; in that case, all wsgi methods can be called from the server's request thread.
By the way, after all this discussion... do you think it would be better to:
1) Push towards a full async API, nailing down all these loose ends
2) Use the simple-but-klugdy "pause iteration" API idea
3) Don't make an "official" async API, and just leave it open to server authors to create their own extensions, and maybe cherry pick the best ideas for WSGI 2.0, or
4) Do something else altogether?
I think the API you've outlined sounds good. I can imagine ways to implement it both for an async server like twisted, and as a compatibility layer for an async-requiring application on a sync server. I think it's easier to make the compatibility layer with this API than with the pause/resume API. However, I would be quite wary of including it in the final spec without it being implemented first. Another question is: what is the current use for it? Does anyone want to write untwisted async web applications? My current interest in WSGI is basically on the "plug twisted web into another webserver as an application" side of things. I wouldn't want to write an application to WSGI (without a framework on top)... If everyone else feels that way, an async API may not be actually useful until there is some other Async-WSGI web server that you could plug twisted framework stuff on top of, or some other async framework you can plug on top of the twisted server. As for postponing until WSGI 2.0, I would hope there doesn't need to be a WSGI 2.0, though, since the interface is so darn simple. ;) But it could be in a separate WSGI async addons. James