Skip to content

Commit 4e13a39

Browse files
committed
PYTHON-812 - Make local threshold global and immutable.
1 parent a788b1f commit 4e13a39

15 files changed

+85
-198
lines changed

doc/api/pymongo/mongo_client.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@
2828
.. autoattribute:: max_message_size
2929
.. autoattribute:: min_wire_version
3030
.. autoattribute:: max_wire_version
31+
.. autoattribute:: local_threshold_ms
3132
.. autoattribute:: codec_options
3233
.. autoattribute:: read_preference
33-
.. autoattribute:: secondary_acceptable_latency_ms
3434
.. autoattribute:: write_concern
3535
.. autoattribute:: is_locked
3636
.. automethod:: database_names

doc/api/pymongo/mongo_replica_set_client.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@
2727
.. autoattribute:: max_message_size
2828
.. autoattribute:: min_wire_version
2929
.. autoattribute:: max_wire_version
30+
.. autoattribute:: local_threshold_ms
3031
.. autoattribute:: codec_options
3132
.. autoattribute:: read_preference
32-
.. autoattribute:: secondary_acceptable_latency_ms
3333
.. autoattribute:: write_concern
3434
.. automethod:: database_names
3535
.. automethod:: drop_database

pymongo/client_options.py

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,8 @@ def _parse_read_preference(options):
5050
return options['read_preference']
5151

5252
mode = options.get('readpreference', 0)
53-
threshold = options.get('secondaryacceptablelatencyms',
54-
options.get('localthresholdms', 15))
5553
tags = options.get('readpreferencetags')
56-
return make_read_preference(mode, threshold, tags)
54+
return make_read_preference(mode, tags)
5755

5856

5957
def _parse_write_concern(options):
@@ -121,19 +119,30 @@ class ClientOptions(object):
121119
def __init__(self, username, password, database, options):
122120
options = dict([validate(opt, val) for opt, val in iteritems(options)])
123121

122+
self.__codec_options = _parse_codec_options(options)
124123
self.__credentials = _parse_credentials(
125124
username, password, database, options)
126-
self.__codec_options = _parse_codec_options(options)
125+
self.__local_threshold_ms = options.get('localthresholdms', 15)
127126
self.__pool_options = _parse_pool_options(options)
128127
self.__read_preference = _parse_read_preference(options)
129128
self.__replica_set_name = options.get('replicaset')
130129
self.__write_concern = _parse_write_concern(options)
131130

131+
@property
132+
def codec_options(self):
133+
"""A :class:`~pymongo.codec_options.CodecOptions` instance."""
134+
return self.__codec_options
135+
132136
@property
133137
def credentials(self):
134138
"""A :class:`~pymongo.auth.MongoCredentials` instance or None."""
135139
return self.__credentials
136140

141+
@property
142+
def local_threshold_ms(self):
143+
"""The local threshold for this instance."""
144+
return self.__local_threshold_ms
145+
137146
@property
138147
def pool_options(self):
139148
"""A :class:`~pymongo.pool.PoolOptions` instance."""
@@ -149,11 +158,6 @@ def replica_set_name(self):
149158
"""Replica set name or None."""
150159
return self.__replica_set_name
151160

152-
@property
153-
def codec_options(self):
154-
"""A :class:`~pymongo.codec_options.CodecOptions` instance."""
155-
return self.__codec_options
156-
157161
@property
158162
def write_concern(self):
159163
"""A :class:`~pymongo.write_concern.WriteConcern` instance."""

pymongo/common.py

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,6 @@ def validate_document_class(option, value):
331331
'readpreference': validate_read_preference_mode,
332332
'readpreferencetags': validate_read_preference_tags,
333333
'localthresholdms': validate_positive_float,
334-
'secondaryacceptablelatencyms': validate_positive_float,
335334
'authmechanism': validate_auth_mechanism,
336335
'authsource': validate_string,
337336
'authmechanismproperties': validate_auth_mechanism_properties,
@@ -432,37 +431,14 @@ def __set_read_pref(self, value):
432431

433432
read_preference = property(__get_read_pref, __set_read_pref)
434433

