Skip to content

Commit 57305e0

Browse files
committed
PYTHON-4747 Sync client_session.py to master
1 parent 4436b1c commit 57305e0

File tree

2 files changed

+55
-25
lines changed

2 files changed

+55
-25
lines changed

pymongo/client_session.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Copyright 2024-present MongoDB, Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""Re-import of synchronous ClientSession API for compatibility."""
16+
from __future__ import annotations
17+
18+
from pymongo.synchronous.client_session import * # noqa: F403
19+
from pymongo.synchronous.client_session import __doc__ as original_doc
20+
21+
__doc__ = original_doc
22+
__all__ = ["ClientSession", "SessionOptions", "TransactionOptions"] # noqa: F405

pymongo/synchronous/client_session.py

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,6 @@
156156
from bson.int64 import Int64
157157
from bson.timestamp import Timestamp
158158
from pymongo import _csot
159-
from pymongo.cursor import _ConnectionManager
160159
from pymongo.errors import (
161160
ConfigurationError,
162161
ConnectionFailure,
@@ -165,20 +164,23 @@
165164
PyMongoError,
166165
WTimeoutError,
167166
)
168-
from pymongo.helpers import _RETRYABLE_ERROR_CODES
167+
from pymongo.helpers_shared import _RETRYABLE_ERROR_CODES
169168
from pymongo.operations import _Op
170169
from pymongo.read_concern import ReadConcern
171170
from pymongo.read_preferences import ReadPreference, _ServerMode
172171
from pymongo.server_type import SERVER_TYPE
172+
from pymongo.synchronous.cursor import _ConnectionManager
173173
from pymongo.write_concern import WriteConcern
174174

175175
if TYPE_CHECKING:
176176
from types import TracebackType
177177

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
180180
from pymongo.typings import ClusterTime, _Address
181181

182+
_IS_SYNC = True
183+
182184

183185
class SessionOptions:
184186
"""Options for a new :class:`ClientSession`.
@@ -476,7 +478,7 @@ def _within_time_limit(start_time: float) -> bool:
476478
_T = TypeVar("_T")
477479

478480
if TYPE_CHECKING:
479-
from pymongo.mongo_client import MongoClient
481+
from pymongo.synchronous.mongo_client import MongoClient
480482

481483

482484
class ClientSession:
@@ -526,9 +528,15 @@ def _end_session(self, lock: bool) -> None:
526528
# is in the committed state when the session is discarded.
527529
self._unpin()
528530
finally:
529-
self._client._return_server_session(self._server_session, lock)
531+
self._client._return_server_session(self._server_session)
530532
self._server_session = None
531533

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+
532540
def _check_ended(self) -> None:
533541
if self._server_session is None:
534542
raise InvalidOperation("Cannot use ended session")
@@ -1097,7 +1105,7 @@ def inc_transaction_id(self) -> None:
10971105
class _ServerSessionPool(collections.deque):
10981106
"""Pool of _ServerSession objects.
10991107
1100-
This class is not thread-safe, access it while holding the Topology lock.
1108+
This class is thread-safe.
11011109
"""
11021110

11031111
def __init__(self, *args: Any, **kwargs: Any):
@@ -1110,8 +1118,11 @@ def reset(self) -> None:
11101118

11111119
def pop_all(self) -> list[_ServerSession]:
11121120
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
11151126
return ids
11161127

11171128
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
11231134
self._clear_stale(session_timeout_minutes)
11241135

11251136
# 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
11281142
if not s.timed_out(session_timeout_minutes):
11291143
return s
11301144

11311145
return _ServerSession(self.generation)
11321146

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:
11431148
# Discard sessions from an old pool to avoid duplicate sessions in the
11441149
# child process after a fork.
11451150
if server_session.generation == self.generation and not server_session.dirty:
11461151
self.appendleft(server_session)
11471152

11481153
def _clear_stale(self, session_timeout_minutes: Optional[int]) -> None:
11491154
# 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)
11541162
# The remaining sessions also haven't timed out.
11551163
break

0 commit comments

Comments
 (0)