@@ -242,10 +242,19 @@ class ExecutionProfile(object):
242242 Defaults to :class:`.NoSpeculativeExecutionPolicy` if not specified
243243 """
244244
245- def __init__ (self , load_balancing_policy = None , retry_policy = None ,
245+ # indicates if lbp was set explicitly or uses default values
246+ _load_balancing_policy_explicit = False
247+
248+ def __init__ (self , load_balancing_policy = _NOT_SET , retry_policy = None ,
246249 consistency_level = ConsistencyLevel .LOCAL_ONE , serial_consistency_level = None ,
247250 request_timeout = 10.0 , row_factory = named_tuple_factory , speculative_execution_policy = None ):
248- self .load_balancing_policy = load_balancing_policy or default_lbp_factory ()
251+
252+ if load_balancing_policy is _NOT_SET :
253+ self ._load_balancing_policy_explicit = False
254+ self .load_balancing_policy = default_lbp_factory ()
255+ else :
256+ self ._load_balancing_policy_explicit = True
257+ self .load_balancing_policy = load_balancing_policy
249258 self .retry_policy = retry_policy or RetryPolicy ()
250259 self .consistency_level = consistency_level
251260 self .serial_consistency_level = serial_consistency_level
@@ -259,6 +268,15 @@ class ProfileManager(object):
259268 def __init__ (self ):
260269 self .profiles = dict ()
261270
271+ def _profiles_without_explicit_lbps (self ):
272+ names = (profile_name for
273+ profile_name , profile in self .profiles .items ()
274+ if not profile ._load_balancing_policy_explicit )
275+ return tuple (
276+ 'EXEC_PROFILE_DEFAULT' if n is EXEC_PROFILE_DEFAULT else n
277+ for n in names
278+ )
279+
262280 def distance (self , host ):
263281 distances = set (p .load_balancing_policy .distance (host ) for p in self .profiles .values ())
264282 return HostDistance .LOCAL if HostDistance .LOCAL in distances else \
@@ -341,7 +359,14 @@ class Cluster(object):
341359 local_dc set (as is the default), the DC is chosen from an arbitrary
342360 host in contact_points. In this case, contact_points should contain
343361 only nodes from a single, local DC.
362+
363+ Note: In the next major version, if you specify contact points, you will
364+ also be required to also explicitly specify a load-balancing policy. This
365+ change will help prevent cases where users had hard-to-debug issues
366+ surrounding unintuitive default load-balancing policy behavior.
344367 """
368+ # tracks if contact_points was set explicitly or with default values
369+ _contact_points_explicit = None
345370
346371 port = 9042
347372 """
@@ -770,17 +795,12 @@ def __init__(self,
770795
771796 Any of the mutable Cluster attributes may be set as keyword arguments to the constructor.
772797 """
773- if contact_points is not _NOT_SET and load_balancing_policy is None :
774- log .warn ('Cluster.__init__ called with contact_points specified, '
775- 'but no load_balancing_policy. In the next major '
776- 'version, this will raise an error; please specify a '
777- 'load balancing policy. '
778- '(contact_points = {cp}, lbp = {lbp}'
779- '' .format (cp = contact_points , lbp = load_balancing_policy ))
780-
781798 if contact_points is not None :
782- if contact_points is _UNSET_ARG :
799+ if contact_points is _NOT_SET :
800+ self ._contact_points_explicit = False
783801 contact_points = ['127.0.0.1' ]
802+ else :
803+ self ._contact_points_explicit = True
784804
785805 if isinstance (contact_points , six .string_types ):
786806 raise TypeError ("contact_points should not be a string, it should be a sequence (e.g. list) of strings" )
@@ -853,11 +873,35 @@ def __init__(self,
853873 raise ValueError ("Clusters constructed with execution_profiles should not specify legacy parameters "
854874 "load_balancing_policy or default_retry_policy. Configure this in a profile instead." )
855875 self ._config_mode = _ConfigMode .LEGACY
876+
856877 else :
857878 if execution_profiles :
858879 self .profile_manager .profiles .update (execution_profiles )
859880 self ._config_mode = _ConfigMode .PROFILES
860881
882+ if self ._contact_points_explicit :
883+ if self ._config_mode is _ConfigMode .PROFILES :
884+ default_lbp_profiles = self .profile_manager ._profiles_without_explicit_lbps ()
885+ if default_lbp_profiles :
886+ log .warn (
887+ 'Cluster.__init__ called with contact_points '
888+ 'specified, but load-balancing policies are not '
889+ 'specified in some ExecutionProfiles. In the next '
890+ 'major version, this will raise an error; please '
891+ 'specify a load-balancing policy. '
892+ '(contact_points = {cp}, '
893+ 'EPs without explicit LBPs = {eps})'
894+ '' .format (cp = contact_points , eps = default_lbp_profiles ))
895+ else :
896+ if load_balancing_policy is None :
897+ log .warn (
898+ 'Cluster.__init__ called with contact_points '
899+ 'specified, but no load_balancing_policy. In the next '
900+ 'major version, this will raise an error; please '
901+ 'specify a load-balancing policy. '
902+ '(contact_points = {cp}, lbp = {lbp})'
903+ '' .format (cp = contact_points , lbp = load_balancing_policy ))
904+
861905 self .metrics_enabled = metrics_enabled
862906 self .ssl_options = ssl_options
863907 self .sockopts = sockopts
@@ -999,6 +1043,21 @@ def add_execution_profile(self, name, profile, pool_wait_timeout=5):
9991043 raise ValueError ("Cannot add execution profiles when legacy parameters are set explicitly." )
10001044 if name in self .profile_manager .profiles :
10011045 raise ValueError ("Profile %s already exists" )
1046+ contact_points_but_no_lbp = (
1047+ self ._contact_points_explicit and not
1048+ profile ._load_balancing_policy_explicit )
1049+ if contact_points_but_no_lbp :
1050+ log .warn (
1051+ 'Tried to add an ExecutionProfile with name {name}. '
1052+ '{self} was explicitly configured with contact_points, but '
1053+ '{ep} was not explicitly configured with a '
1054+ 'load_balancing_policy. In the next major version, trying to '
1055+ 'add an ExecutionProfile without an explicitly configured LBP '
1056+ 'to a cluster with explicitly configured contact_points will '
1057+ 'raise an exception; please specify a load-balancing policy '
1058+ 'in the ExecutionProfile.'
1059+ '' .format (name = repr (name ), self = self , ep = profile ))
1060+
10021061 self .profile_manager .profiles [name ] = profile
10031062 profile .load_balancing_policy .populate (self , self .metadata .all_hosts ())
10041063 # on_up after populate allows things like DCA LBP to choose default local dc
0 commit comments