Skip to content

Commit 979208b

Browse files
committed
PYTHON-2390 - Retryable reads use the same implicit session
1 parent dba0aa9 commit 979208b

File tree

4 files changed

+88
-22
lines changed

4 files changed

+88
-22
lines changed

pymongo/asynchronous/mongo_client.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2048,17 +2048,18 @@ async def _retryable_read(
20482048
retryable = bool(
20492049
retryable and self.options.retry_reads and not (session and session.in_transaction)
20502050
)
2051-
return await self._retry_internal(
2052-
func,
2053-
session,
2054-
None,
2055-
operation,
2056-
is_read=True,
2057-
address=address,
2058-
read_pref=read_pref,
2059-
retryable=retryable,
2060-
operation_id=operation_id,
2061-
)
2051+
async with self._tmp_session(session) as s:
2052+
return await self._retry_internal(
2053+
func,
2054+
s,
2055+
None,
2056+
operation,
2057+
is_read=True,
2058+
address=address,
2059+
read_pref=read_pref,
2060+
retryable=retryable,
2061+
operation_id=operation_id,
2062+
)
20622063

20632064
async def _retryable_write(
20642065
self,

pymongo/synchronous/mongo_client.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2044,17 +2044,18 @@ def _retryable_read(
20442044
retryable = bool(
20452045
retryable and self.options.retry_reads and not (session and session.in_transaction)
20462046
)
2047-
return self._retry_internal(
2048-
func,
2049-
session,
2050-
None,
2051-
operation,
2052-
is_read=True,
2053-
address=address,
2054-
read_pref=read_pref,
2055-
retryable=retryable,
2056-
operation_id=operation_id,
2057-
)
2047+
with self._tmp_session(session) as s:
2048+
return self._retry_internal(
2049+
func,
2050+
s,
2051+
None,
2052+
operation,
2053+
is_read=True,
2054+
address=address,
2055+
read_pref=read_pref,
2056+
retryable=retryable,
2057+
operation_id=operation_id,
2058+
)
20582059

20592060
def _retryable_write(
20602061
self,

test/asynchronous/test_retryable_reads.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,38 @@ async def test_retryable_reads_are_retried_on_the_same_mongos_when_no_others_are
218218
# Assert that both events occurred on the same mongos.
219219
assert listener.succeeded_events[0].connection_id == listener.failed_events[0].connection_id
220220

221+
@async_client_context.require_failCommand_fail_point
222+
async def test_retryable_reads_are_retried_on_the_same_implicit_session(self):
223+
fail_command = {
224+
"configureFailPoint": "failCommand",
225+
"mode": {"times": 1},
226+
"data": {"failCommands": ["count"], "errorCode": 6},
227+
}
228+
229+
listener = OvertCommandListener()
230+
client = await self.async_rs_or_single_client(
231+
directConnection=False,
232+
event_listeners=[listener],
233+
retryReads=True,
234+
)
235+
236+
await async_set_fail_point(client, fail_command)
237+
238+
await client.t.t.estimated_document_count()
239+
240+
# Disable failpoint.
241+
fail_command["mode"] = "off"
242+
await async_set_fail_point(client, fail_command)
243+
244+
# Assert that both events occurred on the same session.
245+
lsids = [
246+
event.command["lsid"]
247+
for event in listener.started_events
248+
if event.command_name == "count"
249+
]
250+
self.assertEqual(len(lsids), 2)
251+
self.assertEqual(lsids[0], lsids[1])
252+
221253

222254
if __name__ == "__main__":
223255
unittest.main()

test/test_retryable_reads.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,38 @@ def test_retryable_reads_are_retried_on_the_same_mongos_when_no_others_are_avail
216216
# Assert that both events occurred on the same mongos.
217217
assert listener.succeeded_events[0].connection_id == listener.failed_events[0].connection_id
218218

219+
@client_context.require_failCommand_fail_point
220+
def test_retryable_reads_are_retried_on_the_same_implicit_session(self):
221+
fail_command = {
222+
"configureFailPoint": "failCommand",
223+
"mode": {"times": 1},
224+
"data": {"failCommands": ["count"], "errorCode": 6},
225+
}
226+
227+
listener = OvertCommandListener()
228+
client = self.rs_or_single_client(
229+
directConnection=False,
230+
event_listeners=[listener],
231+
retryReads=True,
232+
)
233+
234+
set_fail_point(client, fail_command)
235+
236+
client.t.t.estimated_document_count()
237+
238+
# Disable failpoint.
239+
fail_command["mode"] = "off"
240+
set_fail_point(client, fail_command)
241+
242+
# Assert that both events occurred on the same session.
243+
lsids = [
244+
event.command["lsid"]
245+
for event in listener.started_events
246+
if event.command_name == "count"
247+
]
248+
self.assertEqual(len(lsids), 2)
249+
self.assertEqual(lsids[0], lsids[1])
250+
219251

220252
if __name__ == "__main__":
221253
unittest.main()

0 commit comments

Comments
 (0)