|
21 | 21 | import threading |
22 | 22 | from test.asynchronous.utils import async_set_fail_point |
23 | 23 |
|
| 24 | +from pymongo import ReadPreference |
24 | 25 | from pymongo.errors import OperationFailure |
25 | 26 |
|
26 | 27 | sys.path[0:0] = [""] |
@@ -182,6 +183,44 @@ async def test_retryable_reads_are_retried_on_a_different_mongos_when_one_is_ava |
182 | 183 | # Assert that both events occurred on different mongos. |
183 | 184 | assert listener.failed_events[0].connection_id != listener.failed_events[1].connection_id |
184 | 185 |
|
| 186 | + @async_client_context.require_replica_set |
| 187 | + @async_client_context.require_failCommand_fail_point |
| 188 | + async def test_retryable_reads_are_retried_on_a_different_replica_when_one_is_available(self): |
| 189 | + fail_command = { |
| 190 | + "configureFailPoint": "failCommand", |
| 191 | + "mode": {"times": 1}, |
| 192 | + "data": {"failCommands": ["find"], "errorCode": 6}, |
| 193 | + } |
| 194 | + |
| 195 | + replica_clients = [] |
| 196 | + |
| 197 | + for node in async_client_context.nodes: |
| 198 | + client = await self.async_rs_or_single_client(*node, directConnection=True) |
| 199 | + await async_set_fail_point(client, fail_command) |
| 200 | + replica_clients.append(client) |
| 201 | + |
| 202 | + listener = OvertCommandListener() |
| 203 | + client = await self.async_rs_or_single_client( |
| 204 | + event_listeners=[listener], |
| 205 | + retryReads=True, |
| 206 | + directConnection=False, |
| 207 | + readPreference="secondaryPreferred", |
| 208 | + ) |
| 209 | + |
| 210 | + with self.assertRaises(OperationFailure): |
| 211 | + await client.t.t.find_one({}) |
| 212 | + |
| 213 | + # Disable failpoints on each node |
| 214 | + for client in replica_clients: |
| 215 | + fail_command["mode"] = "off" |
| 216 | + await async_set_fail_point(client, fail_command) |
| 217 | + |
| 218 | + self.assertEqual(len(listener.failed_events), 2) |
| 219 | + self.assertEqual(len(listener.succeeded_events), 0) |
| 220 | + |
| 221 | + # Assert that both events occurred on different nodes. |
| 222 | + assert listener.failed_events[0].connection_id != listener.failed_events[1].connection_id |
| 223 | + |
185 | 224 | @async_client_context.require_multiple_mongoses |
186 | 225 | @async_client_context.require_failCommand_fail_point |
187 | 226 | async def test_retryable_reads_are_retried_on_the_same_mongos_when_no_others_are_available( |
@@ -218,6 +257,38 @@ async def test_retryable_reads_are_retried_on_the_same_mongos_when_no_others_are |
218 | 257 | # Assert that both events occurred on the same mongos. |
219 | 258 | assert listener.succeeded_events[0].connection_id == listener.failed_events[0].connection_id |
220 | 259 |
|
| 260 | + @async_client_context.require_replica_set |
| 261 | + @async_client_context.require_failCommand_fail_point |
| 262 | + async def test_retryable_reads_are_retried_on_the_same_replica_when_no_others_are_available( |
| 263 | + self |
| 264 | + ): |
| 265 | + fail_command = { |
| 266 | + "configureFailPoint": "failCommand", |
| 267 | + "mode": {"times": 1}, |
| 268 | + "data": {"failCommands": ["find"], "errorCode": 6}, |
| 269 | + } |
| 270 | + |
| 271 | + node_client = await self.async_rs_or_single_client(*list(async_client_context.nodes)[0]) |
| 272 | + await async_set_fail_point(node_client, fail_command) |
| 273 | + |
| 274 | + listener = OvertCommandListener() |
| 275 | + client = await self.async_rs_or_single_client( |
| 276 | + event_listeners=[listener], |
| 277 | + retryReads=True, |
| 278 | + ) |
| 279 | + |
| 280 | + await client.t.t.find_one({}) |
| 281 | + |
| 282 | + # Disable failpoints |
| 283 | + fail_command["mode"] = "off" |
| 284 | + await async_set_fail_point(node_client, fail_command) |
| 285 | + |
| 286 | + self.assertEqual(len(listener.failed_events), 1) |
| 287 | + self.assertEqual(len(listener.succeeded_events), 1) |
| 288 | + |
| 289 | + # Assert that both events occurred on the same node. |
| 290 | + assert listener.succeeded_events[0].connection_id == listener.failed_events[0].connection_id |
| 291 | + |
221 | 292 | @async_client_context.require_failCommand_fail_point |
222 | 293 | async def test_retryable_reads_are_retried_on_the_same_implicit_session(self): |
223 | 294 | listener = OvertCommandListener() |
|
0 commit comments