Skip to content

Commit 2818a32

Browse files
authored
PYTHON-2392 Implicit sessions should always be discarded after connection errors (#498)
PYTHON-2075 Add more sessions tests with more read and write commands
1 parent d3e66a6 commit 2818a32

File tree

2 files changed

+324
-8
lines changed

2 files changed

+324
-8
lines changed

pymongo/mongo_client.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1827,17 +1827,20 @@ def _tmp_session(self, session, close=True):
18271827
return
18281828

18291829
s = self._ensure_session(session)
1830-
if s and close:
1831-
with s:
1832-
# Call end_session when we exit this scope.
1833-
yield s
1834-
elif s:
1830+
if s:
18351831
try:
1836-
# Only call end_session on error.
18371832
yield s
1838-
except Exception:
1833+
except Exception as exc:
1834+
if isinstance(exc, ConnectionFailure):
1835+
s._server_session.mark_dirty()
1836+
1837+
# Always call end_session on error.
18391838
s.end_session()
18401839
raise
1840+
finally:
1841+
# Call end_session when we exit this scope.
1842+
if close:
1843+
s.end_session()
18411844
else:
18421845
yield None
18431846

test/sessions/dirty-session-errors.json

Lines changed: 314 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,149 @@
192192
}
193193
}
194194
},
195+
{
196+
"description": "Dirty explicit session is discarded (non-bulk write)",
197+
"clientOptions": {
198+
"retryWrites": true
199+
},
200+
"failPoint": {
201+
"configureFailPoint": "failCommand",
202+
"mode": {
203+
"times": 1
204+
},
205+
"data": {
206+
"failCommands": [
207+
"findAndModify"
208+
],
209+
"closeConnection": true
210+
}
211+
},
212+
"operations": [
213+
{
214+
"name": "assertSessionNotDirty",
215+
"object": "testRunner",
216+
"arguments": {
217+
"session": "session0"
218+
}
219+
},
220+
{
221+
"name": "findOneAndUpdate",
222+
"object": "collection",
223+
"arguments": {
224+
"session": "session0",
225+
"filter": {
226+
"_id": 1
227+
},
228+
"update": {
229+
"$inc": {
230+
"x": 1
231+
}
232+
},
233+
"returnDocument": "Before"
234+
},
235+
"result": {
236+
"_id": 1
237+
}
238+
},
239+
{
240+
"name": "assertSessionDirty",
241+
"object": "testRunner",
242+
"arguments": {
243+
"session": "session0"
244+
}
245+
},
246+
{
247+
"name": "endSession",
248+
"object": "session0"
249+
},
250+
{
251+
"name": "find",
252+
"object": "collection",
253+
"arguments": {
254+
"filter": {
255+
"_id": -1
256+
}
257+
},
258+
"result": []
259+
},
260+
{
261+
"name": "assertDifferentLsidOnLastTwoCommands",
262+
"object": "testRunner"
263+
}
264+
],
265+
"expectations": [
266+
{
267+
"command_started_event": {
268+
"command": {
269+
"findAndModify": "test",
270+
"query": {
271+
"_id": 1
272+
},
273+
"update": {
274+
"$inc": {
275+
"x": 1
276+
}
277+
},
278+
"new": false,
279+
"lsid": "session0",
280+
"txnNumber": {
281+
"$numberLong": "1"
282+
},
283+
"readConcern": null,
284+
"writeConcern": null
285+
},
286+
"command_name": "findAndModify",
287+
"database_name": "session-tests"
288+
}
289+
},
290+
{
291+
"command_started_event": {
292+
"command": {
293+
"findAndModify": "test",
294+
"query": {
295+
"_id": 1
296+
},
297+
"update": {
298+
"$inc": {
299+
"x": 1
300+
}
301+
},
302+
"new": false,
303+
"lsid": "session0",
304+
"txnNumber": {
305+
"$numberLong": "1"
306+
},
307+
"readConcern": null,
308+
"writeConcern": null
309+
},
310+
"command_name": "findAndModify",
311+
"database_name": "session-tests"
312+
}
313+
},
314+
{
315+
"command_started_event": {
316+
"command": {
317+
"find": "test",
318+
"filter": {
319+
"_id": -1
320+
}
321+
},
322+
"command_name": "find",
323+
"database_name": "session-tests"
324+
}
325+
}
326+
],
327+
"outcome": {
328+
"collection": {
329+
"data": [
330+
{
331+
"_id": 1,
332+
"x": 1
333+
}
334+
]
335+
}
336+
}
337+
},
195338
{
196339
"description": "Dirty implicit session is discarded (write)",
197340
"clientOptions": {
@@ -300,6 +443,128 @@
300443
}
301444
}
302445
},
446+
{
447+
"description": "Dirty implicit session is discarded (non-bulk write)",
448+
"clientOptions": {
449+
"retryWrites": true
450+
},
451+
"failPoint": {
452+
"configureFailPoint": "failCommand",
453+
"mode": {
454+
"times": 1
455+
},
456+
"data": {
457+
"failCommands": [
458+
"findAndModify"
459+
],
460+
"closeConnection": true
461+
}
462+
},
463+
"operations": [
464+
{
465+
"name": "findOneAndUpdate",
466+
"object": "collection",
467+
"arguments": {
468+
"filter": {
469+
"_id": 1
470+
},
471+
"update": {
472+
"$inc": {
473+
"x": 1
474+
}
475+
},
476+
"returnDocument": "Before"
477+
},
478+
"result": {
479+
"_id": 1
480+
}
481+
},
482+
{
483+
"name": "find",
484+
"object": "collection",
485+
"arguments": {
486+
"filter": {
487+
"_id": -1
488+
}
489+
},
490+
"result": []
491+
},
492+
{
493+
"name": "assertDifferentLsidOnLastTwoCommands",
494+
"object": "testRunner"
495+
}
496+
],
497+
"expectations": [
498+
{
499+
"command_started_event": {
500+
"command": {
501+
"findAndModify": "test",
502+
"query": {
503+
"_id": 1
504+
},
505+
"update": {
506+
"$inc": {
507+
"x": 1
508+
}
509+
},
510+
"new": false,
511+
"txnNumber": {
512+
"$numberLong": "1"
513+
},
514+
"readConcern": null,
515+
"writeConcern": null
516+
},
517+
"command_name": "findAndModify",
518+
"database_name": "session-tests"
519+
}
520+
},
521+
{
522+
"command_started_event": {
523+
"command": {
524+
"findAndModify": "test",
525+
"query": {
526+
"_id": 1
527+
},
528+
"update": {
529+
"$inc": {
530+
"x": 1
531+
}
532+
},
533+
"new": false,
534+
"txnNumber": {
535+
"$numberLong": "1"
536+
},
537+
"readConcern": null,
538+
"writeConcern": null
539+
},
540+
"command_name": "findAndModify",
541+
"database_name": "session-tests"
542+
}
543+
},
544+
{
545+
"command_started_event": {
546+
"command": {
547+
"find": "test",
548+
"filter": {
549+
"_id": -1
550+
}
551+
},
552+
"command_name": "find",
553+
"database_name": "session-tests"
554+
}
555+
}
556+
],
557+
"outcome": {
558+
"collection": {
559+
"data": [
560+
{
561+
"_id": 1,
562+
"x": 1
563+
}
564+
]
565+
}
566+
}
567+
},
303568
{
304569
"description": "Dirty implicit session is discarded (read)",
305570
"failPoint": {
@@ -353,6 +618,54 @@
353618
]
354619
}
355620
}
621+
},
622+
{
623+
"description": "Dirty implicit session is discarded (non-cursor returning read)",
624+
"failPoint": {
625+
"configureFailPoint": "failCommand",
626+
"mode": {
627+
"times": 2
628+
},
629+
"data": {
630+
"failCommands": [
631+
"aggregate"
632+
],
633+
"closeConnection": true
634+
}
635+
},
636+
"operations": [
637+
{
638+
"name": "countDocuments",
639+
"object": "collection",
640+
"arguments": {
641+
"filter": {}
642+
},
643+
"error": true
644+
},
645+
{
646+
"name": "find",
647+
"object": "collection",
648+
"arguments": {
649+
"filter": {
650+
"_id": -1
651+
}
652+
},
653+
"result": []
654+
},
655+
{
656+
"name": "assertDifferentLsidOnLastTwoCommands",
657+
"object": "testRunner"
658+
}
659+
],
660+
"outcome": {
661+
"collection": {
662+
"data": [
663+
{
664+
"_id": 1
665+
}
666+
]
667+
}
668+
}
356669
}
357670
]
358-
}
671+
}

0 commit comments

Comments
 (0)