Merge pull request #385 from datastax/381
PYTHON-381 - Use connect_timeout for socket connect in addition to negotiation
This commit is contained in:
@@ -242,7 +242,7 @@ class Connection(object):
|
|||||||
def __init__(self, host='127.0.0.1', port=9042, authenticator=None,
|
def __init__(self, host='127.0.0.1', port=9042, authenticator=None,
|
||||||
ssl_options=None, sockopts=None, compression=True,
|
ssl_options=None, sockopts=None, compression=True,
|
||||||
cql_version=None, protocol_version=MAX_SUPPORTED_VERSION, is_control_connection=False,
|
cql_version=None, protocol_version=MAX_SUPPORTED_VERSION, is_control_connection=False,
|
||||||
user_type_map=None):
|
user_type_map=None, connect_timeout=None):
|
||||||
self.host = host
|
self.host = host
|
||||||
self.port = port
|
self.port = port
|
||||||
self.authenticator = authenticator
|
self.authenticator = authenticator
|
||||||
@@ -253,6 +253,7 @@ class Connection(object):
|
|||||||
self.protocol_version = protocol_version
|
self.protocol_version = protocol_version
|
||||||
self.is_control_connection = is_control_connection
|
self.is_control_connection = is_control_connection
|
||||||
self.user_type_map = user_type_map
|
self.user_type_map = user_type_map
|
||||||
|
self.connect_timeout = connect_timeout
|
||||||
self._push_watchers = defaultdict(set)
|
self._push_watchers = defaultdict(set)
|
||||||
self._requests = {}
|
self._requests = {}
|
||||||
self._iobuf = io.BytesIO()
|
self._iobuf = io.BytesIO()
|
||||||
@@ -298,8 +299,11 @@ class Connection(object):
|
|||||||
succeeded in connecting and are ready for service (or
|
succeeded in connecting and are ready for service (or
|
||||||
raises an exception otherwise).
|
raises an exception otherwise).
|
||||||
"""
|
"""
|
||||||
|
start = time.time()
|
||||||
|
kwargs['connect_timeout'] = timeout
|
||||||
conn = cls(host, *args, **kwargs)
|
conn = cls(host, *args, **kwargs)
|
||||||
conn.connected_event.wait(timeout)
|
elapsed = time.time() - start
|
||||||
|
conn.connected_event.wait(timeout - elapsed)
|
||||||
if conn.last_error:
|
if conn.last_error:
|
||||||
if conn.is_unsupported_proto_version:
|
if conn.is_unsupported_proto_version:
|
||||||
raise ProtocolVersionUnsupported(host, conn.protocol_version)
|
raise ProtocolVersionUnsupported(host, conn.protocol_version)
|
||||||
@@ -320,7 +324,7 @@ class Connection(object):
|
|||||||
if not self._ssl_impl:
|
if not self._ssl_impl:
|
||||||
raise Exception("This version of Python was not compiled with SSL support")
|
raise Exception("This version of Python was not compiled with SSL support")
|
||||||
self._socket = self._ssl_impl.wrap_socket(self._socket, **self.ssl_options)
|
self._socket = self._ssl_impl.wrap_socket(self._socket, **self.ssl_options)
|
||||||
self._socket.settimeout(1.0)
|
self._socket.settimeout(self.connect_timeout)
|
||||||
self._socket.connect(sockaddr)
|
self._socket.connect(sockaddr)
|
||||||
sockerr = None
|
sockerr = None
|
||||||
break
|
break
|
||||||
@@ -331,7 +335,7 @@ class Connection(object):
|
|||||||
sockerr = err
|
sockerr = err
|
||||||
|
|
||||||
if sockerr:
|
if sockerr:
|
||||||
raise socket.error(sockerr.errno, "Tried connecting to %s. Last error: %s" % ([a[4] for a in addresses], sockerr.strerror))
|
raise socket.error(sockerr.errno, "Tried connecting to %s. Last error: %s" % ([a[4] for a in addresses], sockerr.strerror or sockerr))
|
||||||
|
|
||||||
if self.sockopts:
|
if self.sockopts:
|
||||||
for args in self.sockopts:
|
for args in self.sockopts:
|
||||||
|
@@ -200,7 +200,8 @@ class TwistedConnection(Connection):
|
|||||||
"""
|
"""
|
||||||
self.connector = reactor.connectTCP(
|
self.connector = reactor.connectTCP(
|
||||||
host=self.host, port=self.port,
|
host=self.host, port=self.port,
|
||||||
factory=TwistedConnectionClientFactory(self))
|
factory=TwistedConnectionClientFactory(self),
|
||||||
|
timeout=self.connect_timeout)
|
||||||
|
|
||||||
def client_connection_made(self):
|
def client_connection_made(self):
|
||||||
"""
|
"""
|
||||||
|
@@ -19,7 +19,9 @@ except ImportError:
|
|||||||
|
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from six.moves import range
|
from six.moves import range
|
||||||
|
import sys
|
||||||
from threading import Thread, Event
|
from threading import Thread, Event
|
||||||
|
import time
|
||||||
|
|
||||||
from cassandra import ConsistencyLevel, OperationTimedOut
|
from cassandra import ConsistencyLevel, OperationTimedOut
|
||||||
from cassandra.cluster import NoHostAvailable
|
from cassandra.cluster import NoHostAvailable
|
||||||
@@ -46,7 +48,7 @@ class ConnectionTests(object):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.klass.initialize_reactor()
|
self.klass.initialize_reactor()
|
||||||
|
|
||||||
def get_connection(self):
|
def get_connection(self, timeout=5):
|
||||||
"""
|
"""
|
||||||
Helper method to solve automated testing issues within Jenkins.
|
Helper method to solve automated testing issues within Jenkins.
|
||||||
Officially patched under the 2.0 branch through
|
Officially patched under the 2.0 branch through
|
||||||
@@ -58,7 +60,7 @@ class ConnectionTests(object):
|
|||||||
e = None
|
e = None
|
||||||
for i in range(5):
|
for i in range(5):
|
||||||
try:
|
try:
|
||||||
conn = self.klass.factory(host='127.0.0.1', timeout=5, protocol_version=PROTOCOL_VERSION)
|
conn = self.klass.factory(host='127.0.0.1', timeout=timeout, protocol_version=PROTOCOL_VERSION)
|
||||||
break
|
break
|
||||||
except (OperationTimedOut, NoHostAvailable) as e:
|
except (OperationTimedOut, NoHostAvailable) as e:
|
||||||
continue
|
continue
|
||||||
@@ -224,6 +226,12 @@ class ConnectionTests(object):
|
|||||||
for t in threads:
|
for t in threads:
|
||||||
t.join()
|
t.join()
|
||||||
|
|
||||||
|
def test_connect_timeout(self):
|
||||||
|
start = time.time()
|
||||||
|
self.assertRaises(Exception, self.get_connection, timeout=sys.float_info.min)
|
||||||
|
end = time.time()
|
||||||
|
self.assertAlmostEqual(start, end, 1)
|
||||||
|
|
||||||
|
|
||||||
class AsyncoreConnectionTests(ConnectionTests, unittest.TestCase):
|
class AsyncoreConnectionTests(ConnectionTests, unittest.TestCase):
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user