<h1>Data Flow in Medusa</h1> <img src="data_flow.gif"> <p>Data flow, both input and output, is asynchronous. This is signified by the <i>request</i> and <i>reply</i> queues in the above diagram. This means that both requests and replies can get 'backed up', and are still handled correctly. For instance, HTTP/1.1 supports the concept of <i>pipelined requests</i>, where a series of requests are sent immediately to a server, and the replies are sent as they are processed. With a <i>synchronous</i> request, the client would have to wait for a reply to each request before sending the next.</p> <p>The input data is partitioned into requests by looking for a <i>terminator</i>. A terminator is simply a protocol-specific delimiter - often simply CRLF (carriage-return line-feed), though it can be longer (for example, MIME multi-part boundaries can be specified as terminators). The protocol handler is notified whenever a complete request has been received.</p> <p>The protocol handler then generates a reply, which is enqueued for output back to the client. Sometimes, instead of queuing the actual data, an object that will generate this data is used, called a <i>producer</i>.</p> <img src="producers.gif"> <p>The use of <code>producers</code> gives the programmer extraordinary control over how output is generated and inserted into the output queue. Though they are simple objects (requiring only a single method, <i>more()</i>, to be defined), they can be <i>composed</i> - simple producers can be wrapped around each other to create arbitrarily complex behaviors. [now would be a good time to browse through some of the producer classes in <code>producers.py</code>.]</p> <p>The HTTP/1.1 producers make an excellent example. HTTP allows replies to be encoded in various ways - for example a reply consisting of dynamically-generated output might use the 'chunked' transfer encoding to send data that is compressed on-the-fly.</p> <img src="composing_producers.gif"> <p>In the diagram, green producers actually generate output, and grey ones transform it in some manner. This producer might generate output looking like this: <pre> HTTP/1.1 200 OK Content-Encoding: gzip Transfer-Encoding: chunked Header ==> Date: Mon, 04 Aug 1997 21:31:44 GMT Content-Type: text/html Server: Medusa/3.0 Chunking ==> 0x200 Compression ==> <512 bytes of compressed html> 0x200 <512 bytes of compressed html> ... 0 </pre> <p>Still more can be done with this output stream: For the purpose of efficiency, it makes sense to send output in large, fixed-size chunks: This transformation can be applied by wrapping a 'globbing' producer around the whole thing.</p> <p>An important feature of Medusa's producers is that they are actually rather small objects that do not expand into actual output data until the moment they are needed: The <code>async_chat</code> class will only call on a producer for output when the outgoing socket has indicated that it is ready for data. Thus Medusa is extremely efficient when faced with network delays, 'hiccups', and low bandwidth clients. <p>One final note: The mechanisms described above are completely general - although the examples given demonstrate application to the <code>http</code> protocol, Medusa's asynchronous core has been applied to many different protocols, including <code>smtp</code>, <code>pop3</code>, <code>ftp</code>, and even <code>dns</code>.