[Web-SIG] WSGI uses

tony at lownds.com tony at lownds.com
Thu Aug 19 21:37:01 CEST 2004


> For instance, I was thinking about setting up something for Medusa with
> WSGI.  But though I think asynchronous code seems like a good server
> architecture, I'm not that interested in it for applications.  But this
> iteration of the WSGI spec allows for async pretty well; you can tell
> you are in that situation when wsgi.multiprocess is false and
> wsgi.multithread is false, and the iterator output can produce the data
> fairly well.
>

How do you decide when to actually send the data back to the client? On
every yield?

That could perform badly if one does

def application(...):
  ...
  return open(filename)

...that usage is actually suggested in the spec.

In a similar vein, if servers/gateways send data back on every call to
write, and applications don't take that into account, they could also
suffer in performance. It seems like an object with write() and flush()
makes it easier to provide guarantees about streaming -- which I think
WSGI ought to do.

> I then realized that threading itself could be a piece of middleware --
> you just have to do the proper buffering with input and output.  An
> intelligent application that realizes it can't run as an async process
> could install this middleware itself when necessary.
>

Did you find that an async server has to provide a new buffer for every
request to implement the write() function correctly?

Although I suggested the (env, start_response) -> write() protocol, it
just can't adapt to future needs. As soon as more than one function/method
is needed, the API is broken -- and can't be fixed.

For instance, having one method to start the response and NOT get a
write() function could allow server/gateways avoid some work...

What about passing in a class with class methods in place of the
start_response method? i.e.

class ContextLogic:
    @classmethod
    def start_writing(cls, env, status, headers):
       cls.start(env, status, headers)
       # prepare output object
       return output.write

    @classmethod
    def start(cls, env, status, headers):
        ....

    @classmethod
    def request_url(cls, env):
        ...

    @classmethod
    def get_input_stream(cls, env):
       ...

Contexts can be re-used, and middleware does not have to delegate (it just
subclasses on the fly).

class Pooler:
    class PoolingLogicMixin:
         @classmethod
         def get_pool(cls, env):
             ...

    def __init__(self, subapp, ...):
        self.subapp = subapp

    def __call__(self, context, env):
        class NewContext(PoolingLogicMixin, context): pass
        return self.subapp(NewContext, env)

One more thought: how about using the term WSGI "driver" instead of
server/gateway?

-Tony




More information about the Web-SIG mailing list