[Twisted-Python] XMLRPC server help neede
bv at bnl.gov
Wed Apr 27 11:19:58 EDT 2005
Roland Hedberg <roland.hedberg at adm.umu.se> writes:
> If the packet is well formed and the server knows what to do with it,
> it should reply to the client and then perform the action.
> My problem is how I would go about doing this. Conceptually I could
> imaging having a workqueue where I would place the message and then
> from the point of view of the client-sever communication just forget
> about it.
> Anyone who has done anything similar or has an idea on how to do this ?
I do this by subclassing twisted.web.xmlrpc.XMLRPC and handling the
query in a work queue (appended below) that runs in its own thread.
In my case the client doesn't care if it sent me well formed data or
not, so immediately after putting the query in the work queue I return
from the xmlrpc method and the client is free. In my case, I do some
sanity checking of the query inside the queue. In your case you'd do
the checking before stuffing the queue so you could inform the client.
Here is a sketch of the server chopped out from my code:
from twisted.web import xmlrpc
"The XML-RPC listener"
self.data_cq = CommandQueue()
self.sem = sem
self.services = services
from twisted.python.failure import Failure
if x.__class__ == Failure:
if x.value == "DEBUG": return x
"Accept callbacks from Export API"
d = self.sem.acquire()
d.addCallback(lambda x: self.data_cq(self.services.method,idstr,values))
All the real work is done in the "services.method" method. You'll
note that I use a Semaphore class (appended below). This is keep
other operations not shown here from being executed in the middle of
handling the query.
BTW, the Semaphore and CommandQueue classes were developed with much
help from this list. Thanks again!
from twisted.internet import defer
from Queue import Queue, Empty
from twisted.python import failure
"""Asynchronous semaphore stolen from:
def __init__(self, value=1, verbose=None):
self.queue = 
self.value = value
d = defer.Deferred()
self.value -= 1
self.value += 1
'''Queue up commands for serial calling. One must call the
drain() method to start reading the internal queue. Most likely
one wants to call this in a thread.'''
all_queues = 
"Create a CommandQueue"
self.queue = Queue()
self.stop = False
from twisted.internet import reactor
'''Call meth(*a,**k) when it reaches end of queue. Returns a
Deferred that will pass the return of meth.'''
deferred = defer.Deferred()
'Drain the command queue until CommandQueue.stop is True'
while not self.stop:
d,meth,a,k = self.queue.get(True,1)
#print "calling %s(%s,%s)"%(meth.__name__,str(a),str(k))
res = meth(*a,**k)
res = failure.Failure(sys.exc_value)
#print "callback done"
#print "drain closing"
More information about the Twisted-Python