Skip to content

Commit fc645a2

Browse files
committed
PYTHON-1838 Discard ServerSessions involved in network errors
1 parent b2c5c5f commit fc645a2

File tree

5 files changed

+600
-4
lines changed

5 files changed

+600
-4
lines changed

pymongo/client_session.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -786,6 +786,15 @@ def __init__(self):
786786
self.session_id = {'id': Binary(uuid.uuid4().bytes, 4)}
787787
self.last_use = monotonic.time()
788788
self._transaction_id = 0
789+
self.dirty = False
790+
791+
def mark_dirty(self):
792+
"""Mark this session as dirty.
793+
794+
A server session is marked dirty when a command fails with a network
795+
error. Dirty sessions are later discarded from the server session pool.
796+
"""
797+
self.dirty = True
789798

790799
def timed_out(self, session_timeout_minutes):
791800
idle_seconds = monotonic.time() - self.last_use
@@ -832,10 +841,11 @@ def get_server_session(self, session_timeout_minutes):
832841
def return_server_session(self, server_session, session_timeout_minutes):
833842
self._clear_stale(session_timeout_minutes)
834843
if not server_session.timed_out(session_timeout_minutes):
835-
self.appendleft(server_session)
844+
self.return_server_session_no_lock(server_session)
836845

837846
def return_server_session_no_lock(self, server_session):
838-
self.appendleft(server_session)
847+
if not server_session.dirty:
848+
self.appendleft(server_session)
839849

840850
def _clear_stale(self, session_timeout_minutes):
841851
# Clear stale sessions. The least recently used are on the right.

pymongo/mongo_client.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1312,6 +1312,8 @@ def _reset_on_error(self, server_address, session):
13121312
# Server Discovery And Monitoring Spec: "When an application
13131313
# operation fails because of any network error besides a socket
13141314
# timeout...."
1315+
if session:
1316+
session._server_session.mark_dirty()
13151317
raise
13161318
except NotMasterError:
13171319
# "When the client sees a "not master" error it MUST replace the
@@ -1323,6 +1325,8 @@ def _reset_on_error(self, server_address, session):
13231325
# "Client MUST replace the server's description with type Unknown
13241326
# ... MUST NOT request an immediate check of the server."
13251327
self.__reset_server(server_address)
1328+
if session:
1329+
session._server_session.mark_dirty()
13261330
raise
13271331
except OperationFailure as exc:
13281332
if exc.code in helpers._RETRYABLE_ERROR_CODES:

0 commit comments

Comments
 (0)