[Twisted-Python] improving foolscap's use of Twisted
Greetings, My goal is to get Brian Warner's foolscap library ported to Twisted endpoints instead of the older Twisted api interfaces it currently uses (ClientFactory and IConnector). This effort has been documented in foolscap trac ticket #203: http://foolscap.lothar.com/trac/ticket/203 and also part of Tahoe-LAFS trac ticket #517 - make tahoe Tor- and I2P-friendly: https://tahoe-lafs.org/trac/tahoe-lafs/ticket/517 My question is this: Since Foolscap's TubConnectorClientFactory does rely on clientConnectionFailed... What is the equivalent to this for the new interfaces? I have tried to braindump all my foolscap twisted endpoint thoughts to foolscap trac ticket #203 : http://foolscap.lothar.com/trac/ticket/203#comment:30 http://foolscap.lothar.com/trac/ticket/203#comment:31 If we look at line 1223 of https://github.com/warner/foolscap/blob/master/foolscap/negotiate.py (at 0395476c7cb154f925d67abf6858a8200126352b) we see that there's this TubConnectorClientFactory: class TubConnectorClientFactory(protocol.ClientFactory, object): and later at line 1384 it is used with connectTCP like this: f = TubConnectorClientFactory(self, host, lp) c = reactor.connectTCP(host, port, f) In my endpoints2 branch (https://github.com/david415/foolscap/tree/endpoints2) I changed it to: class TubConnectorFactory(protocol.Factory, object): I suspected that TubConnector?'s clientConnectionFailed doesn't get called and then I found a relevent quaote this twisted doc: https://twistedmatrix.com/documents/current/core/howto/endpoints.html here's the quote: """Note: If you've used ClientFactory before, keep in mind that the connect method takes a Factory, not a ClientFactory. Even if you pass a ClientFactory to endpoint.connect, its clientConnectionFailed and clientConnectionLost methods will not be called.""" Currently foolscap's extensive collection of unittests are exercising bugs in my code when I try to port foolscap to twisted endpoints. foolscap$ trial foolscap.test.test_appserver.RunCommand.test_run foolscap.test.test_appserver RunCommand test_run ... [ERROR] =============================================================================== [ERROR] Traceback (most recent call last): Failure: foolscap.tokens.NegotiationError: no connection established within client timeout foolscap.test.test_appserver.RunCommand.test_run ------------------------------------------------------------------------------- Ran 1 tests in 60.576s FAILED (errors=1) foolscap$ Cheers! David Stainton
On 10:02 am, dstainton415@gmail.com wrote:
Greetings,
My goal is to get Brian Warner's foolscap library ported to Twisted endpoints instead of the older Twisted api interfaces it currently uses (ClientFactory and IConnector).
This effort has been documented in foolscap trac ticket #203: http://foolscap.lothar.com/trac/ticket/203
and also part of Tahoe-LAFS trac ticket #517 - make tahoe Tor- and I2P- friendly: https://tahoe-lafs.org/trac/tahoe-lafs/ticket/517
My question is this:
Since Foolscap's TubConnectorClientFactory does rely on clientConnectionFailed... What is the equivalent to this for the new interfaces?
I have tried to braindump all my foolscap twisted endpoint thoughts to foolscap trac ticket #203 : http://foolscap.lothar.com/trac/ticket/203#comment:30 http://foolscap.lothar.com/trac/ticket/203#comment:31
If we look at line 1223 of https://github.com/warner/foolscap/blob/master/foolscap/negotiate.py (at 0395476c7cb154f925d67abf6858a8200126352b)
we see that there's this TubConnectorClientFactory: class TubConnectorClientFactory(protocol.ClientFactory, object):
and later at line 1384 it is used with connectTCP like this: f = TubConnectorClientFactory(self, host, lp) c = reactor.connectTCP(host, port, f)
It looks like TubConnector is the primary intended user of TubConnectorClientFactory. In this case, you can simply move the logic from TubConnector.clientConnectionFailed to an errback on the Deferred returned by IStreamClientEndpoint.connect. Or you can leave it where it is an just make clientConnectionFailed be that errback. For example: f = TubConnectorClientFactory(self, host, lp) d = endpoint.connect(f) d.addErrback(self.clientConnectionFailed) (removing the connector argument from clientConnectionFailed, of course). You may want to apply a similar transformation to the *success* case here as well. That is, move the code that initiates protocol actions on the connection to a callback on this Deferred instead of automatically starting those actions in buildProtocol (this gives greater flexibility in how the protocol is used - if you want to change the details of initialization you can do so by using a different callback on the endpoint's Deferred instead of having to mess around with the factory or the protocol to disable this stuff). Jean-Paul
Thanks! That's just what I needed. On Sat, Mar 8, 2014 at 12:52 PM, <exarkun@twistedmatrix.com> wrote:
On 10:02 am, dstainton415@gmail.com wrote:
Greetings,
My goal is to get Brian Warner's foolscap library ported to Twisted endpoints instead of the older Twisted api interfaces it currently uses (ClientFactory and IConnector).
This effort has been documented in foolscap trac ticket #203: http://foolscap.lothar.com/trac/ticket/203
and also part of Tahoe-LAFS trac ticket #517 - make tahoe Tor- and I2P- friendly: https://tahoe-lafs.org/trac/tahoe-lafs/ticket/517
My question is this:
Since Foolscap's TubConnectorClientFactory does rely on clientConnectionFailed... What is the equivalent to this for the new interfaces?
I have tried to braindump all my foolscap twisted endpoint thoughts to foolscap trac ticket #203 : http://foolscap.lothar.com/trac/ticket/203#comment:30 http://foolscap.lothar.com/trac/ticket/203#comment:31
If we look at line 1223 of https://github.com/warner/foolscap/blob/master/foolscap/negotiate.py (at 0395476c7cb154f925d67abf6858a8200126352b)
we see that there's this TubConnectorClientFactory: class TubConnectorClientFactory(protocol.ClientFactory, object):
and later at line 1384 it is used with connectTCP like this: f = TubConnectorClientFactory(self, host, lp) c = reactor.connectTCP(host, port, f)
It looks like TubConnector is the primary intended user of TubConnectorClientFactory. In this case, you can simply move the logic from TubConnector.clientConnectionFailed to an errback on the Deferred returned by IStreamClientEndpoint.connect. Or you can leave it where it is an just make clientConnectionFailed be that errback.
For example:
f = TubConnectorClientFactory(self, host, lp) d = endpoint.connect(f) d.addErrback(self.clientConnectionFailed)
(removing the connector argument from clientConnectionFailed, of course).
You may want to apply a similar transformation to the *success* case here as well. That is, move the code that initiates protocol actions on the connection to a callback on this Deferred instead of automatically starting those actions in buildProtocol (this gives greater flexibility in how the protocol is used - if you want to change the details of initialization you can do so by using a different callback on the endpoint's Deferred instead of having to mess around with the factory or the protocol to disable this stuff).
Jean-Paul
_______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
participants (2)
-
David Stainton -
exarkun@twistedmatrix.com