diff --git a/doc/changelog.rst b/doc/changelog.rst index 5c781a24f..9c9e96ed0 100644 --- a/doc/changelog.rst +++ b/doc/changelog.rst @@ -32,6 +32,9 @@ Version 3.9 adds support for MongoDB 4.2. Highlights include: - ``ssl_ca_certs`` has been deprecated in favor of ``tlsCAFile``. - ``ssl_certfile`` has been deprecated in favor of ``tlsCertificateKeyFile``. - ``ssl_pem_passphrase`` has been deprecated in favor of ``tlsCertificateKeyFilePassword``. + - ``waitQueueMultiple`` has been deprecated without replacement. This option + was a poor solution for putting an upper bound on queuing since it didn't + affect queuing in other parts of the driver. - The ``retryWrites`` URI option now defaults to ``True``. Supported write operations that fail with a retryable error will automatically be retried one time, with at-most-once semantics. diff --git a/doc/faq.rst b/doc/faq.rst index c425c438a..2f72746b4 100644 --- a/doc/faq.rst +++ b/doc/faq.rst @@ -98,21 +98,12 @@ process, increase ``maxPoolSize``:: client = MongoClient(host, port, maxPoolSize=None) -By default, any number of threads are allowed to wait for sockets to become -available, and they can wait any length of time. Override ``waitQueueMultiple`` -to cap the number of waiting threads. E.g., to keep the number of waiters less -than or equal to 500:: - - client = MongoClient(host, port, maxPoolSize=50, waitQueueMultiple=10) - -When 500 threads are waiting for a socket, the 501st that needs a socket -raises :exc:`~pymongo.errors.ExceededMaxWaiters`. Use this option to -bound the amount of queueing in your application during a load spike, at the -cost of additional exceptions. - -Once the pool reaches its max size, additional threads are allowed to wait -indefinitely for sockets to become available, unless you set -``waitQueueTimeoutMS``:: +Once the pool reaches its maximum size, additional threads have to wait for +sockets to become available. PyMongo does not limit the number of threads +that can wait for sockets to become available and it is the application's +responsibility to limit the size of its thread pool to bound queuing during a +load spike. Threads are allowed to wait for any length of time unless +``waitQueueTimeoutMS`` is defined:: client = MongoClient(host, port, waitQueueTimeoutMS=100) diff --git a/pymongo/common.py b/pymongo/common.py index f61b404ec..76c14e08f 100644 --- a/pymongo/common.py +++ b/pymongo/common.py @@ -658,16 +658,26 @@ INTERNAL_URI_OPTION_NAME_MAP = { 'tlscertificatekeyfilepassword': 'ssl_pem_passphrase', } -# Map from deprecated URI option names to the updated option names. -# Case is preserved for updated option names as they are part of user warnings. +# Map from deprecated URI option names to a tuple indicating the method of +# their deprecation and any additional information that may be needed to +# construct the warning message. URI_OPTIONS_DEPRECATION_MAP = { - 'j': 'journal', - 'wtimeout': 'wTimeoutMS', - 'ssl_cert_reqs': 'tlsAllowInvalidCertificates', - 'ssl_match_hostname': 'tlsAllowInvalidHostnames', - 'ssl_crlfile': 'tlsCRLFile', - 'ssl_ca_certs': 'tlsCAFile', - 'ssl_pem_passphrase': 'tlsCertificateKeyFilePassword', + # format: : (, ), + # Supported values: + # - 'renamed': should be the new option name. Note that case is + # preserved for renamed options as they are part of user warnings. + # - 'removed': may suggest the rationale for deprecating the + # option and/or recommend remedial action. + 'j': ('renamed', 'journal'), + 'wtimeout': ('renamed', 'wTimeoutMS'), + 'ssl_cert_reqs': ('renamed', 'tlsAllowInvalidCertificates'), + 'ssl_match_hostname': ('renamed', 'tlsAllowInvalidHostnames'), + 'ssl_crlfile': ('renamed', 'tlsCRLFile'), + 'ssl_ca_certs': ('renamed', 'tlsCAFile'), + 'ssl_pem_passphrase': ('renamed', 'tlsCertificateKeyFilePassword'), + 'waitqueuemultiple': ('removed', ( + 'Instead of using waitQueueMultiple to bound queuing, limit the size ' + 'of the thread pool in your application server')) } # Augment the option validator map with pymongo-specific option information. diff --git a/pymongo/uri_parser.py b/pymongo/uri_parser.py index becbf16e1..82e69b163 100644 --- a/pymongo/uri_parser.py +++ b/pymongo/uri_parser.py @@ -195,16 +195,27 @@ def _handle_option_deprecations(options): """ for optname in list(options): if optname in URI_OPTIONS_DEPRECATION_MAP: - newoptname = URI_OPTIONS_DEPRECATION_MAP[optname] - if newoptname in options: - warn_msg = "Deprecated option '%s' ignored in favor of '%s'." - warnings.warn(warn_msg % (options.cased_key(optname), - options.cased_key(newoptname))) - options.pop(optname) - continue - warn_msg = "Option '%s' is deprecated, use '%s' instead." - warnings.warn(warn_msg % (options.cased_key(optname), - newoptname)) + mode, message = URI_OPTIONS_DEPRECATION_MAP[optname] + if mode == 'renamed': + newoptname = message + if newoptname in options: + warn_msg = ("Deprecated option '%s' ignored in favor of " + "'%s'.") + warnings.warn( + warn_msg % (options.cased_key(optname), + options.cased_key(newoptname)), + DeprecationWarning, stacklevel=2) + options.pop(optname) + continue + warn_msg = "Option '%s' is deprecated, use '%s' instead." + warnings.warn( + warn_msg % (options.cased_key(optname), newoptname), + DeprecationWarning, stacklevel=2) + elif mode == 'removed': + warn_msg = "Option '%s' is deprecated. %s." + warnings.warn( + warn_msg % (options.cased_key(optname), message), + DeprecationWarning, stacklevel=2) return options diff --git a/test/test_uri_parser.py b/test/test_uri_parser.py index 8f626633f..d218e2be7 100644 --- a/test/test_uri_parser.py +++ b/test/test_uri_parser.py @@ -485,6 +485,15 @@ class TestURI(unittest.TestCase): "fsync": True, "wtimeoutms": 10} self.assertEqual(res, parse_uri(uri)["options"]) + def test_waitQueueMultiple_deprecated(self): + uri = "mongodb://example.com/?waitQueueMultiple=5" + with warnings.catch_warnings(record=True) as ctx: + warnings.simplefilter('always') + parse_uri(uri) + + self.assertEqual(len(ctx), 1) + self.assertTrue(issubclass(ctx[0].category, DeprecationWarning)) + if __name__ == "__main__": unittest.main()