PYTHON-3636 MongoClient should perform SRV resolution lazily#2191
PYTHON-3636 MongoClient should perform SRV resolution lazily#2191ShaneHarvey merged 64 commits intomongodb:masterfrom
Conversation
NoahStapp
left a comment
There was a problem hiding this comment.
Some small clarity tweaks and async-specific changes, but great start!
Co-authored-by: Noah Stapp <noah@noahstapp.com>
| srvServiceName="customname", | ||
| connect=False, | ||
| ) | ||
| await client.aconnect() |
There was a problem hiding this comment.
Are these open/close calls still needed?
There was a problem hiding this comment.
yes because these are srv uris
pymongo/srv_resolver.py
Outdated
| ttl = rrset.ttl if rrset else 0 | ||
| return nodes, ttl | ||
| __doc__ = original_doc | ||
| __all__ = ["maybe_decode", "_SrvResolver"] |
There was a problem hiding this comment.
Thanks for checking, let's remove it.
| print(exc) # noqa: T201 | ||
| sys.exit(0) | ||
| from pymongo.synchronous.uri_parser import * # noqa: F403 | ||
| from pymongo.synchronous.uri_parser import __doc__ as original_doc |
There was a problem hiding this comment.
By __doc__ I mean a module level docstring like:
"""Tools to parse and validate a MongoDB URI."""
pymongo/asynchronous/mongo_client.py
Outdated
|
|
||
| def __hash__(self) -> int: | ||
| return hash(self._topology) | ||
| if self._topology is None: |
There was a problem hiding this comment.
We still need to address hashing and equality. It's broken to change the hash of an object since it means that a single client could be added twice to a dictionary or set. The hash (and eq) methods need to use a single deterministic approach:
set = {}
c = AsyncMongoClient('mongodb+srv://...')
set.add(c)
await c.aconnect()
set.add(c)
assert len(set) == 1This means we need to use the eq_props() approach in all cases.
pymongo/asynchronous/mongo_client.py
Outdated
| raise TypeError(f"port must be an instance of int, not {type(port)}") | ||
| self._host = host | ||
| self._port = port | ||
| self._topology: Optional[Topology] = None |
There was a problem hiding this comment.
Adding assert self._topology is not None so many times feels a bit off since it adds runtime overhead for a static typing issue. What if we do this instead?:
self._topology: Topology = None # type: ignore[assignment]
pymongo/asynchronous/mongo_client.py
Outdated
| self._kill_cursors_executor.join(), # type: ignore[func-returns-value] | ||
| return_exceptions=True, | ||
| ) | ||
| if self._topology is not None: |
There was a problem hiding this comment.
Rather than indenting this code (which causes code churn) how about we do this?:
if self._topology is not None:
return
session_ids = self._topology.pop_all_sessions()
...| ) | ||
| with self.assertRaisesRegex(ConfigurationError, "Invalid URI host: mongodb is not"): | ||
| client = self.simple_client("mongodb+srv://mongodb") | ||
| await client.aconnect() |
There was a problem hiding this comment.
This behavior change is important to call out in the changelog and jira ticket.
pymongo/asynchronous/mongo_client.py
Outdated
| "%s:%d" % (host, port) if port is not None else host | ||
| for host, port in self._topology_settings.seeds | ||
| if self._topology is None: | ||
| options = self._resolve_srv_info["seeds"] |
There was a problem hiding this comment.
Do we have tests for this? If not could we add some? I'd like to see the behavior difference in repr().
pymongo/asynchronous/mongo_client.py
Outdated
| cast, | ||
| ) | ||
|
|
||
| import pymongo.uri_parser_shared |
There was a problem hiding this comment.
Duplicate import with the from pymongo_uri_parsed_shared... below.
pymongo/asynchronous/srv_resolver.py
Outdated
| if hasattr(asyncresolver, "resolve"): | ||
| # dnspython >= 2 | ||
| return await asyncresolver.resolve(*args, **kwargs) # type:ignore[return-value] | ||
| raise ConfigurationError("Upgrade to dnspython version >= 2.0") |
There was a problem hiding this comment.
This error message should explicitly inform users that they are attempting to use the async API with an old dnspython version. Telling them only to upgrade without any other information is inconsistent with the underlying reason.
There was a problem hiding this comment.
Could you add a commit suggestion here?
test/test_default_exports.py
Outdated
|
|
||
| def test_pymongo_imports(self): | ||
| import pymongo | ||
| from pymongo.asynchronous.uri_parser import parse_uri |
There was a problem hiding this comment.
This test ensures backwards compatibility with our synchronous API public exports, so there shouldn't be any asynchronous imports here.
There was a problem hiding this comment.
Good catch. We need to revert all the changes to this test.
Co-authored-by: Noah Stapp <noah@noahstapp.com>
pymongo/asynchronous/srv_resolver.py
Outdated
| if hasattr(asyncresolver, "resolve"): | ||
| # dnspython >= 2 | ||
| return await asyncresolver.resolve(*args, **kwargs) # type:ignore[return-value] | ||
| raise ConfigurationError("Upgrade to dnspython version >= 2.0") |
There was a problem hiding this comment.
| raise ConfigurationError("Upgrade to dnspython version >= 2.0") | |
| raise ConfigurationError("Upgrade to dnspython version >= 2.0 to use AsyncMongoClient with mongodb+srv:// connections.") |
ShaneHarvey
left a comment
There was a problem hiding this comment.
LGTM once the tests pass!
https://jira.mongodb.org/browse/PYTHON-3636