PYTHON-890 - Support localThresholdMS URI option.
This commit is contained in:
parent
313e21ab4f
commit
6e4608b9cd
@ -33,6 +33,7 @@
|
||||
.. autoattribute:: read_preference
|
||||
.. autoattribute:: tag_sets
|
||||
.. autoattribute:: secondary_acceptable_latency_ms
|
||||
.. autoattribute:: local_threshold_ms
|
||||
.. autoattribute:: write_concern
|
||||
.. autoattribute:: uuid_subtype
|
||||
.. autoattribute:: is_locked
|
||||
|
||||
@ -34,6 +34,7 @@
|
||||
.. autoattribute:: read_preference
|
||||
.. autoattribute:: tag_sets
|
||||
.. autoattribute:: secondary_acceptable_latency_ms
|
||||
.. autoattribute:: local_threshold_ms
|
||||
.. autoattribute:: write_concern
|
||||
.. autoattribute:: uuid_subtype
|
||||
.. automethod:: database_names
|
||||
|
||||
@ -328,6 +328,7 @@ VALIDATORS = {
|
||||
'tag_sets': validate_tag_sets,
|
||||
'secondaryacceptablelatencyms': validate_positive_float_or_zero,
|
||||
'secondary_acceptable_latency_ms': validate_positive_float_or_zero,
|
||||
'localthresholdms': validate_positive_float_or_zero,
|
||||
'auto_start_request': validate_boolean,
|
||||
'use_greenlets': validate_boolean,
|
||||
'authmechanism': validate_auth_mechanism,
|
||||
|
||||
@ -206,6 +206,14 @@ class MongoClient(common.BaseObject):
|
||||
set, ``{}``, means "read from any member that matches the mode,
|
||||
ignoring tags. Defaults to ``[{}]``, meaning "ignore members'
|
||||
tags."
|
||||
- `secondaryAcceptableLatencyMS`: (integer) Any replica-set member
|
||||
whose ping time is within secondary_acceptable_latency_ms of the
|
||||
nearest member may accept reads. Default 15 milliseconds.
|
||||
**Ignored by mongos** and must be configured on the command line.
|
||||
See the localThreshold_ option for more information.
|
||||
- `localThresholdMS`: (integer) Alias for
|
||||
secondaryAcceptableLatencyMS. Takes precedence over
|
||||
secondaryAcceptableLatencyMS.
|
||||
|
||||
| **SSL configuration:**
|
||||
|
||||
@ -294,6 +302,11 @@ class MongoClient(common.BaseObject):
|
||||
options[option] = value
|
||||
options.update(opts)
|
||||
|
||||
# localthresholdms takes precedence over secondaryacceptablelatencyms.
|
||||
if "localthresholdms" in options:
|
||||
options["secondaryacceptablelatencyms"] = (
|
||||
options["localthresholdms"])
|
||||
|
||||
common.validate_boolean('tz_aware', tz_aware)
|
||||
uuid_representation = options.pop('uuidrepresentation', PYTHON_LEGACY)
|
||||
options['codec_options'] = CodecOptions(
|
||||
@ -688,6 +701,14 @@ class MongoClient(common.BaseObject):
|
||||
return self.__member_property(
|
||||
'max_write_batch_size', common.MAX_WRITE_BATCH_SIZE)
|
||||
|
||||
@property
|
||||
def local_threshold_ms(self):
|
||||
"""Alias for secondary_acceptable_latency_ms.
|
||||
|
||||
.. versionadded:: 2.9
|
||||
"""
|
||||
return self.secondary_acceptable_latency_ms
|
||||
|
||||
def __simple_command(self, sock_info, dbname, spec):
|
||||
"""Send a command to the server. May raise AutoReconnect.
|
||||
"""
|
||||
|
||||
@ -550,11 +550,14 @@ class MongoReplicaSetClient(common.BaseObject):
|
||||
ignoring tags." :class:`MongoReplicaSetClient` tries each set of
|
||||
tags in turn until it finds a set of tags with at least one matching
|
||||
member. Defaults to ``[{}]``, meaning "ignore members' tags."
|
||||
- `secondary_acceptable_latency_ms`: (integer) Any replica-set member
|
||||
whose ping time is within secondary_acceptable_latency_ms of the
|
||||
- `secondaryAcceptableLatencyMS`: (integer) Any replica-set member
|
||||
whose ping time is within secondaryAcceptableLatencyMS of the
|
||||
nearest member may accept reads. Default 15 milliseconds.
|
||||
**Ignored by mongos** and must be configured on the command line.
|
||||
See the localThreshold_ option for more information.
|
||||
- `localThresholdMS`: (integer) Alias for
|
||||
secondaryAcceptableLatencyMS. Takes precedence over
|
||||
secondaryAcceptableLatencyMS.
|
||||
|
||||
| **SSL configuration:**
|
||||
|
||||
@ -689,6 +692,11 @@ class MongoReplicaSetClient(common.BaseObject):
|
||||
"2.6 you must install the ssl package "
|
||||
"from PyPI.")
|
||||
|
||||
# localThresholdMS takes precedence over secondaryAcceptableLatencyMS
|
||||
if "localthresholdms" in self.__opts:
|
||||
self.__opts["secondaryacceptablelatencyms"] = (
|
||||
self.__opts["localthresholdms"])
|
||||
|
||||
super(MongoReplicaSetClient, self).__init__(**self.__opts)
|
||||
if self.slave_okay:
|
||||
warnings.warn("slave_okay is deprecated. Please "
|
||||
@ -1017,6 +1025,14 @@ class MongoReplicaSetClient(common.BaseObject):
|
||||
"""**DEPRECATED** Is auto_start_request enabled?"""
|
||||
return self.__auto_start_request
|
||||
|
||||
@property
|
||||
def local_threshold_ms(self):
|
||||
"""Alias for secondary_acceptable_latency_ms.
|
||||
|
||||
.. versionadded:: 2.9
|
||||
"""
|
||||
return self.secondary_acceptable_latency_ms
|
||||
|
||||
def __simple_command(self, sock_info, dbname, spec):
|
||||
"""Send a command to the server.
|
||||
Returns (response, ping_time in seconds).
|
||||
|
||||
@ -331,6 +331,63 @@ class TestClient(unittest.TestCase, TestRequestMixin):
|
||||
finally:
|
||||
ctx.exit()
|
||||
|
||||
def test_backport_localthresholdms_uri(self):
|
||||
uri = "mongodb://%s:%s" % (host, port)
|
||||
lt_uri = "mongodb://%s:%d/?localThresholdMS=10" % (host, port)
|
||||
sl_uri = ("mongodb://%s:%d/?secondaryAcceptableLatencyMS=10" %
|
||||
(host, port))
|
||||
lt_sl_uri = ("mongodb://%s:%d/?localThresholdMS=10;"
|
||||
"secondaryAcceptableLatencyMS=8" % (host, port))
|
||||
|
||||
# Just localThresholdMS
|
||||
client = MongoClient(uri)
|
||||
self.assertEqual(client.secondary_acceptable_latency_ms, 15)
|
||||
self.assertEqual(client.local_threshold_ms, 15)
|
||||
client = MongoClient(uri, localThresholdMS=10)
|
||||
self.assertEqual(client.secondary_acceptable_latency_ms, 10)
|
||||
self.assertEqual(client.local_threshold_ms, 10)
|
||||
client = MongoClient(uri, localThresholdMS=10,
|
||||
secondaryAcceptableLatencyMS=8)
|
||||
self.assertEqual(client.secondary_acceptable_latency_ms, 10)
|
||||
self.assertEqual(client.local_threshold_ms, 10)
|
||||
|
||||
# URI options take precedence over kwargs but localThresholdMS takes
|
||||
# precedence over secondaryAcceptableLatencyMS always. Test to make
|
||||
# sure the precedence is correct between URI vs. kwargs.
|
||||
client = MongoClient(lt_uri)
|
||||
self.assertEqual(client.secondary_acceptable_latency_ms, 10)
|
||||
self.assertEqual(client.local_threshold_ms, 10)
|
||||
client = MongoClient(lt_uri, localThresholdMS=8)
|
||||
self.assertEqual(client.secondary_acceptable_latency_ms, 10)
|
||||
self.assertEqual(client.local_threshold_ms, 10)
|
||||
client = MongoClient(lt_uri, secondaryAcceptableLatencyMS=8)
|
||||
self.assertEqual(client.secondary_acceptable_latency_ms, 10)
|
||||
self.assertEqual(client.local_threshold_ms, 10)
|
||||
client = MongoClient(lt_uri, localThresholdMS=8,
|
||||
secondaryAcceptableLatencyMS=6)
|
||||
self.assertEqual(client.secondary_acceptable_latency_ms, 10)
|
||||
self.assertEqual(client.local_threshold_ms, 10)
|
||||
|
||||
client = MongoClient(sl_uri, secondaryAcceptableLatencyMS=8)
|
||||
self.assertEqual(client.secondary_acceptable_latency_ms, 10)
|
||||
self.assertEqual(client.local_threshold_ms, 10)
|
||||
client = MongoClient(sl_uri, localThresholdMS=10)
|
||||
self.assertEqual(client.secondary_acceptable_latency_ms, 10)
|
||||
self.assertEqual(client.local_threshold_ms, 10)
|
||||
client = MongoClient(sl_uri, localThresholdMS=10,
|
||||
secondaryAcceptableLatencyMS=6)
|
||||
self.assertEqual(client.secondary_acceptable_latency_ms, 10)
|
||||
self.assertEqual(client.local_threshold_ms, 10)
|
||||
|
||||
client = MongoClient(lt_sl_uri)
|
||||
self.assertEqual(client.secondary_acceptable_latency_ms, 10)
|
||||
self.assertEqual(client.local_threshold_ms, 10)
|
||||
client = MongoClient(lt_sl_uri, localThresholdMS=8,
|
||||
secondaryAcceptableLatencyMS=4)
|
||||
self.assertEqual(client.secondary_acceptable_latency_ms, 10)
|
||||
self.assertEqual(client.local_threshold_ms, 10)
|
||||
|
||||
|
||||
def test_get_default_database(self):
|
||||
c = MongoClient("mongodb://%s:%d/foo" % (host, port), _connect=False)
|
||||
self.assertEqual(Database(c, 'foo'), c.get_default_database())
|
||||
|
||||
@ -154,6 +154,44 @@ class TestMongosHA(unittest.TestCase):
|
||||
# No error
|
||||
client.db.collection.find_one()
|
||||
|
||||
def test_backport_localthresholdms_kwarg(self):
|
||||
# Test that localThresholdMS takes precedence over
|
||||
# secondaryAcceptableLatencyMS.
|
||||
client = MockClient(
|
||||
standalones=[],
|
||||
members=[],
|
||||
mongoses=['a:1', 'b:2', 'c:3'],
|
||||
host='a:1,b:2,c:3',
|
||||
localThresholdMS=7,
|
||||
secondaryAcceptableLatencyMS=0)
|
||||
|
||||
self.assertEqual(7, client.secondary_acceptable_latency_ms)
|
||||
self.assertEqual(7, client.local_threshold_ms)
|
||||
# No error
|
||||
client.db.collection.find_one()
|
||||
|
||||
client = MockClient(
|
||||
standalones=[],
|
||||
members=[],
|
||||
mongoses=['a:1', 'b:2', 'c:3'],
|
||||
host='a:1,b:2,c:3',
|
||||
localThresholdMS=0,
|
||||
secondaryAcceptableLatencyMS=15)
|
||||
|
||||
self.assertEqual(0, client.secondary_acceptable_latency_ms)
|
||||
self.assertEqual(0, client.local_threshold_ms)
|
||||
|
||||
# Test that using localThresholdMS works in the same way as using
|
||||
# secondaryAcceptableLatencyMS.
|
||||
client.db.collection.find_one()
|
||||
# Our chosen mongos goes down.
|
||||
client.kill_host('%s:%s' % (client.host, client.port))
|
||||
try:
|
||||
client.db.collection.find_one()
|
||||
except:
|
||||
pass
|
||||
# No error
|
||||
client.db.collection.find_one()
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
@ -166,6 +166,27 @@ class TestReadPreferences(TestReadPreferencesBase):
|
||||
self._get_client,
|
||||
secondaryacceptablelatencyms=-1)
|
||||
|
||||
def test_backport_latency_validation(self):
|
||||
self.assertEqual(17, self._get_client(
|
||||
localThresholdMS=17
|
||||
).secondary_acceptable_latency_ms)
|
||||
|
||||
self.assertEqual(42, self._get_client(
|
||||
secondaryAcceptableLatencyMS=42
|
||||
).local_threshold_ms)
|
||||
|
||||
self.assertEqual(666, self._get_client(
|
||||
localThresholdMS=666
|
||||
).local_threshold_ms)
|
||||
|
||||
self.assertEqual(0, self._get_client(
|
||||
localthresholdms=0
|
||||
).local_threshold_ms)
|
||||
|
||||
self.assertRaises(ConfigurationError,
|
||||
self._get_client,
|
||||
localthresholdms=-1)
|
||||
|
||||
def test_primary(self):
|
||||
self.assertReadsFrom('primary',
|
||||
read_preference=ReadPreference.PRIMARY)
|
||||
|
||||
@ -743,6 +743,64 @@ class TestReplicaSetClient(TestReplicaSetClientBase, TestRequestMixin):
|
||||
self.assertTrue("pymongo_test_bernie" in dbs)
|
||||
client.close()
|
||||
|
||||
def test_backport_repl_localthresholdms_uri(self):
|
||||
uri = ("mongodb://%s/?replicaSet=%s" % (pair, self.name))
|
||||
lt_uri = ("mongodb://%s/?replicaSet=%s;localThresholdMS=10"
|
||||
% (pair, self.name))
|
||||
sl_uri = ("mongodb://%s/?replicaSet=%s;secondaryAcceptableLatencyMS=10"
|
||||
% (pair, self.name))
|
||||
sl_lt_uri = ("mongodb://%s/?replicaSet=%s;localThresholdMS=10;"
|
||||
"secondaryAcceptableLatencyMS=8" % (pair, self.name))
|
||||
|
||||
# Just localThresholdMS
|
||||
client = MongoReplicaSetClient(uri)
|
||||
self.assertEqual(client.secondary_acceptable_latency_ms, 15)
|
||||
self.assertEqual(client.local_threshold_ms, 15)
|
||||
client = MongoReplicaSetClient(uri, localThresholdMS=10)
|
||||
self.assertEqual(client.secondary_acceptable_latency_ms, 10)
|
||||
self.assertEqual(client.local_threshold_ms, 10)
|
||||
client = MongoClient(uri, localThresholdMS=10,
|
||||
secondaryAcceptableLatencyMS=8)
|
||||
self.assertEqual(client.secondary_acceptable_latency_ms, 10)
|
||||
self.assertEqual(client.local_threshold_ms, 10)
|
||||
|
||||
# URI options take precedence over kwargs but localThresholdMS takes
|
||||
# precedence over secondaryAcceptableLatencyMS always. Test to make
|
||||
# sure the precedence is correct between URI vs. kwargs.
|
||||
client = MongoReplicaSetClient(lt_uri)
|
||||
self.assertEqual(client.secondary_acceptable_latency_ms, 10)
|
||||
self.assertEqual(client.local_threshold_ms, 10)
|
||||
client = MongoReplicaSetClient(lt_uri, localThresholdMS=8)
|
||||
self.assertEqual(client.secondary_acceptable_latency_ms, 10)
|
||||
self.assertEqual(client.local_threshold_ms, 10)
|
||||
client = MongoClient(lt_uri, secondaryAcceptableLatencyMS=8)
|
||||
self.assertEqual(client.secondary_acceptable_latency_ms, 10)
|
||||
self.assertEqual(client.local_threshold_ms, 10)
|
||||
client = MongoClient(lt_uri, secondaryAcceptableLatencyMS=8,
|
||||
localThresholdMS=6)
|
||||
self.assertEqual(client.secondary_acceptable_latency_ms, 10)
|
||||
self.assertEqual(client.local_threshold_ms, 10)
|
||||
|
||||
client = MongoClient(sl_uri, secondaryAcceptableLatencyMS=8)
|
||||
self.assertEqual(client.secondary_acceptable_latency_ms, 10)
|
||||
self.assertEqual(client.local_threshold_ms, 10)
|
||||
client = MongoClient(sl_uri, localThresholdMS=10)
|
||||
self.assertEqual(client.secondary_acceptable_latency_ms, 10)
|
||||
self.assertEqual(client.local_threshold_ms, 10)
|
||||
client = MongoClient(sl_uri, localThresholdMS=10,
|
||||
secondaryAcceptableLatencyMS=6)
|
||||
self.assertEqual(client.secondary_acceptable_latency_ms, 10)
|
||||
self.assertEqual(client.local_threshold_ms, 10)
|
||||
|
||||
client = MongoClient(sl_lt_uri)
|
||||
self.assertEqual(client.secondary_acceptable_latency_ms, 10)
|
||||
self.assertEqual(client.local_threshold_ms, 10)
|
||||
client = MongoClient(sl_lt_uri, localThresholdMS=8,
|
||||
secondaryAcceptableLatencyMS=4)
|
||||
self.assertEqual(client.secondary_acceptable_latency_ms, 10)
|
||||
self.assertEqual(client.local_threshold_ms, 10)
|
||||
|
||||
|
||||
def _test_kill_cursor_explicit(self, read_pref):
|
||||
c = self._get_client(read_preference=read_pref)
|
||||
db = c.pymongo_test
|
||||
|
||||
@ -138,6 +138,8 @@ class TestURI(unittest.TestCase):
|
||||
self.assertEqual({'authsource': 'foobar'}, split_options('authSource=foobar'))
|
||||
# maxPoolSize isn't yet a documented URI option.
|
||||
self.assertRaises(ConfigurationError, split_options, 'maxpoolsize=50')
|
||||
self.assertEqual({'localthresholdms': 300},
|
||||
split_options('localThresholdMS=300'))
|
||||
|
||||
def test_parse_uri(self):
|
||||
self.assertRaises(InvalidURI, parse_uri, "http://foobar.com")
|
||||
|
||||
Loading…
Reference in New Issue
Block a user