diff --git a/doc/changelog.rst b/doc/changelog.rst index c5a4f47d79..6fffcdf696 100644 --- a/doc/changelog.rst +++ b/doc/changelog.rst @@ -42,6 +42,12 @@ PyMongo 4.9 brings a number of improvements including: - Fixed a bug where PyMongo would raise ``InvalidBSON: date value out of range`` when using :attr:`~bson.codec_options.DatetimeConversion.DATETIME_CLAMP` or :attr:`~bson.codec_options.DatetimeConversion.DATETIME_AUTO` with a non-UTC timezone. +- The default value for ``connect`` in ``MongoClient`` is changed to ``False`` when running on + unction-as-a-service (FaaS) like AWS Lambda, Google Cloud Functions, and Microsoft Azure Functions. + On some FaaS systems, there is a ``fork()`` operation at function + startup. By delaying the connection to the first operation, we avoid a deadlock. See + `Is PyMongo Fork-Safe`_ for more information. + Issues Resolved ............... @@ -49,6 +55,7 @@ Issues Resolved See the `PyMongo 4.9 release notes in JIRA`_ for the list of resolved issues in this release. +.. _Is PyMongo Fork-Safe : https://www.mongodb.com/docs/languages/python/pymongo-driver/current/faq/#is-pymongo-fork-safe- .. _PyMongo 4.9 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=39940 diff --git a/pymongo/asynchronous/mongo_client.py b/pymongo/asynchronous/mongo_client.py index 2af773c440..b5e73e8de8 100644 --- a/pymongo/asynchronous/mongo_client.py +++ b/pymongo/asynchronous/mongo_client.py @@ -720,6 +720,10 @@ def __init__( .. versionchanged:: 4.7 Deprecated parameter ``wTimeoutMS``, use :meth:`~pymongo.timeout`. + + .. versionchanged:: 4.9 + The default value of ``connect`` is changed to ``False`` when running in a + Function-as-a-service environment. """ doc_class = document_class or dict self._init_kwargs: dict[str, Any] = { @@ -803,7 +807,10 @@ def __init__( if tz_aware is None: tz_aware = opts.get("tz_aware", False) if connect is None: - connect = opts.get("connect", True) + # Default to connect=True unless on a FaaS system, which might use fork. + from pymongo.pool_options import _is_faas + + connect = opts.get("connect", not _is_faas()) keyword_opts["tz_aware"] = tz_aware keyword_opts["connect"] = connect diff --git a/pymongo/synchronous/mongo_client.py b/pymongo/synchronous/mongo_client.py index 6c5f68b7eb..26af488acd 100644 --- a/pymongo/synchronous/mongo_client.py +++ b/pymongo/synchronous/mongo_client.py @@ -263,7 +263,8 @@ def __init__( aware (otherwise they will be naive) :param connect: If ``True`` (the default), immediately begin connecting to MongoDB in the background. Otherwise connect - on the first operation. + on the first operation. The default value is ``False`` when + running in a Function-as-a-service environment. :param type_registry: instance of :class:`~bson.codec_options.TypeRegistry` to enable encoding and decoding of custom types. @@ -719,6 +720,10 @@ def __init__( .. versionchanged:: 4.7 Deprecated parameter ``wTimeoutMS``, use :meth:`~pymongo.timeout`. + + .. versionchanged:: 4.9 + The default value of ``connect`` is changed to ``False`` when running in a + Function-as-a-service environment. """ doc_class = document_class or dict self._init_kwargs: dict[str, Any] = { @@ -802,7 +807,10 @@ def __init__( if tz_aware is None: tz_aware = opts.get("tz_aware", False) if connect is None: - connect = opts.get("connect", True) + # Default to connect=True unless on a FaaS system, which might use fork. + from pymongo.pool_options import _is_faas + + connect = opts.get("connect", not _is_faas()) keyword_opts["tz_aware"] = tz_aware keyword_opts["connect"] = connect diff --git a/test/lambda/mongodb/app.py b/test/lambda/mongodb/app.py index 5840347d9a..274990d3bc 100644 --- a/test/lambda/mongodb/app.py +++ b/test/lambda/mongodb/app.py @@ -8,6 +8,7 @@ import json import os +import warnings from bson import has_c as has_bson_c from pymongo import MongoClient @@ -18,6 +19,9 @@ ServerHeartbeatListener, ) +# Ensure there are no warnings raised in normal operation. +warnings.simplefilter("error") + open_connections = 0 heartbeat_count = 0 streaming_heartbeat_count = 0 diff --git a/tools/synchro.py b/tools/synchro.py index f38a83f128..b5a6922618 100644 --- a/tools/synchro.py +++ b/tools/synchro.py @@ -108,7 +108,8 @@ docstring_replacements: dict[tuple[str, str], str] = { ("MongoClient", "connect"): """If ``True`` (the default), immediately begin connecting to MongoDB in the background. Otherwise connect - on the first operation.""", + on the first operation. The default value is ``False`` when + running in a Function-as-a-service environment.""", ("Collection", "create"): """If ``True``, force collection creation even without options being set.""", ("Collection", "session"): """A