3

I need complex logic in my application, eg:

  1. My application is XML-RPC server
  2. When it received XML-RPC request it needs to do some calculations.
  3. Then it need to call another one XML-RPC server, and parse it's response.
  4. Next it need to do some more calculations and
  5. Return results of step 4 to XML-RPC client.

I solved this case something like that:

from twisted.web import xmlrpc
import xmlrpclib

class RPCProxy(xmlrpc.XMLRPC):

  def xmlrpc_do_something(self, param1, param2):
    result1 = self.do_some_calc1(param1, param2)
    s = xmlrpclib.ServerProxy('http://some.another.server:1234/RPC2')
    result2 = getattr(s, 'do_something_else')(result1)
    result3 = self.do_some_calc2(result2)
    return result3

How should i do this in a Twisted-like way?

Sharkman
  • 133
  • 12

1 Answers1

5

The XML-RPC server support in Twisted uses Deferreds to support asynchronous results. Return a Deferred from your xmlrpc_ method and no response will be sent until the Deferred fires.

Twisted also has an XML-RPC client library that supports Deferreds.

from twisted.web import xmlrpc

class RPCProxy(xmlrpc.XMLRPC):

    def xmlrpc_do_something(self, param1, param2):
        result1 = self.do_some_calc1(param1, param2)
        s = xmlrpc.Proxy('http://some.another.server:1234/RPC2')
        deferredResult = s.callRemote('do_something_else', result1)
        deferredResult.addCallback(self.do_some_calc2)
        return deferredResults

If do_some_calc1 and do_some_calc2 are CPU-bound operations that are thread-safe, then you can easily shove them into a thread pool and get a Deferred for their results too:

from twisted.web import xmlrpc
from twisted.internet import threads

class RPCProxy(xmlrpc.XMLRPC):

    def xmlrpc_do_something(self, param1, param2):
        deferredResult = threads.deferToThread(self.do_some_calc1, param1, param2)

        def gotCalc1(result1):
            s = xmlrpc.Proxy('http://some.another.server:1234/RPC2')
            return s.callRemote('do_something_else', result1)
        deferredResult.addCallback(gotCalc1)

        def gotResult2(result2):
            return threads.deferToThread(self.do_some_calc2, result2)
        deferredResult.addCallback(gotResult2)

        return deferredResults
Jean-Paul Calderone
  • 47,755
  • 6
  • 94
  • 122