Skip to content

Commit 7669675

Browse files
committed
control-connection: deprecate ControlConnection.wait_for_schema_agreement
Keep ControlConnection.wait_for_schema_agreement() as a compatibility wrapper, but move the existing implementation to _wait_for_schema_agreement() and deprecate the public method in favor of Session.wait_for_schema_agreement(). This lets the control-connection refresh path continue using the old logic internally without emitting warnings. The control-connection wait path was designed for internal metadata refresh use, not as a user-facing schema agreement API. It observes schema agreement from the control connection's perspective and can report disagreement for hosts the session is not actually using, or fail because the control connection itself is transiently unhealthy. When called directly by user code that can produce false positives or failures that do not reflect whether the session can safely proceed. Update the unit tests to call the internal helper everywhere a warning is not expected, add explicit deprecation coverage for the public wrapper, and set stacklevel=2 so the warning points at the caller instead of inside the driver.
1 parent 1c417c3 commit 7669675

2 files changed

Lines changed: 30 additions & 12 deletions

File tree

cassandra/cluster.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3905,9 +3905,9 @@ def _refresh_schema(self, connection, preloaded_results=None, schema_agreement_w
39053905
if self._cluster.is_shutdown:
39063906
return False
39073907

3908-
agreed = self.wait_for_schema_agreement(connection,
3909-
preloaded_results=preloaded_results,
3910-
wait_time=schema_agreement_wait)
3908+
agreed = self._wait_for_schema_agreement(connection,
3909+
preloaded_results=preloaded_results,
3910+
wait_time=schema_agreement_wait)
39113911

39123912
if not self._schema_meta_enabled and not force:
39133913
log.debug("[control connection] Skipping schema refresh because schema metadata is disabled")
@@ -4198,6 +4198,14 @@ def _handle_schema_change(self, event):
41984198
self._cluster.scheduler.schedule_unique(delay, self.refresh_schema, **event)
41994199

42004200
def wait_for_schema_agreement(self, connection=None, preloaded_results=None, wait_time=None):
4201+
warn("ControlConnection.wait_for_schema_agreement is deprecated and will be removed in 4.0. "
4202+
"Use Session.wait_for_schema_agreement instead.", DeprecationWarning, stacklevel=2)
4203+
return self._wait_for_schema_agreement(connection=connection,
4204+
preloaded_results=preloaded_results,
4205+
wait_time=wait_time)
4206+
4207+
def _wait_for_schema_agreement(self, connection=None, preloaded_results=None, wait_time=None):
4208+
42014209
total_timeout = wait_time if wait_time is not None else self._cluster.max_schema_agreement_wait
42024210
if total_timeout <= 0:
42034211
return True

tests/unit/test_control_connection.py

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
import unittest
1616

1717
from concurrent.futures import ThreadPoolExecutor
18-
from unittest.mock import Mock, ANY, call
18+
from unittest.mock import Mock, ANY, call, patch
1919

2020
from cassandra import OperationTimedOut, SchemaTargetType, SchemaChangeType
2121
from cassandra.protocol import ResultMessage, RESULT_KIND_ROWS
@@ -210,16 +210,26 @@ def test_wait_for_schema_agreement(self):
210210
"""
211211
Basic test with all schema versions agreeing
212212
"""
213-
assert self.control_connection.wait_for_schema_agreement()
213+
assert self.control_connection._wait_for_schema_agreement()
214214
# the control connection should not have slept at all
215215
assert self.time.clock == 0
216216

217+
@patch('cassandra.cluster.warn')
218+
def test_wait_for_schema_agreement_warns_about_deprecation(self, mocked_warn):
219+
assert self.control_connection.wait_for_schema_agreement()
220+
221+
mocked_warn.assert_called_once()
222+
warning_args, warning_kwargs = mocked_warn.call_args
223+
assert 'ControlConnection.wait_for_schema_agreement is deprecated' in str(warning_args[0])
224+
assert warning_args[1] is DeprecationWarning
225+
assert warning_kwargs['stacklevel'] == 2
226+
217227
def test_wait_for_schema_agreement_uses_preloaded_results_if_given(self):
218228
"""
219229
wait_for_schema_agreement uses preloaded results if given for shared table queries
220230
"""
221231
preloaded_results = self._matching_schema_preloaded_results
222-
assert self.control_connection.wait_for_schema_agreement(preloaded_results=preloaded_results)
232+
assert self.control_connection._wait_for_schema_agreement(preloaded_results=preloaded_results)
223233
# the control connection should not have slept at all
224234
assert self.time.clock == 0
225235
# the connection should not have made any queries if given preloaded results
@@ -230,7 +240,7 @@ def test_wait_for_schema_agreement_falls_back_to_querying_if_schemas_dont_match_
230240
wait_for_schema_agreement requery if schema does not match using preloaded results
231241
"""
232242
preloaded_results = self._nonmatching_schema_preloaded_results
233-
assert self.control_connection.wait_for_schema_agreement(preloaded_results=preloaded_results)
243+
assert self.control_connection._wait_for_schema_agreement(preloaded_results=preloaded_results)
234244
# the control connection should not have slept at all
235245
assert self.time.clock == 0
236246
assert self.connection.wait_for_responses.call_count == 1
@@ -241,7 +251,7 @@ def test_wait_for_schema_agreement_fails(self):
241251
"""
242252
# change the schema version on one node
243253
self.connection.peer_results[1][1][2] = 'b'
244-
assert not self.control_connection.wait_for_schema_agreement()
254+
assert not self.control_connection._wait_for_schema_agreement()
245255
# the control connection should have slept until it hit the limit
246256
assert self.time.clock >= self.cluster.max_schema_agreement_wait
247257

@@ -262,7 +272,7 @@ def test_wait_for_schema_agreement_skipping(self):
262272
self.connection.peer_results[1][1][3] = 'c'
263273
self.cluster.metadata.get_host(DefaultEndPoint('192.168.1.1')).is_up = False
264274

265-
assert self.control_connection.wait_for_schema_agreement()
275+
assert self.control_connection._wait_for_schema_agreement()
266276
assert self.time.clock == 0
267277

268278
def test_wait_for_schema_agreement_rpc_lookup(self):
@@ -279,12 +289,12 @@ def test_wait_for_schema_agreement_rpc_lookup(self):
279289

280290
# even though the new host has a different schema version, it's
281291
# marked as down, so the control connection shouldn't care
282-
assert self.control_connection.wait_for_schema_agreement()
292+
assert self.control_connection._wait_for_schema_agreement()
283293
assert self.time.clock == 0
284294

285295
# but once we mark it up, the control connection will care
286296
host.is_up = True
287-
assert not self.control_connection.wait_for_schema_agreement()
297+
assert not self.control_connection._wait_for_schema_agreement()
288298
assert self.time.clock >= self.cluster.max_schema_agreement_wait
289299

290300

@@ -299,7 +309,7 @@ def test_wait_for_schema_agreement_none_timeout(self):
299309
status_event_refresh_window=0)
300310
cc._connection = self.connection
301311
cc._time = self.time
302-
assert cc.wait_for_schema_agreement()
312+
assert cc._wait_for_schema_agreement()
303313

304314
def test_refresh_nodes_and_tokens(self):
305315
self.control_connection.refresh_node_list_and_token_map()

0 commit comments

Comments
 (0)