remove op_query
This commit is contained in:
parent
8dc7efade2
commit
ebb7b1fdae
@ -46,6 +46,8 @@ from pymongo.common import (
|
||||
MAX_MESSAGE_SIZE,
|
||||
MAX_WIRE_VERSION,
|
||||
MAX_WRITE_BATCH_SIZE,
|
||||
MIN_SUPPORTED_SERVER_VERSION,
|
||||
MIN_SUPPORTED_WIRE_VERSION,
|
||||
ORDERED_TYPES,
|
||||
)
|
||||
from pymongo.errors import ( # type:ignore[attr-defined]
|
||||
@ -235,13 +237,12 @@ class AsyncConnection:
|
||||
await self.close_conn(ConnectionClosedReason.STALE)
|
||||
|
||||
def hello_cmd(self) -> dict[str, Any]:
|
||||
# Handshake spec requires us to use OP_MSG+hello command for the
|
||||
# initial handshake in load balanced or stable API mode.
|
||||
# As of PYTHON-5713, always use OP_MSG for the handshake since all
|
||||
# supported servers (MongoDB 4.2+, wire version >= 8) support it.
|
||||
self.op_msg_enabled = True
|
||||
if self.opts.server_api or self.hello_ok or self.opts.load_balanced:
|
||||
self.op_msg_enabled = True
|
||||
return {HelloCompat.CMD: 1}
|
||||
else:
|
||||
return {HelloCompat.LEGACY_CMD: 1, "helloOk": True}
|
||||
return {HelloCompat.LEGACY_CMD: 1, "helloOk": True}
|
||||
|
||||
async def hello(self) -> Hello[dict[str, Any]]:
|
||||
return await self._hello(None, None)
|
||||
@ -291,6 +292,19 @@ class AsyncConnection:
|
||||
if performing_handshake:
|
||||
self.connect_rtt = time.monotonic() - start
|
||||
hello = Hello(doc, awaitable=awaitable)
|
||||
# OP_MSG requires wire version 6+.
|
||||
if hello.max_wire_version < 6:
|
||||
raise ConfigurationError(
|
||||
"Server at %s:%d reports wire version %d, but this version of "
|
||||
"PyMongo requires at least %d (MongoDB %s)."
|
||||
% (
|
||||
self.address[0],
|
||||
self.address[1] or 0,
|
||||
hello.max_wire_version,
|
||||
MIN_SUPPORTED_WIRE_VERSION,
|
||||
MIN_SUPPORTED_SERVER_VERSION,
|
||||
)
|
||||
)
|
||||
self.is_writable = hello.is_writable
|
||||
self.max_wire_version = hello.max_wire_version
|
||||
self.max_bson_size = hello.max_bson_size
|
||||
|
||||
@ -43,6 +43,8 @@ from pymongo.common import (
|
||||
MAX_MESSAGE_SIZE,
|
||||
MAX_WIRE_VERSION,
|
||||
MAX_WRITE_BATCH_SIZE,
|
||||
MIN_SUPPORTED_SERVER_VERSION,
|
||||
MIN_SUPPORTED_WIRE_VERSION,
|
||||
ORDERED_TYPES,
|
||||
)
|
||||
from pymongo.errors import ( # type:ignore[attr-defined]
|
||||
@ -235,13 +237,12 @@ class Connection:
|
||||
self.close_conn(ConnectionClosedReason.STALE)
|
||||
|
||||
def hello_cmd(self) -> dict[str, Any]:
|
||||
# Handshake spec requires us to use OP_MSG+hello command for the
|
||||
# initial handshake in load balanced or stable API mode.
|
||||
# As of PYTHON-5713, always use OP_MSG for the handshake since all
|
||||
# supported servers (MongoDB 4.2+, wire version >= 8) support it.
|
||||
self.op_msg_enabled = True
|
||||
if self.opts.server_api or self.hello_ok or self.opts.load_balanced:
|
||||
self.op_msg_enabled = True
|
||||
return {HelloCompat.CMD: 1}
|
||||
else:
|
||||
return {HelloCompat.LEGACY_CMD: 1, "helloOk": True}
|
||||
return {HelloCompat.LEGACY_CMD: 1, "helloOk": True}
|
||||
|
||||
def hello(self) -> Hello[dict[str, Any]]:
|
||||
return self._hello(None, None)
|
||||
@ -291,6 +292,19 @@ class Connection:
|
||||
if performing_handshake:
|
||||
self.connect_rtt = time.monotonic() - start
|
||||
hello = Hello(doc, awaitable=awaitable)
|
||||
# OP_MSG requires wire version 6+.
|
||||
if hello.max_wire_version < 6:
|
||||
raise ConfigurationError(
|
||||
"Server at %s:%d reports wire version %d, but this version of "
|
||||
"PyMongo requires at least %d (MongoDB %s)."
|
||||
% (
|
||||
self.address[0],
|
||||
self.address[1] or 0,
|
||||
hello.max_wire_version,
|
||||
MIN_SUPPORTED_WIRE_VERSION,
|
||||
MIN_SUPPORTED_SERVER_VERSION,
|
||||
)
|
||||
)
|
||||
self.is_writable = hello.is_writable
|
||||
self.max_wire_version = hello.max_wire_version
|
||||
self.max_bson_size = hello.max_bson_size
|
||||
|
||||
@ -13,12 +13,13 @@
|
||||
# limitations under the License.
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
import unittest
|
||||
|
||||
import pytest
|
||||
|
||||
try:
|
||||
from mockupdb import Command, MockupDB, OpMsg, OpMsgReply, OpQuery, OpReply, absent, go
|
||||
from mockupdb import Command, MockupDB, OpMsg, OpMsgReply, OpReply, absent, go
|
||||
|
||||
_HAVE_MOCKUPDB = True
|
||||
except ImportError:
|
||||
@ -28,8 +29,8 @@ except ImportError:
|
||||
from bson.objectid import ObjectId
|
||||
from pymongo import MongoClient, has_c
|
||||
from pymongo import version as pymongo_version
|
||||
from pymongo.common import MIN_SUPPORTED_WIRE_VERSION
|
||||
from pymongo.errors import OperationFailure
|
||||
from pymongo.common import MIN_SUPPORTED_SERVER_VERSION, MIN_SUPPORTED_WIRE_VERSION
|
||||
from pymongo.errors import ConfigurationError, OperationFailure, ServerSelectionTimeoutError
|
||||
from pymongo.server_api import ServerApi, ServerApiVersion
|
||||
|
||||
pytestmark = pytest.mark.mockupdb
|
||||
@ -53,7 +54,7 @@ def _check_handshake_data(request):
|
||||
|
||||
class TestHandshake(unittest.TestCase):
|
||||
def hello_with_option_helper(self, protocol, **kwargs):
|
||||
hello = "ismaster" if isinstance(protocol(), OpQuery) else "hello"
|
||||
hello = "hello" if ("apiVersion" in kwargs or "loadBalanced" in kwargs) else "ismaster"
|
||||
# `db.command("hello"|"ismaster")` commands are the same for primaries and
|
||||
# secondaries, so we only need one server.
|
||||
primary = MockupDB()
|
||||
@ -165,7 +166,7 @@ class TestHandshake(unittest.TestCase):
|
||||
future = go(client.db.command, "whatever")
|
||||
|
||||
for request in primary:
|
||||
if request.matches(Command("ismaster")):
|
||||
if request.matches("ismaster"):
|
||||
if request.client_port == heartbeat.client_port:
|
||||
# This is the monitor again, keep going.
|
||||
request.ok(primary_response)
|
||||
@ -242,11 +243,10 @@ class TestHandshake(unittest.TestCase):
|
||||
self.hello_with_option_helper(Command, apiVersion="1")
|
||||
|
||||
def test_handshake_not_either(self):
|
||||
# If we don't specify either option then it should be using
|
||||
# OP_QUERY for the initial step of the handshake.
|
||||
self.hello_with_option_helper(Command)
|
||||
# As of PYTHON-5713, always use OP_MSG for the initial handshake.
|
||||
self.hello_with_option_helper(OpMsg)
|
||||
with self.assertRaisesRegex(AssertionError, "does not match"):
|
||||
self.hello_with_option_helper(OpMsg)
|
||||
self.hello_with_option_helper(Command)
|
||||
|
||||
def test_handshake_max_wire(self):
|
||||
server = MockupDB()
|
||||
@ -292,6 +292,26 @@ class TestHandshake(unittest.TestCase):
|
||||
self.found_auth_msg, "Could not find authentication command with correct protocol"
|
||||
)
|
||||
|
||||
def test_handshake_op_msg_not_supported(self):
|
||||
# If a server responds with maxWireVersion < 6 (no OP_MSG support),
|
||||
# the wire version error must surface to the user.
|
||||
server = MockupDB()
|
||||
server.autoresponds("ismaster", ok=1, ismaster=True, minWireVersion=0, maxWireVersion=5)
|
||||
server.run()
|
||||
self.addCleanup(server.stop)
|
||||
|
||||
client = MongoClient(server.uri, serverSelectionTimeoutMS=500)
|
||||
self.addCleanup(client.close)
|
||||
|
||||
# The ConfigurationError from _hello() is stored as the server's error
|
||||
# and surfaces inside ServerSelectionTimeoutError.
|
||||
expected = re.escape(
|
||||
"reports wire version 5, but this version of PyMongo requires at least "
|
||||
"%d (MongoDB %s)." % (MIN_SUPPORTED_WIRE_VERSION, MIN_SUPPORTED_SERVER_VERSION)
|
||||
)
|
||||
with self.assertRaisesRegex(ServerSelectionTimeoutError, expected):
|
||||
client.db.command("ping")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Loading…
Reference in New Issue
Block a user