Как отправить запрос XML-RPC из обратного вызова XML-RPC в витой - PullRequest
3 голосов
/ 23 января 2012

Мне нужна сложная логика в моем приложении, например:

  1. Мое приложение - сервер XML-RPC
  2. Получив запрос XML-RPC, он должен выполнить некоторые вычисления.
  3. Затем необходимо вызвать еще один XML-RPC-сервер и проанализировать его ответ.
  4. Далее нужно сделать еще несколько вычислений и
  5. Вернуть результаты шага 4 клиенту XML-RPC.

Я решил это дело примерно так:

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

Как мне это сделать по-витому?

1 Ответ

5 голосов
/ 23 января 2012

Поддержка сервера XML-RPC в Twisted использует Deferred для поддержки асинхронных результатов.Верните Deferred из вашего метода xmlrpc_, и ответ не будет отправлен до тех пор, пока не сработает Deferred.

Twisted также имеет клиентскую библиотеку XML-RPC, которая поддерживает 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 и do_some_calc2 являются процессами с привязкой к процессору, которые являются поточно-ориентированными, поэтому вы можете легко поместить их в пул потоков и получить Deferred для их результатов:

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
...