1919from __future__ import absolute_import
2020
2121import atexit
22+ import datetime
2223from binascii import hexlify
2324from collections import defaultdict
2425from collections .abc import Mapping
8283from cassandra .marshal import int64_pack
8384from cassandra .tablets import Tablet , Tablets
8485from cassandra .timestamps import MonotonicTimestampGenerator
85- from cassandra .util import _resolve_contact_points_to_string_map , Version
86+ from cassandra .util import _resolve_contact_points_to_string_map , Version , maybe_add_timeout_to_query
8687
8788from cassandra .datastax .insights .reporter import MonitorReporter
8889from cassandra .datastax .insights .util import version_supports_insights
@@ -1033,6 +1034,12 @@ def default_retry_policy(self, policy):
10331034 or to disable the shardaware port (advanced shardaware)
10341035 """
10351036
1037+ metadata_request_timeout = datetime .timedelta (seconds = 2 )
1038+ """
1039+ Timeout for all queries used by driver it self.
1040+ Supported only by Scylla clusters.
1041+ """
1042+
10361043 @property
10371044 def schema_metadata_enabled (self ):
10381045 """
@@ -1148,7 +1155,9 @@ def __init__(self,
11481155 client_id = None ,
11491156 cloud = None ,
11501157 scylla_cloud = None ,
1151- shard_aware_options = None ):
1158+ shard_aware_options = None ,
1159+ metadata_request_timeout = None ,
1160+ ):
11521161 """
11531162 ``executor_threads`` defines the number of threads in a pool for handling asynchronous tasks such as
11541163 extablishing connection pools or refreshing metadata.
@@ -1240,6 +1249,8 @@ def __init__(self,
12401249 self .no_compact = no_compact
12411250
12421251 self .auth_provider = auth_provider
1252+ if metadata_request_timeout is not None :
1253+ self .metadata_request_timeout = metadata_request_timeout
12431254
12441255 if load_balancing_policy is not None :
12451256 if isinstance (load_balancing_policy , type ):
@@ -3549,6 +3560,7 @@ class PeersQueryType(object):
35493560 _is_shutdown = False
35503561 _timeout = None
35513562 _protocol_version = None
3563+ _metadata_request_timeout = None
35523564
35533565 _schema_event_refresh_window = None
35543566 _topology_event_refresh_window = None
@@ -3648,7 +3660,7 @@ def _reconnect_internal(self):
36483660 (conn , _ ) = self ._connect_host_in_lbp ()
36493661 if conn is not None :
36503662 return conn
3651-
3663+
36523664 # Try to re-resolve hostnames as a fallback when all hosts are unreachable
36533665 self ._cluster ._resolve_hostnames ()
36543666
@@ -3693,7 +3705,10 @@ def _try_connect(self, host):
36933705 # If sharding information is available, it's a ScyllaDB cluster, so do not use peers_v2 table.
36943706 if connection .features .sharding_info is not None :
36953707 self ._uses_peers_v2 = False
3696-
3708+
3709+ # Cassandra does not support "USING TIMEOUT"
3710+ self ._metadata_request_timeout = None if connection .features .sharding_info is None \
3711+ else datetime .timedelta (seconds = self ._cluster .control_connection_timeout )
36973712 self ._tablets_routing_v1 = connection .features .tablets_routing_v1
36983713
36993714 # use weak references in both directions
@@ -3710,8 +3725,10 @@ def _try_connect(self, host):
37103725
37113726 sel_peers = self ._get_peers_query (self .PeersQueryType .PEERS , connection )
37123727 sel_local = self ._SELECT_LOCAL if self ._token_meta_enabled else self ._SELECT_LOCAL_NO_TOKENS
3713- peers_query = QueryMessage (query = sel_peers , consistency_level = ConsistencyLevel .ONE )
3714- local_query = QueryMessage (query = sel_local , consistency_level = ConsistencyLevel .ONE )
3728+ peers_query = QueryMessage (query = maybe_add_timeout_to_query (sel_peers , self ._metadata_request_timeout ),
3729+ consistency_level = ConsistencyLevel .ONE )
3730+ local_query = QueryMessage (query = maybe_add_timeout_to_query (sel_local , self ._metadata_request_timeout ),
3731+ consistency_level = ConsistencyLevel .ONE )
37153732 (peers_success , peers_result ), (local_success , local_result ) = connection .wait_for_responses (
37163733 peers_query , local_query , timeout = self ._timeout , fail_on_error = False )
37173734
@@ -3722,7 +3739,8 @@ def _try_connect(self, host):
37223739 # error with the peers v2 query, fallback to peers v1
37233740 self ._uses_peers_v2 = False
37243741 sel_peers = self ._get_peers_query (self .PeersQueryType .PEERS , connection )
3725- peers_query = QueryMessage (query = sel_peers , consistency_level = ConsistencyLevel .ONE )
3742+ peers_query = QueryMessage (query = maybe_add_timeout_to_query (sel_peers , self ._metadata_request_timeout ),
3743+ consistency_level = ConsistencyLevel .ONE )
37263744 peers_result = connection .wait_for_response (
37273745 peers_query , timeout = self ._timeout )
37283746
@@ -3830,7 +3848,12 @@ def _refresh_schema(self, connection, preloaded_results=None, schema_agreement_w
38303848 log .debug ("Skipping schema refresh due to lack of schema agreement" )
38313849 return False
38323850
3833- self ._cluster .metadata .refresh (connection , self ._timeout , fetch_size = self ._schema_meta_page_size , ** kwargs )
3851+ self ._cluster .metadata .refresh (
3852+ connection ,
3853+ self ._timeout ,
3854+ fetch_size = self ._schema_meta_page_size ,
3855+ metadata_request_timeout = self ._metadata_request_timeout ,
3856+ ** kwargs )
38343857
38353858 return True
38363859
@@ -3861,8 +3884,10 @@ def _refresh_node_list_and_token_map(self, connection, preloaded_results=None,
38613884 else :
38623885 log .debug ("[control connection] Refreshing node list and token map" )
38633886 sel_local = self ._SELECT_LOCAL
3864- peers_query = QueryMessage (query = sel_peers , consistency_level = cl )
3865- local_query = QueryMessage (query = sel_local , consistency_level = cl )
3887+ peers_query = QueryMessage (query = maybe_add_timeout_to_query (sel_peers , self ._metadata_request_timeout ),
3888+ consistency_level = cl )
3889+ local_query = QueryMessage (query = maybe_add_timeout_to_query (sel_local , self ._metadata_request_timeout ),
3890+ consistency_level = cl )
38663891 peers_result , local_result = connection .wait_for_responses (
38673892 peers_query , local_query , timeout = self ._timeout )
38683893
@@ -3917,8 +3942,9 @@ def _refresh_node_list_and_token_map(self, connection, preloaded_results=None,
39173942 # local rpc_address has not been queried yet, try to fetch it
39183943 # separately, which might fail because C* < 2.1.6 doesn't have rpc_address
39193944 # in system.local. See CASSANDRA-9436.
3920- local_rpc_address_query = QueryMessage (query = self ._SELECT_LOCAL_NO_TOKENS_RPC_ADDRESS ,
3921- consistency_level = ConsistencyLevel .ONE )
3945+ local_rpc_address_query = QueryMessage (
3946+ query = maybe_add_timeout_to_query (self ._SELECT_LOCAL_NO_TOKENS_RPC_ADDRESS , self ._metadata_request_timeout ),
3947+ consistency_level = ConsistencyLevel .ONE )
39223948 success , local_rpc_address_result = connection .wait_for_response (
39233949 local_rpc_address_query , timeout = self ._timeout , fail_on_error = False )
39243950 if success :
@@ -4153,8 +4179,10 @@ def wait_for_schema_agreement(self, connection=None, preloaded_results=None, wai
41534179 select_peers_query = self ._get_peers_query (self .PeersQueryType .PEERS_SCHEMA , connection )
41544180
41554181 while elapsed < total_timeout :
4156- peers_query = QueryMessage (query = select_peers_query , consistency_level = cl )
4157- local_query = QueryMessage (query = self ._SELECT_SCHEMA_LOCAL , consistency_level = cl )
4182+ peers_query = QueryMessage (query = maybe_add_timeout_to_query (select_peers_query , self ._metadata_request_timeout ),
4183+ consistency_level = cl )
4184+ local_query = QueryMessage (query = maybe_add_timeout_to_query (self ._SELECT_SCHEMA_LOCAL , self ._metadata_request_timeout ),
4185+ consistency_level = cl )
41584186 try :
41594187 timeout = min (self ._timeout , total_timeout - elapsed )
41604188 peers_result , local_result = connection .wait_for_responses (
0 commit comments