[Welcome] [TitleIndex] [WordIndex

Problem

Sometimes it may be useful to create and reuse things like database connections, proxies for XML-RPC and SOAP client access, etc. This recipe shows how to do so.

Solution

The solution requires that, in your Quixote driver script, you do the following:

Your subclass of quixote.Publisher will have the following:

Implement a Publisher subclass

Here is an example of a subclass of quixote.Publisher that creates a database connection, several XML-RPC proxies, and a SOAP proxy:

from quixote.publish import Publisher
from pyPgSQL import PgSQL
import xmlrpclib

from quixote import enable_ptl
enable_ptl()

# Warning: Must import SOAPpy *after* enable_ptl.  I don't know why.
from SOAPpy import SOAPProxy

class PersistentContainer:
    pass

class MyPublisher(Publisher):
    def __init__(self, root_namespace, config=None):
        Publisher.__init__(self, root_namespace, config)
        self.container = PersistentContainer()
        self.container.dbConnection = PgSQL.connect(CONNECTION_ARGS)
        self.container.xmlrpcProxy = xmlrpclib.ServerProxy('http://localhost:8082')
        self.container.soapProxy = SOAPProxy(str("http://localhost:8083/"))
        meerkatURI = "http://www.oreillynet.com/meerkat/xml-rpc/server.php"
        self.container.meerkatServer = xmlrpclib.Server(meerkatURI)

    def cleanup(self):
        self.container.dbConnection.close()

    def start_request(self, request):
        Publisher.start_request(self, request)
        request.container = self.container

Explanation:

Start the Server

SCGI Initialization

If you use Apache and SCGI, the following will start up the SCGI request handler with your Publisher subclass:

from scgi.quixote_handler import QuixoteHandler, main

class MyAppHandler(QuixoteHandler):
    publisher_class = MyPublisher
    root_namespace = "myapplication.ui"
    prefix = ""

    # QuixoteHandler.serve will raise SystemExit when we should shutdown. The finally:
    # clause will handle this case and make sure we get a chance to cleanup before
    # the interpreter starts to shut down.
    def serve(self):
        try:
            QuixoteHandler.serve(self)
        finally:
            self.publisher.cleanup()

if __name__ == '__main__':
    main(MyAppHandler)

Medusa Initialization

If you use Medusa, the following will start up the Medusa request handler with your Publisher subclass:

from quixote.publish import Publisher
from quixote.server import medusa_http

def start_server(port):
    print 'Now serving the myapplication application on port %i' % port
    server = http_server.http_server('', port)
    publisher = MyPublisher('iptables_firewall_config.ui')
    publisher.read_config('config.py')
    publisher.setup_logs()
    dh = medusa_http.QuixoteHandler(publisher, 'myapplication on medusa server', server)
    server.install_handler(dh)
    try:
        asyncore.loop()
    finally:
        publisher.cleanup()

def main():
    port = 8081
    start_server(port)

if __name__ == "__main__":
    main()

Discussion

This recipe can be employed whenever you wish to reuse a resource or object that has a cost (time or space) when you create it. This recipe ensures that only one request handler can use the resource or object at any one time. Furthermore, it ensures that any one request handler will be finished with handling its request before the resource is given to another request handler.

Because of the way in which requests are handled, under some Web server configurations, more than one instance of the resource may be created. With a Web server configuration which creates multiple processes, as is the case with Apache and SCGI, the Quixote SCGI handler may create more than one process to handle requests concurrently. When this happens, there will be one instance of your resource in each process.


CategoryCookbook


2010-09-22 22:14