435-
def __get_latency(self):
436-
"""Deprecated. Use ``client.read_preference.local_threshold_ms``.
437-
438-
See :class:`~pymongo.read_preferences.ReadPreference`.
439-
440-
.. note:: ``secondary_acceptable_latency_ms`` is ignored when talking
441-
to a replica set *through* a mongos. The equivalent is the
442-
localThreshold_ command line option.
443-
444-
.. _localThreshold: http://docs.mongodb.org/manual/reference/mongos/#cmdoption-mongos--localThreshold
445-
"""
446-
return self.__read_pref.local_threshold_ms
447-
448-
def __set_latency(self, threshold):
449-
warnings.warn("The secondary_acceptable_latency_ms attribute is "
450-
"deprecated", DeprecationWarning, stacklevel=2)
451-
mode = self.__read_pref.mode
452-
tag_sets = self.__read_pref.tag_sets
453-
self.__read_pref = make_read_preference(mode, threshold, tag_sets)
454-
455-
secondary_acceptable_latency_ms = property(__get_latency, __set_latency)
456-
457434
def __get_tags(self):
458435
return self.__read_pref.tag_sets
459436

460437
def __set_tags(self, tag_sets):
461438
warnings.warn("The tag_sets attribute is deprecated",
462439
DeprecationWarning, stacklevel=2)
463440
mode = self.__read_pref.mode
464-
threshold = self.__read_pref.local_threshold_ms
465-
self.__read_pref = make_read_preference(mode, threshold, tag_sets)
441+
self.__read_pref = make_read_preference(mode, tag_sets)
466442

467443
tag_sets = property(__get_tags, __set_tags)
468444

