[Twisted-web] Re: [Web-SIG] A more Twisted approach to async apps
James Y Knight
foom at fuhm.net
Fri Oct 15 09:20:34 MDT 2004
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.
More information about the Twisted-web