Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Kneel And Disconnect: Getting The Fastest Connection Out Of A Hostname

Kneel And Disconnect: Getting The Fastest Connection Out Of A Hostname

Did you know that when you resolve a hostname, you can get multiple addresses back, and pick any one to connect to? Some of these addresses will connect near instantly, while others might take a long time or time out. This talk is about a Twisted endpoint API I built that takes a hostname, and returns the connection that takes the least time to complete, from the list of resolved host addresses.

Ashwini Oruganti

April 11, 2014
Tweet

More Decks by Ashwini Oruganti

Other Decks in Programming

Transcript

  1. Endpoint an interface with a single method that takes an

    argument returns*: a listening port / a connected protocol
  2. “There are probably people out there who are smart enough

    not to need [tests], we’re not one of those. ” - PyPy docs
  3. Step 2: Sort them from simplest to most complex. (the

    failure ones come before the success ones)
  4. def _nameResolution(self, host): try: d = self.deferToThread( self._getaddrinfo, host, 0)

    return d except socket.gaierror: defer.fail( error.DNSLookupError("...")) # WRONG
  5. def _nameResolution(self, host): return self._deferToThread( self._getaddrinfo, host, 0) def connect(self,

    protocolFactory): [...] def errbackForGai(obj): return fail(error.DNSLookupError("...")) d = self._nameResolution(self._host) d.addErrback(errbackForGai)
  6. If something is hard to test, it is usually a

    bad idea. Good code is generally easy to test.
  7. 0 seconds later is still "some amount of time" later,

    even if it's not a very big amount of time
  8. def connect(self, protocolFactory): [...] def _canceller(d): [...] def errbackForGai(failure) [...]

    def _endpoints(gaiResult): [...] def attemptConnection(endpoints): [...] def usedEndpointRemoval(connResult, connAttempt): [...] def afterConnectionAttempt(connResult): [...] def checkDone(): [...] def connectFailed(reason): [...] def iterateEndpoint(): [...]