|Title:||Suspend WSGI application execution|
|Author:||Manlio Perillo <firstname.lastname@example.org>|
|Discussions-To:||Python Web-SIG <email@example.com>|
This specification defines a set of extensions that allow a WSGI application to suspend its execution, and resume it later. The specification is based on an informal propose by Phillip J. Eby, described in a thread on the twisted-web mailing list.
The WSGI 1.0 specification (ignoring the deprecated write callable) has been designed so that it can be implemented on asynchronous servers. Since the WSGI application returns an iterator, the WSGI implementation is allowed to suspend iteration over app_iter, if the socket channel can not send the produced data to the client. When the WSGI application returns a generator, the execution of application code will be suspended. This specification defines a standard interface by which WSGI applications can explicitly suspend their execution, and resume it later.
This specification introduces two new variables to the WSGI environment: x-wsgiorg.suspend and x-wsgiorg.suspend_status.
The variable x-wsgiorg.suspend is a callable object that accept an optional positional argument. In the following description, this argument is given the name timeout, but it is not required to have this name, and the application must invoke the callable using positional argument.
The timeout argument is either None or an integer value in milliseconds. If omitted, it defaults to None.
The x-wsgiorg.suspend callable returns a callable, named resume in this specification. The callable does not accept arguments. When called, the server will resume execution of the WSGI application, if this was suspended. How this is done is not specified.
After calling x-wsgiorg.suspend, the application must yield an empty string (''), in the application iterable to the server. (The result of calling x-wsgiorg.suspend and yielding a non-empty string, or making multiple calls to x-wsgiorg.suspend before yielding the empty string, is undefined.) The server then suspends execution of the application until one of the following conditions is met:
- The WSGI application calls the resume callable.
- timeout milliseconds have elapsed without the resume callable being called, unless the value of timeout is None, in which case the wait will never timeout.
The resume callable returns a boolean value:
- if WSGI application was suspended and will be resumed
- if WSGI application was not in suspended state
The variable x-wsgiorg.suspend_status is a callable object that require no arguments. It returns an integer that can have the following values:
- if WSGI application was resumed due to timeout
- if WSGI application is in suspended state
- if WSGI application was resumed due to resume being called
The result of calling x-wsgiorg.suspend_status before calling x-wsgiorg.suspend and yielding an empty string in the application iterable to the server, is undefined.
The following example illustrates a very simple use of the x-wsgiorg.suspend extension.
More advanced examples can be found in txwsgi, a reference asynchronous implementation of WSGI for the Twisted Web server.
def application(environ, start_response): def app_iter(): resume = suspend(500) yield '' resumed = resume() status = suspend_status() yield 'resumed: %d, status: %d\n' % (resumed, status) yield '.' * 76 + '\n' resume = suspend(3000) yield '' resumed = resume() status = suspend_status() yield 'resumed: %d, status: %d\n' % (resumed, status) suspend = environ['x-wsgiorg.suspend'] suspend_status = environ['x-wsgiorg.suspend_status'] start_response('200 OK', [('Content-Type', 'text/plain')]) return app_iter()
- The empty string yielded by an application after calling x-wsgiorg.suspend must pass through any intervening middleware and be detected by the server. Although WSGI explicitly requires middleware to relay such strings to the server (see Middleware Handling of Block Boundaries), some components may not, making them incompatible with this specification.
This specification provides a generalization of the interface documented in the x-wsgiorg.fdevent specification.
x-wsgiorg.suspend is more easy to implement, and, above all, does not specify how WSGI application is resumed (that is, how resume will be called).
The txwsgi implementation provides an example (doc/examples/demo_fdevent.py) that use Twisted Reactor API to wait for file descriptor read of write ready status. The example is similar to the one described in the x-wsgiorg.fdevent specification.
- Should timeout be specified as a floating-point value in seconds?
- Should x-wsgiorg.suspend_status be renamed x-wsgiorg.suspend.timeout, and have a value as specified for x-wsgiorg.fdevent.timeout?