How different protocols interact with each other in Twisted

The scenario where I want two different protocols to communicate with each other looks like this:

A and B are two different protocols. First A will communicate with the server and get some values. Only after A finishes fetching values ​​will B start communicating with the server.

Now my problem is that there is an elegant way to initialize B when A is retrieving values.

I'm currently just getting started with B in data manipulation function A. But I don't think this is an elegant way.

I mean the elegant way: the initialization of B is done by a thread controller or something, but not by another protocol.

Is there an elegant way? such as delayed or any other things.

I'm just new to twisted, not very knowledgeable about delayed ...

Many thanks!

+2


a source to share


1 answer


You seem to have overcome the first hurdle — figuring out how A and B interact in general. This is good, because for most people this is the biggest conceptual challenge. In terms of elegance, if you take an approach that isolates your protocol code from the application code that controls it (ie "Business Logic"), there are several options. I'll give an example of one based on Deferral.

Consider two POP3 clients. First you want to get the list of messages and then the second one to get the first message from the resulting list. This example



from twisted.internet import defer, protocol, reactor
from twisted.mail.pop3 import AdvancedPOP3Client

class MessageDownloader(object):
    def __init__(self, host, port, user, password):
        self.host = host
        self.port = port
        self.user = user
        self.password = password
        self.cc = ClientCreator(reactor, AdvancedPOP3Client)


    def connect(self):
        """
        Connect to the POP3 server and authenticate.  Return a Deferred
        which fires with the connected protocol instance.
        """
        connDeferred = self.cc.connect(self.host, self.port)
        def cbAuthenticate(proto):
            loginDeferred = proto.login(user, password)
            loginDeferred.addCallback(lambda ignored: proto)
            return loginDeferred
        connDeferred.addCallback(cbAuthenticate)
        return connDeferred


    def run(self):
        connDeferred = self.connect()
        connDeferred.addCallback(self.cbFirstConnection)
        return connDeferred


    def cbFirstConnection(self, firstProto):
        listDeferred = firstProto.listUID()

        def cbListed(uidList):
            connDeferred = self.connect()
            def cbConnected(secondProto):
                return secondProto.retrieve(uidList[0])
            connDeferred.addCallback(cbConnected)
        listDeferred.addCallback(cbListed)
        return listDeferred

if __name__ == '__main__':
    import sys
    MessageDownloader(*sys.argv[1:]).run()
    reactor.run()

      

This is where all the logic for getting the list of UIDs and setting up a new connection to retrieve the message is decoupled from the actual protocol implementation (which is entirely in Twisted). The lazy data returned from almost every API in use allows you to hook up events, however your application wants.

+1


a source







All Articles