pymongo/database.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -342,16 +342,14 @@ def _command(self, command, value=1,
342342
command.update(kwargs)
343343

344344
orig = pref = read_preference or self.read_preference
345-
threshold = kwargs.pop('secondary_acceptable_latency_ms', None)
346345
tags = kwargs.pop('tags_sets', None)
347-
if threshold or tags:
346+
if tags:
348347
warnings.warn("The secondary_acceptable_latency_ms "
349348
"and tag_sets options are deprecated",
350349
DeprecationWarning, stacklevel=3)
351350
mode = orig.mode
352351
tags = tags or orig.tag_sets
353-
threshold = threshold or orig.local_threshold_ms
354-
orig = make_read_preference(mode, threshold, tags)
352+
orig = make_read_preference(mode, tags)
355353

356354
if command_name not in SECONDARY_OK_COMMANDS:
357355
pref = ReadPreference.PRIMARY
@@ -436,8 +434,8 @@ def command(self, command, value=1,
436434
be added to the command document before it is sent
437435
438436
.. versionchanged:: 3.0
439-
Deprecated the `tag_sets` and `secondary_acceptable_latency_ms`
440-
options.
437+
Deprecated the `tag_sets` option.
438+
Removed the `secondary_acceptable_latency_ms` option.
441439
Removed `compile_re` option: PyMongo now always represents BSON
442440
regular expressions as :class:`~bson.regex.Regex` objects. Use
443441
:meth:`~bson.regex.Regex.try_compile` to attempt to convert from a

pymongo/mongo_client.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,8 @@ def __init__(
315315
pool_class=pool_class,
316316
pool_options=options.pool_options,
317317
monitor_class=monitor_class,
318-
condition_class=condition_class)
318+
condition_class=condition_class,
319+
local_threshold_ms=options.local_threshold_ms)
319320

320321
self._topology = Topology(self._topology_settings)
321322
if connect:
@@ -610,6 +611,11 @@ def max_write_batch_size(self):
610611
return self._server_property(
611612
'max_write_batch_size', common.MAX_WRITE_BATCH_SIZE)
612613

614+
@property
615+
def local_threshold_ms(self):
616+
"""The local threshold for this instance."""
617+
return self.__options.local_threshold_ms
618+
613619
def _writable_max_wire_version(self):
614620
"""Connect to a writable server and get its max wire protocol version.
615621

pymongo/read_preferences.py

Lines changed: 32 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
from collections import Mapping, namedtuple
1818

1919
from pymongo.errors import ConfigurationError
20-
from pymongo.server_selectors import (near_member_with_tags_server_selector,
21-
near_secondary_with_tags_server_selector,
20+
from pymongo.server_selectors import (member_with_tags_server_selector,
21+
secondary_with_tags_server_selector,
2222
writable_server_selector)
2323

2424

@@ -64,20 +64,15 @@ class ServerMode(object):
6464
"""Base class for all read preferences.
6565
"""
6666

67-
__slots__ = ("__mongos_mode", "__mode", "__threshold", "__tag_sets")
67+
__slots__ = ("__mongos_mode", "__mode", "__tag_sets")
6868

69-
def __init__(self, mode, local_threshold_ms=15, tag_sets=None):
69+
def __init__(self, mode, tag_sets=None):
7070
if mode == _PRIMARY and tag_sets is not None:
7171
raise ConfigurationError("Read preference primary "
7272
"cannot be combined with tags")
7373
self.__mongos_mode = _MONGOS_MODES[mode]
7474
self.__mode = mode
7575
self.__tag_sets = _validate_tag_sets(tag_sets)
76-
try:
77-
self.__threshold = float(local_threshold_ms)
78-
except (ValueError, TypeError):
79-
raise ConfigurationError("local_threshold_ms must "
80-
"be a positive integer or float")
8176

8277
@property
8378
def name(self):
@@ -99,22 +94,6 @@ def mode(self):
9994
"""
10095
return self.__mode
10196

102-
@property
103-
def local_threshold_ms(self):
104-
"""An integer. Any replica-set member whose ping time is within
105-
``local_threshold_ms`` of the nearest member may accept reads.
106-
When used with mongos high availability, any mongos whose ping
107-
time is within ``local_threshold_ms`` of the nearest mongos
108-
may be chosen as the new mongos during a failover. Default 15
109-
milliseconds.
110-
111-
.. note:: ``local_threshold_ms`` is ignored when talking
112-
to a replica set through a mongos. The equivalent is the
113-
`localThreshold <http://docs.mongodb.org/manual/reference/mongos/#cmdoption--localThreshold>`_
114-
command line option.
115-
"""
116-
return self.__threshold
117-
11897
@property
11998
def tag_sets(self):
12099
"""Set ``tag_sets`` to a list of dictionaries like [{'dc': 'ny'}] to
@@ -131,13 +110,14 @@ def tag_sets(self):
131110
return self.__tag_sets or [{}]
132111

133112
def __repr__(self):
134-
return "%s(local_threshold_ms=%d, tag_sets=%r)" % (
135-
self.name, self.__threshold, self.__tag_sets)
113+
return "%s(tag_sets=%r)" % (
114+
self.name, self.__tag_sets)
136115

137116
def __eq__(self, other):
138-
return (self.mode == other.mode and
139-
self.local_threshold_ms == other.local_threshold_ms and
140-
self.tag_sets == other.tag_sets)
117+
if isinstance(other, ServerMode):
118+
return (self.mode == other.mode and
119+
self.tag_sets == other.tag_sets)
120+
raise NotImplementedError
141121

142122
def __ne__(self, other):
143123
return not self == other
@@ -151,14 +131,10 @@ class Primary(ServerMode):
151131
* When connected to a mongos queries are sent to the primary of a shard.
152132
* When connected to a replica set queries are sent to the primary of
153133
the replica set.
154-
155-
:Parameters:
156-
- `local_threshold_ms`: Used for mongos high availability. The
157-
:attr:`~local_threshold_ms` when selecting a failover mongos.
158134
"""
159135

160-
def __init__(self, local_threshold_ms=15):
161-
super(Primary, self).__init__(_PRIMARY, local_threshold_ms)
136+
def __init__(self):
137+
super(Primary, self).__init__(_PRIMARY)
162138

163139
def __call__(self, server_descriptions):
164140
"""Return matching ServerDescriptions from a list."""
@@ -167,6 +143,11 @@ def __call__(self, server_descriptions):
167143
def __repr__(self):
168144
return "Primary"
169145

146+
def __eq__(self, other):
147+
if isinstance(other, ServerMode):
148+
return other.mode == _PRIMARY
149+
raise NotImplementedError
150+
170151

171152
class PrimaryPreferred(ServerMode):
172153
"""PrimaryPreferred read preference.
@@ -179,25 +160,21 @@ class PrimaryPreferred(ServerMode):
179160
available, otherwise a secondary.
180161
181162
:Parameters:
182-
- `local_threshold_ms`: The :attr:`~local_threshold_ms` when
183-
selecting a secondary.
184163
- `tag_sets`: The :attr:`~tag_sets` to use if the primary is not
185164
available.
186165
"""
187166

188-
def __init__(self, local_threshold_ms=15, tag_sets=None):
189-
super(PrimaryPreferred, self).__init__(
190-
_PRIMARY_PREFERRED, local_threshold_ms, tag_sets)
167+
def __init__(self, tag_sets=None):
168+
super(PrimaryPreferred, self).__init__(_PRIMARY_PREFERRED, tag_sets)
191169

192170
def __call__(self, server_descriptions):
193171
"""Return matching ServerDescriptions from a list."""
194172
writable_servers = writable_server_selector(server_descriptions)
195173
if writable_servers:
196174
return writable_servers
197175
else:
198-
return near_secondary_with_tags_server_selector(
176+
return secondary_with_tags_server_selector(
199177
self.tag_sets,
200-
self.local_threshold_ms,
201178
server_descriptions)
202179

203180

@@ -212,20 +189,16 @@ class Secondary(ServerMode):
212189
secondaries. An error is raised if no secondaries are available.
213190
214191
:Parameters:
215-
- `local_threshold_ms`: The :attr:`~local_threshold_ms` when
216-
selecting a secondary.
217192
- `tag_sets`: The :attr:`~tag_sets` to use with this read_preference
218193
"""
219194

220-
def __init__(self, local_threshold_ms=15, tag_sets=None):
221-
super(Secondary, self).__init__(
222-
_SECONDARY, local_threshold_ms, tag_sets)
195+
def __init__(self, tag_sets=None):
196+
super(Secondary, self).__init__(_SECONDARY, tag_sets)
223197

224198
def __call__(self, server_descriptions):
225199
"""Return matching ServerDescriptions from a list."""
226-
return near_secondary_with_tags_server_selector(
200+
return secondary_with_tags_server_selector(
227201
self.tag_sets,
228-
self.local_threshold_ms,
229202
server_descriptions)
230203

231204

@@ -240,20 +213,16 @@ class SecondaryPreferred(ServerMode):
240213
secondaries, or the primary if no secondary is available.
241214
242215
:Parameters:
243-
- `local_threshold_ms`: The :attr:`~local_threshold_ms` when
244-
selecting a secondary.
245216
- `tag_sets`: The :attr:`~tag_sets` to use with this read_preference
246217
"""
247218

248-
def __init__(self, local_threshold_ms=15, tag_sets=None):
249-
super(SecondaryPreferred, self).__init__(
250-
_SECONDARY_PREFERRED, local_threshold_ms, tag_sets)
219+
def __init__(self, tag_sets=None):
220+
super(SecondaryPreferred, self).__init__(_SECONDARY_PREFERRED, tag_sets)
251221

252222
def __call__(self, server_descriptions):
253223
"""Return matching ServerDescriptions from a list."""
254-
secondaries = near_secondary_with_tags_server_selector(
224+
secondaries = secondary_with_tags_server_selector(
255225
self.tag_sets,
256-
self.local_threshold_ms,
257226
server_descriptions)
258227

259228
if secondaries:
@@ -273,33 +242,29 @@ class Nearest(ServerMode):
273242
members.
274243
275244
:Parameters:
276-
- `local_threshold_ms`: The :attr:`~local_threshold_ms` when
277-
selecting a secondary.
278245
- `tag_sets`: The :attr:`~tag_sets` to use with this read_preference
279246
"""
280247

281-
def __init__(self, local_threshold_ms=15, tag_sets=None):
282-
super(Nearest, self).__init__(
283-
_NEAREST, local_threshold_ms, tag_sets)
248+
def __init__(self, tag_sets=None):
249+
super(Nearest, self).__init__(_NEAREST, tag_sets)
284250

285251
def __call__(self, server_descriptions):
286252
"""Return matching ServerDescriptions from a list."""
287-
return near_member_with_tags_server_selector(
253+
return member_with_tags_server_selector(
288254
self.tag_sets or [{}],
289-
self.local_threshold_ms,
290255
server_descriptions)
291256

292257

293258
_ALL_READ_PREFERENCES = (Primary, PrimaryPreferred,
294259
Secondary, SecondaryPreferred, Nearest)
295260

296-
def make_read_preference(mode, local_threshold_ms, tag_sets):
261+
def make_read_preference(mode, tag_sets):
297262
if mode == _PRIMARY:
298263
if tag_sets not in (None, [{}]):
299264
raise ConfigurationError("Read preference primary "
300265
"cannot be combined with tags")
301-
return Primary(local_threshold_ms)
302-
return _ALL_READ_PREFERENCES[mode](local_threshold_ms, tag_sets)
266+
return Primary()
267+
return _ALL_READ_PREFERENCES[mode](tag_sets)
303268

304269

305270
_MODES = (

0 commit comments

Comments
 (0)