Skip to content

Commit 251188d

Browse files
committed
Delay initialization of shared connection state
This makes it much simpler to avoid sharing connection state across multiple processes. Fixes PYTHON-60
1 parent b6d4589 commit 251188d

7 files changed

Lines changed: 28 additions & 3 deletions

File tree

cassandra/cluster.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,7 @@ def connect(self, keyspace=None):
530530
raise Exception("Cluster is already shut down")
531531

532532
if not self._is_setup:
533+
self.connection_class.initialize_reactor()
533534
atexit.register(partial(_shutdown_cluster, self))
534535
for address in self.contact_points:
535536
host = self.add_host(address, signal=False)

cassandra/connection.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,14 @@ def __init__(self, host='127.0.0.1', port=9042, authenticator=None,
179179

180180
self.lock = RLock()
181181

182+
@classmethod
183+
def initialize_reactor(self):
184+
"""
185+
Called once by Cluster.connect(). This should be used by implementations
186+
to set up any resources that will be shared across connections.
187+
"""
188+
pass
189+
182190
def close(self):
183191
raise NotImplementedError()
184192

cassandra/io/asyncorereactor.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,12 +135,17 @@ class AsyncoreConnection(Connection, asyncore.dispatcher):
135135
module in the Python standard library for its event loop.
136136
"""
137137

138-
_loop = AsyncoreLoop()
138+
_loop = None
139139

140140
_total_reqd_bytes = 0
141141
_writable = False
142142
_readable = False
143143

144+
@classmethod
145+
def initialize_reactor(cls):
146+
if not cls._loop:
147+
cls._loop = AsyncoreLoop()
148+
144149
@classmethod
145150
def factory(cls, *args, **kwargs):
146151
timeout = kwargs.pop('timeout', 5.0)

cassandra/io/libevreactor.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,14 +200,18 @@ class LibevConnection(Connection):
200200
"""
201201
An implementation of :class:`.Connection` that uses libev for its event loop.
202202
"""
203-
_libevloop = LibevLoop()
204-
203+
_libevloop = None
205204
_write_watcher_is_active = False
206205
_total_reqd_bytes = 0
207206
_read_watcher = None
208207
_write_watcher = None
209208
_socket = None
210209

210+
@classmethod
211+
def initialize_reactor(cls):
212+
if not cls._libevloop:
213+
cls._libevloop = LibevLoop()
214+
211215
@classmethod
212216
def factory(cls, *args, **kwargs):
213217
timeout = kwargs.pop('timeout', 5.0)

tests/integration/standard/test_connection.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ class ConnectionTest(object):
3939

4040
klass = None
4141

42+
def setUp(self):
43+
self.klass.initialize_reactor()
44+
4245
def get_connection(self):
4346
"""
4447
Helper method to solve automated testing issues within Jenkins.
@@ -216,6 +219,7 @@ class AsyncoreConnectionTest(ConnectionTest, unittest.TestCase):
216219
def setUp(self):
217220
if 'gevent.monkey' in sys.modules:
218221
raise unittest.SkipTest("Can't test libev with gevent monkey patching")
222+
ConnectionTest.setUp(self)
219223

220224

221225
class LibevConnectionTest(ConnectionTest, unittest.TestCase):
@@ -228,3 +232,4 @@ def setUp(self):
228232
if LibevConnection is None:
229233
raise unittest.SkipTest(
230234
'libev does not appear to be installed properly')
235+
ConnectionTest.setUp(self)

tests/unit/io/test_asyncorereactor.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class AsyncoreConnectionTest(unittest.TestCase):
4242

4343
@classmethod
4444
def setUpClass(cls):
45+
AsyncoreConnection.initialize_reactor()
4546
cls.socket_patcher = patch('socket.socket', spec=socket.socket)
4647
cls.mock_socket = cls.socket_patcher.start()
4748
cls.mock_socket().connect_ex.return_value = 0

tests/unit/io/test_libevreactor.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ class LibevConnectionTest(unittest.TestCase):
5050
def setUp(self):
5151
if LibevConnection is None:
5252
raise unittest.SkipTest('libev does not appear to be installed correctly')
53+
LibevConnection.initialize_reactor()
5354

5455
def make_connection(self):
5556
c = LibevConnection('1.2.3.4', cql_version='3.0.1')

0 commit comments

Comments
 (0)