156
156
from bson .int64 import Int64
157
157
from bson .timestamp import Timestamp
158
158
from pymongo import _csot
159
- from pymongo .cursor import _ConnectionManager
160
159
from pymongo .errors import (
161
160
ConfigurationError ,
162
161
ConnectionFailure ,
165
164
PyMongoError ,
166
165
WTimeoutError ,
167
166
)
168
- from pymongo .helpers import _RETRYABLE_ERROR_CODES
167
+ from pymongo .helpers_shared import _RETRYABLE_ERROR_CODES
169
168
from pymongo .operations import _Op
170
169
from pymongo .read_concern import ReadConcern
171
170
from pymongo .read_preferences import ReadPreference , _ServerMode
172
171
from pymongo .server_type import SERVER_TYPE
172
+ from pymongo .synchronous .cursor import _ConnectionManager
173
173
from pymongo .write_concern import WriteConcern
174
174
175
175
if TYPE_CHECKING :
176
176
from types import TracebackType
177
177
178
- from pymongo .pool import Connection
179
- from pymongo .server import Server
178
+ from pymongo .synchronous . pool import Connection
179
+ from pymongo .synchronous . server import Server
180
180
from pymongo .typings import ClusterTime , _Address
181
181
182
+ _IS_SYNC = True
183
+
182
184
183
185
class SessionOptions :
184
186
"""Options for a new :class:`ClientSession`.
@@ -476,7 +478,7 @@ def _within_time_limit(start_time: float) -> bool:
476
478
_T = TypeVar ("_T" )
477
479
478
480
if TYPE_CHECKING :
479
- from pymongo .mongo_client import MongoClient
481
+ from pymongo .synchronous . mongo_client import MongoClient
480
482
481
483
482
484
class ClientSession :
@@ -526,9 +528,15 @@ def _end_session(self, lock: bool) -> None:
526
528
# is in the committed state when the session is discarded.
527
529
self ._unpin ()
528
530
finally :
529
- self ._client ._return_server_session (self ._server_session , lock )
531
+ self ._client ._return_server_session (self ._server_session )
530
532
self ._server_session = None
531
533
534
+ def _end_implicit_session (self ) -> None :
535
+ # Implicit sessions can't be part of transactions or pinned connections
536
+ if self ._server_session is not None :
537
+ self ._client ._return_server_session (self ._server_session )
538
+ self ._server_session = None
539
+
532
540
def _check_ended (self ) -> None :
533
541
if self ._server_session is None :
534
542
raise InvalidOperation ("Cannot use ended session" )
@@ -1097,7 +1105,7 @@ def inc_transaction_id(self) -> None:
1097
1105
class _ServerSessionPool (collections .deque ):
1098
1106
"""Pool of _ServerSession objects.
1099
1107
1100
- This class is not thread-safe, access it while holding the Topology lock .
1108
+ This class is thread-safe.
1101
1109
"""
1102
1110
1103
1111
def __init__ (self , * args : Any , ** kwargs : Any ):
@@ -1110,8 +1118,11 @@ def reset(self) -> None:
1110
1118
1111
1119
def pop_all (self ) -> list [_ServerSession ]:
1112
1120
ids = []
1113
- while self :
1114
- ids .append (self .pop ().session_id )
1121
+ while True :
1122
+ try :
1123
+ ids .append (self .pop ().session_id )
1124
+ except IndexError :
1125
+ break
1115
1126
return ids
1116
1127
1117
1128
def get_server_session (self , session_timeout_minutes : Optional [int ]) -> _ServerSession :
@@ -1123,33 +1134,30 @@ def get_server_session(self, session_timeout_minutes: Optional[int]) -> _ServerS
1123
1134
self ._clear_stale (session_timeout_minutes )
1124
1135
1125
1136
# The most recently used sessions are on the left.
1126
- while self :
1127
- s = self .popleft ()
1137
+ while True :
1138
+ try :
1139
+ s = self .popleft ()
1140
+ except IndexError :
1141
+ break
1128
1142
if not s .timed_out (session_timeout_minutes ):
1129
1143
return s
1130
1144
1131
1145
return _ServerSession (self .generation )
1132
1146
1133
- def return_server_session (
1134
- self , server_session : _ServerSession , session_timeout_minutes : Optional [int ]
1135
- ) -> None :
1136
- if session_timeout_minutes is not None :
1137
- self ._clear_stale (session_timeout_minutes )
1138
- if server_session .timed_out (session_timeout_minutes ):
1139
- return
1140
- self .return_server_session_no_lock (server_session )
1141
-
1142
- def return_server_session_no_lock (self , server_session : _ServerSession ) -> None :
1147
+ def return_server_session (self , server_session : _ServerSession ) -> None :
1143
1148
# Discard sessions from an old pool to avoid duplicate sessions in the
1144
1149
# child process after a fork.
1145
1150
if server_session .generation == self .generation and not server_session .dirty :
1146
1151
self .appendleft (server_session )
1147
1152
1148
1153
def _clear_stale (self , session_timeout_minutes : Optional [int ]) -> None :
1149
1154
# Clear stale sessions. The least recently used are on the right.
1150
- while self :
1151
- if self [- 1 ].timed_out (session_timeout_minutes ):
1152
- self .pop ()
1153
- else :
1155
+ while True :
1156
+ try :
1157
+ s = self .pop ()
1158
+ except IndexError :
1159
+ break
1160
+ if not s .timed_out (session_timeout_minutes ):
1161
+ self .append (s )
1154
1162
# The remaining sessions also haven't timed out.
1155
1163
break
0 commit comments