From d14a5a4e0a82fdd007a313101f32518cb6ce8ecb Mon Sep 17 00:00:00 2001 From: Iris Date: Mon, 16 Sep 2024 14:46:07 -0700 Subject: [PATCH 01/10] PYTHON-4585 Cursor.to_list does not apply client's timeoutMS setting --- pymongo/asynchronous/command_cursor.py | 3 +++ pymongo/asynchronous/cursor.py | 5 ++++- pymongo/synchronous/command_cursor.py | 3 +++ pymongo/synchronous/cursor.py | 5 ++++- test/asynchronous/test_cursor.py | 26 +++++++++++++++++++++++++- test/test_cursor.py | 26 +++++++++++++++++++++++++- 6 files changed, 64 insertions(+), 4 deletions(-) diff --git a/pymongo/asynchronous/command_cursor.py b/pymongo/asynchronous/command_cursor.py index b2cd345f63..5a4559bd77 100644 --- a/pymongo/asynchronous/command_cursor.py +++ b/pymongo/asynchronous/command_cursor.py @@ -29,6 +29,7 @@ ) from bson import CodecOptions, _convert_raw_document_lists_to_streams +from pymongo import _csot from pymongo.asynchronous.cursor import _ConnectionManager from pymongo.cursor_shared import _CURSOR_CLOSED_ERRORS from pymongo.errors import ConnectionFailure, InvalidOperation, OperationFailure @@ -77,6 +78,7 @@ def __init__( self._address = address self._batch_size = batch_size self._max_await_time_ms = max_await_time_ms + self._timeout = self._collection.database.client.options.timeout self._session = session self._explicit_session = explicit_session self._killed = self._id == 0 @@ -385,6 +387,7 @@ async def __aenter__(self) -> AsyncCommandCursor[_DocumentType]: async def __aexit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None: await self.close() + @_csot.apply async def to_list(self, length: Optional[int] = None) -> list[_DocumentType]: """Converts the contents of this cursor to a list more efficiently than ``[doc async for doc in cursor]``. diff --git a/pymongo/asynchronous/cursor.py b/pymongo/asynchronous/cursor.py index bae77bb304..dbe54134cb 100644 --- a/pymongo/asynchronous/cursor.py +++ b/pymongo/asynchronous/cursor.py @@ -36,7 +36,7 @@ from bson import RE_TYPE, _convert_raw_document_lists_to_streams from bson.code import Code from bson.son import SON -from pymongo import helpers_shared +from pymongo import _csot, helpers_shared from pymongo.asynchronous.helpers import anext from pymongo.collation import validate_collation_or_none from pymongo.common import ( @@ -196,6 +196,7 @@ def __init__( self._explain = False self._comment = comment self._max_time_ms = max_time_ms + self._timeout = self._collection.database.client.options.timeout self._max_await_time_ms: Optional[int] = None self._max: Optional[Union[dict[Any, Any], _Sort]] = max self._min: Optional[Union[dict[Any, Any], _Sort]] = min @@ -294,6 +295,7 @@ def _clone(self, deepcopy: bool = True, base: Optional[AsyncCursor] = None) -> A "limit", "max_time_ms", "max_await_time_ms", + "timeout", "comment", "max", "min", @@ -1290,6 +1292,7 @@ async def __aenter__(self) -> AsyncCursor[_DocumentType]: async def __aexit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None: await self.close() + @_csot.apply async def to_list(self, length: Optional[int] = None) -> list[_DocumentType]: """Converts the contents of this cursor to a list more efficiently than ``[doc async for doc in cursor]``. diff --git a/pymongo/synchronous/command_cursor.py b/pymongo/synchronous/command_cursor.py index da05bf1a3b..3a4372856a 100644 --- a/pymongo/synchronous/command_cursor.py +++ b/pymongo/synchronous/command_cursor.py @@ -29,6 +29,7 @@ ) from bson import CodecOptions, _convert_raw_document_lists_to_streams +from pymongo import _csot from pymongo.cursor_shared import _CURSOR_CLOSED_ERRORS from pymongo.errors import ConnectionFailure, InvalidOperation, OperationFailure from pymongo.message import ( @@ -77,6 +78,7 @@ def __init__( self._address = address self._batch_size = batch_size self._max_await_time_ms = max_await_time_ms + self._timeout = self._collection.database.client.options.timeout self._session = session self._explicit_session = explicit_session self._killed = self._id == 0 @@ -385,6 +387,7 @@ def __enter__(self) -> CommandCursor[_DocumentType]: def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None: self.close() + @_csot.apply def to_list(self, length: Optional[int] = None) -> list[_DocumentType]: """Converts the contents of this cursor to a list more efficiently than ``[doc for doc in cursor]``. diff --git a/pymongo/synchronous/cursor.py b/pymongo/synchronous/cursor.py index c352b64098..563f0e6c39 100644 --- a/pymongo/synchronous/cursor.py +++ b/pymongo/synchronous/cursor.py @@ -36,7 +36,7 @@ from bson import RE_TYPE, _convert_raw_document_lists_to_streams from bson.code import Code from bson.son import SON -from pymongo import helpers_shared +from pymongo import _csot, helpers_shared from pymongo.collation import validate_collation_or_none from pymongo.common import ( validate_is_document_type, @@ -196,6 +196,7 @@ def __init__( self._explain = False self._comment = comment self._max_time_ms = max_time_ms + self._timeout = self._collection.database.client.options.timeout self._max_await_time_ms: Optional[int] = None self._max: Optional[Union[dict[Any, Any], _Sort]] = max self._min: Optional[Union[dict[Any, Any], _Sort]] = min @@ -294,6 +295,7 @@ def _clone(self, deepcopy: bool = True, base: Optional[Cursor] = None) -> Cursor "limit", "max_time_ms", "max_await_time_ms", + "timeout", "comment", "max", "min", @@ -1288,6 +1290,7 @@ def __enter__(self) -> Cursor[_DocumentType]: def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None: self.close() + @_csot.apply def to_list(self, length: Optional[int] = None) -> list[_DocumentType]: """Converts the contents of this cursor to a list more efficiently than ``[doc for doc in cursor]``. diff --git a/test/asynchronous/test_cursor.py b/test/asynchronous/test_cursor.py index d6773d832e..a8c0042997 100644 --- a/test/asynchronous/test_cursor.py +++ b/test/asynchronous/test_cursor.py @@ -34,6 +34,7 @@ AllowListEventListener, EventListener, OvertCommandListener, + delay, ignore_deprecations, wait_until, ) @@ -44,7 +45,7 @@ from pymongo.asynchronous.cursor import AsyncCursor, CursorType from pymongo.asynchronous.helpers import anext from pymongo.collation import Collation -from pymongo.errors import ExecutionTimeout, InvalidOperation, OperationFailure +from pymongo.errors import ExecutionTimeout, InvalidOperation, OperationFailure, PyMongoError from pymongo.operations import _IndexList from pymongo.read_concern import ReadConcern from pymongo.read_preferences import ReadPreference @@ -1410,6 +1411,15 @@ async def test_to_list_length(self): docs = await c.to_list(3) self.assertEqual(len(docs), 2) + async def test_to_list_csot_applied(self): + client = await self.async_single_client(timeoutMS=1000) + coll = client.pymongo.test + await coll.insert_many([{} for _ in range(5)]) + cursor = coll.find({"$where": delay(2)}) + with self.assertRaises(PyMongoError) as ctx: + await cursor.to_list() + self.assertTrue(ctx.exception.timeout) + @async_client_context.require_change_streams async def test_command_cursor_to_list(self): # Set maxAwaitTimeMS=1 to speed up the test. @@ -1439,6 +1449,20 @@ async def test_command_cursor_to_list_length(self): result = await db.test.aggregate([pipeline]) self.assertEqual(len(await result.to_list(1)), 1) + @async_client_context.require_change_streams + async def test_command_cursor_to_list_csot_applied(self): + client = await self.async_single_client(timeoutMS=1000) + fail_command = { + "configureFailPoint": "failCommand", + "mode": {"times": 2}, + "data": {"failCommands": ["aggregate"], "blockConnection": True, "blockTimeMS": 10000}, + } + cursor = await client.db.test.aggregate([{"$changeStream": {}}], maxAwaitTimeMS=1) + async with self.fail_point(fail_command): + with self.assertRaises(PyMongoError) as ctx: + await cursor.to_list() + self.assertTrue(ctx.exception.timeout) + class TestRawBatchCursor(AsyncIntegrationTest): async def test_find_raw(self): diff --git a/test/test_cursor.py b/test/test_cursor.py index 9bc22aca3c..09dcc6c388 100644 --- a/test/test_cursor.py +++ b/test/test_cursor.py @@ -34,6 +34,7 @@ AllowListEventListener, EventListener, OvertCommandListener, + delay, ignore_deprecations, wait_until, ) @@ -42,7 +43,7 @@ from bson.code import Code from pymongo import ASCENDING, DESCENDING from pymongo.collation import Collation -from pymongo.errors import ExecutionTimeout, InvalidOperation, OperationFailure +from pymongo.errors import ExecutionTimeout, InvalidOperation, OperationFailure, PyMongoError from pymongo.operations import _IndexList from pymongo.read_concern import ReadConcern from pymongo.read_preferences import ReadPreference @@ -1401,6 +1402,15 @@ def test_to_list_length(self): docs = c.to_list(3) self.assertEqual(len(docs), 2) + def test_to_list_csot_applied(self): + client = self.single_client(timeoutMS=1000) + coll = client.pymongo.test + coll.insert_many([{} for _ in range(5)]) + cursor = coll.find({"$where": delay(2)}) + with self.assertRaises(PyMongoError) as ctx: + cursor.to_list() + self.assertTrue(ctx.exception.timeout) + @client_context.require_change_streams def test_command_cursor_to_list(self): # Set maxAwaitTimeMS=1 to speed up the test. @@ -1430,6 +1440,20 @@ def test_command_cursor_to_list_length(self): result = db.test.aggregate([pipeline]) self.assertEqual(len(result.to_list(1)), 1) + @client_context.require_change_streams + def test_command_cursor_to_list_csot_applied(self): + client = single_client(timeoutMS=1000) + fail_command = { + "configureFailPoint": "failCommand", + "mode": {"times": 2}, + "data": {"failCommands": ["aggregate"], "blockConnection": True, "blockTimeMS": 10000}, + } + cursor = client.db.test.aggregate([{"$changeStream": {}}], maxAwaitTimeMS=1) + with self.fail_point(fail_command): + with self.assertRaises(PyMongoError) as ctx: + cursor.to_list() + self.assertTrue(ctx.exception.timeout) + class TestRawBatchCursor(IntegrationTest): def test_find_raw(self): From 7aaaa6571cb2618e364897261d7c7208bc4739e4 Mon Sep 17 00:00:00 2001 From: Iris Date: Mon, 16 Sep 2024 15:28:54 -0700 Subject: [PATCH 02/10] require failCommand should fix my errors --- test/asynchronous/test_cursor.py | 1 + test/test_cursor.py | 1 + 2 files changed, 2 insertions(+) diff --git a/test/asynchronous/test_cursor.py b/test/asynchronous/test_cursor.py index a8c0042997..311845176c 100644 --- a/test/asynchronous/test_cursor.py +++ b/test/asynchronous/test_cursor.py @@ -1450,6 +1450,7 @@ async def test_command_cursor_to_list_length(self): self.assertEqual(len(await result.to_list(1)), 1) @async_client_context.require_change_streams + @async_client_context.require_failCommand_fail_point async def test_command_cursor_to_list_csot_applied(self): client = await self.async_single_client(timeoutMS=1000) fail_command = { diff --git a/test/test_cursor.py b/test/test_cursor.py index 09dcc6c388..c51d6f5a18 100644 --- a/test/test_cursor.py +++ b/test/test_cursor.py @@ -1441,6 +1441,7 @@ def test_command_cursor_to_list_length(self): self.assertEqual(len(result.to_list(1)), 1) @client_context.require_change_streams + @client_context.require_failCommand_fail_point def test_command_cursor_to_list_csot_applied(self): client = single_client(timeoutMS=1000) fail_command = { From d417ae890be8151a67e3fdd8c8464e9a31b7d60b Mon Sep 17 00:00:00 2001 From: Iris Date: Mon, 16 Sep 2024 16:06:43 -0700 Subject: [PATCH 03/10] attempt to figure out what the failures are... --- test/asynchronous/test_cursor.py | 2 +- test/test_cursor.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/asynchronous/test_cursor.py b/test/asynchronous/test_cursor.py index 311845176c..dc429176e0 100644 --- a/test/asynchronous/test_cursor.py +++ b/test/asynchronous/test_cursor.py @@ -1458,7 +1458,7 @@ async def test_command_cursor_to_list_csot_applied(self): "mode": {"times": 2}, "data": {"failCommands": ["aggregate"], "blockConnection": True, "blockTimeMS": 10000}, } - cursor = await client.db.test.aggregate([{"$changeStream": {}}], maxAwaitTimeMS=1) + cursor = await client.db.test.aggregate([{"$changeStream": {}}]) async with self.fail_point(fail_command): with self.assertRaises(PyMongoError) as ctx: await cursor.to_list() diff --git a/test/test_cursor.py b/test/test_cursor.py index c51d6f5a18..9a964e53ff 100644 --- a/test/test_cursor.py +++ b/test/test_cursor.py @@ -1449,7 +1449,7 @@ def test_command_cursor_to_list_csot_applied(self): "mode": {"times": 2}, "data": {"failCommands": ["aggregate"], "blockConnection": True, "blockTimeMS": 10000}, } - cursor = client.db.test.aggregate([{"$changeStream": {}}], maxAwaitTimeMS=1) + cursor = client.db.test.aggregate([{"$changeStream": {}}]) with self.fail_point(fail_command): with self.assertRaises(PyMongoError) as ctx: cursor.to_list() From 458e908011d9b1d6dc3999f2581104adbab846e7 Mon Sep 17 00:00:00 2001 From: Iris Date: Mon, 16 Sep 2024 16:47:31 -0700 Subject: [PATCH 04/10] attempt to fix failures --- test/asynchronous/test_cursor.py | 4 ++-- test/test_cursor.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/asynchronous/test_cursor.py b/test/asynchronous/test_cursor.py index dc429176e0..618f833eea 100644 --- a/test/asynchronous/test_cursor.py +++ b/test/asynchronous/test_cursor.py @@ -1455,8 +1455,8 @@ async def test_command_cursor_to_list_csot_applied(self): client = await self.async_single_client(timeoutMS=1000) fail_command = { "configureFailPoint": "failCommand", - "mode": {"times": 2}, - "data": {"failCommands": ["aggregate"], "blockConnection": True, "blockTimeMS": 10000}, + "mode": {"times": 1}, + "data": {"failCommands": ["aggregate"], "blockTimeMS": 10000}, } cursor = await client.db.test.aggregate([{"$changeStream": {}}]) async with self.fail_point(fail_command): diff --git a/test/test_cursor.py b/test/test_cursor.py index 9a964e53ff..015c240173 100644 --- a/test/test_cursor.py +++ b/test/test_cursor.py @@ -1446,8 +1446,8 @@ def test_command_cursor_to_list_csot_applied(self): client = single_client(timeoutMS=1000) fail_command = { "configureFailPoint": "failCommand", - "mode": {"times": 2}, - "data": {"failCommands": ["aggregate"], "blockConnection": True, "blockTimeMS": 10000}, + "mode": {"times": 1}, + "data": {"failCommands": ["aggregate"], "blockTimeMS": 10000}, } cursor = client.db.test.aggregate([{"$changeStream": {}}]) with self.fail_point(fail_command): From 983bbdb5704de2d1577f10c180d966461cf2b39f Mon Sep 17 00:00:00 2001 From: Iris Date: Mon, 16 Sep 2024 17:59:36 -0700 Subject: [PATCH 05/10] attempt to fix failures pt2 --- test/asynchronous/test_cursor.py | 4 ++-- test/test_cursor.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/asynchronous/test_cursor.py b/test/asynchronous/test_cursor.py index 618f833eea..8d85d7fb7f 100644 --- a/test/asynchronous/test_cursor.py +++ b/test/asynchronous/test_cursor.py @@ -1456,9 +1456,9 @@ async def test_command_cursor_to_list_csot_applied(self): fail_command = { "configureFailPoint": "failCommand", "mode": {"times": 1}, - "data": {"failCommands": ["aggregate"], "blockTimeMS": 10000}, + "data": {"failCommands": ["getMore"], "blockTimeMS": 10000}, } - cursor = await client.db.test.aggregate([{"$changeStream": {}}]) + cursor = await client.db.test.aggregate([], batchSize=5) async with self.fail_point(fail_command): with self.assertRaises(PyMongoError) as ctx: await cursor.to_list() diff --git a/test/test_cursor.py b/test/test_cursor.py index 015c240173..d9f83b8cf0 100644 --- a/test/test_cursor.py +++ b/test/test_cursor.py @@ -1447,9 +1447,9 @@ def test_command_cursor_to_list_csot_applied(self): fail_command = { "configureFailPoint": "failCommand", "mode": {"times": 1}, - "data": {"failCommands": ["aggregate"], "blockTimeMS": 10000}, + "data": {"failCommands": ["getMore"], "blockTimeMS": 10000}, } - cursor = client.db.test.aggregate([{"$changeStream": {}}]) + cursor = client.db.test.aggregate([], batchSize=5) with self.fail_point(fail_command): with self.assertRaises(PyMongoError) as ctx: cursor.to_list() From b4205723545afb1241490dfa46717ca8d6ec1b60 Mon Sep 17 00:00:00 2001 From: Iris Date: Mon, 16 Sep 2024 21:05:44 -0700 Subject: [PATCH 06/10] remove need for change streams and remove redundant timeout from clone --- pymongo/asynchronous/cursor.py | 1 - test/asynchronous/test_cursor.py | 5 ++--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/pymongo/asynchronous/cursor.py b/pymongo/asynchronous/cursor.py index dbe54134cb..4b4bb52a8e 100644 --- a/pymongo/asynchronous/cursor.py +++ b/pymongo/asynchronous/cursor.py @@ -295,7 +295,6 @@ def _clone(self, deepcopy: bool = True, base: Optional[AsyncCursor] = None) -> A "limit", "max_time_ms", "max_await_time_ms", - "timeout", "comment", "max", "min", diff --git a/test/asynchronous/test_cursor.py b/test/asynchronous/test_cursor.py index 8d85d7fb7f..c6013d8b59 100644 --- a/test/asynchronous/test_cursor.py +++ b/test/asynchronous/test_cursor.py @@ -1449,16 +1449,15 @@ async def test_command_cursor_to_list_length(self): result = await db.test.aggregate([pipeline]) self.assertEqual(len(await result.to_list(1)), 1) - @async_client_context.require_change_streams @async_client_context.require_failCommand_fail_point async def test_command_cursor_to_list_csot_applied(self): client = await self.async_single_client(timeoutMS=1000) fail_command = { "configureFailPoint": "failCommand", - "mode": {"times": 1}, + "mode": {"times": 2}, "data": {"failCommands": ["getMore"], "blockTimeMS": 10000}, } - cursor = await client.db.test.aggregate([], batchSize=5) + cursor = await client.db.test.aggregate([], batchSize=1) async with self.fail_point(fail_command): with self.assertRaises(PyMongoError) as ctx: await cursor.to_list() From 0e70ad419c6f86634da89d8e1782b2a1e5e0c32c Mon Sep 17 00:00:00 2001 From: Iris Date: Tue, 17 Sep 2024 08:55:34 -0700 Subject: [PATCH 07/10] using new way to create clients, still a wip though --- pymongo/synchronous/cursor.py | 1 - test/asynchronous/test_cursor.py | 6 ++++-- test/test_cursor.py | 9 +++++---- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/pymongo/synchronous/cursor.py b/pymongo/synchronous/cursor.py index 563f0e6c39..27a76cf91d 100644 --- a/pymongo/synchronous/cursor.py +++ b/pymongo/synchronous/cursor.py @@ -295,7 +295,6 @@ def _clone(self, deepcopy: bool = True, base: Optional[Cursor] = None) -> Cursor "limit", "max_time_ms", "max_await_time_ms", - "timeout", "comment", "max", "min", diff --git a/test/asynchronous/test_cursor.py b/test/asynchronous/test_cursor.py index c6013d8b59..9a171afaff 100644 --- a/test/asynchronous/test_cursor.py +++ b/test/asynchronous/test_cursor.py @@ -1452,12 +1452,14 @@ async def test_command_cursor_to_list_length(self): @async_client_context.require_failCommand_fail_point async def test_command_cursor_to_list_csot_applied(self): client = await self.async_single_client(timeoutMS=1000) + coll = client.pymongo.test + await coll.insert_many([{} for _ in range(10)]) fail_command = { "configureFailPoint": "failCommand", "mode": {"times": 2}, - "data": {"failCommands": ["getMore"], "blockTimeMS": 10000}, + "data": {"failCommands": ["getMore"], "blockTimeMS": 2000}, } - cursor = await client.db.test.aggregate([], batchSize=1) + cursor = await client.db.test.aggregate([], batchSize=5) async with self.fail_point(fail_command): with self.assertRaises(PyMongoError) as ctx: await cursor.to_list() diff --git a/test/test_cursor.py b/test/test_cursor.py index d9f83b8cf0..8d00d71901 100644 --- a/test/test_cursor.py +++ b/test/test_cursor.py @@ -1440,14 +1440,15 @@ def test_command_cursor_to_list_length(self): result = db.test.aggregate([pipeline]) self.assertEqual(len(result.to_list(1)), 1) - @client_context.require_change_streams @client_context.require_failCommand_fail_point def test_command_cursor_to_list_csot_applied(self): - client = single_client(timeoutMS=1000) + client = self.single_client(timeoutMS=1000) + coll = client.pymongo.test + coll.insert_many([{} for _ in range(10)]) fail_command = { "configureFailPoint": "failCommand", - "mode": {"times": 1}, - "data": {"failCommands": ["getMore"], "blockTimeMS": 10000}, + "mode": {"times": 2}, + "data": {"failCommands": ["getMore"], "blockTimeMS": 2000}, } cursor = client.db.test.aggregate([], batchSize=5) with self.fail_point(fail_command): From 947a33212e090e0138ab9e86435352b0adea99ac Mon Sep 17 00:00:00 2001 From: Iris Date: Tue, 17 Sep 2024 11:21:40 -0700 Subject: [PATCH 08/10] added blockConnection, tests should pass now --- test/asynchronous/test_cursor.py | 19 ++++++++++++------- test/test_cursor.py | 19 ++++++++++++------- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/test/asynchronous/test_cursor.py b/test/asynchronous/test_cursor.py index 9a171afaff..97432112f0 100644 --- a/test/asynchronous/test_cursor.py +++ b/test/asynchronous/test_cursor.py @@ -1412,10 +1412,13 @@ async def test_to_list_length(self): self.assertEqual(len(docs), 2) async def test_to_list_csot_applied(self): - client = await self.async_single_client(timeoutMS=1000) + client = await self.async_single_client(timeoutMS=500) + # Initialize the client with a larger timeout to help make test less flakey + with pymongo.timeout(2): + await client.admin.command("ping") coll = client.pymongo.test await coll.insert_many([{} for _ in range(5)]) - cursor = coll.find({"$where": delay(2)}) + cursor = coll.find({"$where": delay(1)}) with self.assertRaises(PyMongoError) as ctx: await cursor.to_list() self.assertTrue(ctx.exception.timeout) @@ -1451,15 +1454,17 @@ async def test_command_cursor_to_list_length(self): @async_client_context.require_failCommand_fail_point async def test_command_cursor_to_list_csot_applied(self): - client = await self.async_single_client(timeoutMS=1000) + client = await self.async_single_client(timeoutMS=500) + # Initialize the client with a larger timeout to help make test less flakey + with pymongo.timeout(2): + await client.admin.command("ping") coll = client.pymongo.test - await coll.insert_many([{} for _ in range(10)]) fail_command = { "configureFailPoint": "failCommand", - "mode": {"times": 2}, - "data": {"failCommands": ["getMore"], "blockTimeMS": 2000}, + "mode": {"times": 5}, + "data": {"failCommands": ["getMore"], "blockConnection": True, "blockTimeMS": 1000}, } - cursor = await client.db.test.aggregate([], batchSize=5) + cursor = await coll.aggregate([], batchSize=1) async with self.fail_point(fail_command): with self.assertRaises(PyMongoError) as ctx: await cursor.to_list() diff --git a/test/test_cursor.py b/test/test_cursor.py index 8d00d71901..1ba0525959 100644 --- a/test/test_cursor.py +++ b/test/test_cursor.py @@ -1403,10 +1403,13 @@ def test_to_list_length(self): self.assertEqual(len(docs), 2) def test_to_list_csot_applied(self): - client = self.single_client(timeoutMS=1000) + client = self.single_client(timeoutMS=500) + # Initialize the client with a larger timeout to help make test less flakey + with pymongo.timeout(2): + client.admin.command("ping") coll = client.pymongo.test coll.insert_many([{} for _ in range(5)]) - cursor = coll.find({"$where": delay(2)}) + cursor = coll.find({"$where": delay(1)}) with self.assertRaises(PyMongoError) as ctx: cursor.to_list() self.assertTrue(ctx.exception.timeout) @@ -1442,15 +1445,17 @@ def test_command_cursor_to_list_length(self): @client_context.require_failCommand_fail_point def test_command_cursor_to_list_csot_applied(self): - client = self.single_client(timeoutMS=1000) + client = self.single_client(timeoutMS=500) + # Initialize the client with a larger timeout to help make test less flakey + with pymongo.timeout(2): + client.admin.command("ping") coll = client.pymongo.test - coll.insert_many([{} for _ in range(10)]) fail_command = { "configureFailPoint": "failCommand", - "mode": {"times": 2}, - "data": {"failCommands": ["getMore"], "blockTimeMS": 2000}, + "mode": {"times": 5}, + "data": {"failCommands": ["getMore"], "blockConnection": True, "blockTimeMS": 1000}, } - cursor = client.db.test.aggregate([], batchSize=5) + cursor = coll.aggregate([], batchSize=1) with self.fail_point(fail_command): with self.assertRaises(PyMongoError) as ctx: cursor.to_list() From 84a6fe981c310008e2d3dae3f89164b4c719ba8b Mon Sep 17 00:00:00 2001 From: Iris Date: Tue, 17 Sep 2024 12:02:23 -0700 Subject: [PATCH 09/10] use require_failCommand_blockConnection instead of fail_point --- test/asynchronous/test_cursor.py | 2 +- test/test_cursor.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/asynchronous/test_cursor.py b/test/asynchronous/test_cursor.py index 97432112f0..6a334755b9 100644 --- a/test/asynchronous/test_cursor.py +++ b/test/asynchronous/test_cursor.py @@ -1452,7 +1452,7 @@ async def test_command_cursor_to_list_length(self): result = await db.test.aggregate([pipeline]) self.assertEqual(len(await result.to_list(1)), 1) - @async_client_context.require_failCommand_fail_point + @async_client_context.require_failCommand_blockConnection async def test_command_cursor_to_list_csot_applied(self): client = await self.async_single_client(timeoutMS=500) # Initialize the client with a larger timeout to help make test less flakey diff --git a/test/test_cursor.py b/test/test_cursor.py index 1ba0525959..e54313bcd2 100644 --- a/test/test_cursor.py +++ b/test/test_cursor.py @@ -1443,7 +1443,7 @@ def test_command_cursor_to_list_length(self): result = db.test.aggregate([pipeline]) self.assertEqual(len(result.to_list(1)), 1) - @client_context.require_failCommand_fail_point + @client_context.require_failCommand_blockConnection def test_command_cursor_to_list_csot_applied(self): client = self.single_client(timeoutMS=500) # Initialize the client with a larger timeout to help make test less flakey From 309e60c312335a500c39498b5074334a2e8d89c8 Mon Sep 17 00:00:00 2001 From: Iris Date: Tue, 17 Sep 2024 12:34:44 -0700 Subject: [PATCH 10/10] okay this should actually pass now --- test/asynchronous/test_cursor.py | 1 + test/test_cursor.py | 1 + 2 files changed, 2 insertions(+) diff --git a/test/asynchronous/test_cursor.py b/test/asynchronous/test_cursor.py index 6a334755b9..33eaacee96 100644 --- a/test/asynchronous/test_cursor.py +++ b/test/asynchronous/test_cursor.py @@ -1459,6 +1459,7 @@ async def test_command_cursor_to_list_csot_applied(self): with pymongo.timeout(2): await client.admin.command("ping") coll = client.pymongo.test + await coll.insert_many([{} for _ in range(5)]) fail_command = { "configureFailPoint": "failCommand", "mode": {"times": 5}, diff --git a/test/test_cursor.py b/test/test_cursor.py index e54313bcd2..d99732aec3 100644 --- a/test/test_cursor.py +++ b/test/test_cursor.py @@ -1450,6 +1450,7 @@ def test_command_cursor_to_list_csot_applied(self): with pymongo.timeout(2): client.admin.command("ping") coll = client.pymongo.test + coll.insert_many([{} for _ in range(5)]) fail_command = { "configureFailPoint": "failCommand", "mode": {"times": 5},