Skip to content

Commit f20cc0a

Browse files
committed
add final test
1 parent c70b66c commit f20cc0a

File tree

5 files changed

+230
-6
lines changed

5 files changed

+230
-6
lines changed

pymongo/asynchronous/pool.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -847,11 +847,14 @@ async def _reset(
847847
pause: bool = True,
848848
service_id: Optional[ObjectId] = None,
849849
interrupt_connections: bool = False,
850+
from_server_description: bool = False,
850851
) -> None:
851852
old_state = self.state
852853
async with self.size_cond:
853854
if self.closed:
854855
return
856+
if from_server_description and self.state == PoolState.BACKOFF:
857+
return
855858
# Clear the backoff amount.
856859
self._backoff = 0
857860
if self.opts.pause_enabled and pause and not self.opts.load_balanced:
@@ -951,10 +954,16 @@ async def update_is_writable(self, is_writable: Optional[bool]) -> None:
951954
_socket.update_is_writable(self.is_writable) # type: ignore[arg-type]
952955

953956
async def reset(
954-
self, service_id: Optional[ObjectId] = None, interrupt_connections: bool = False
957+
self,
958+
service_id: Optional[ObjectId] = None,
959+
interrupt_connections: bool = False,
960+
from_server_description: bool = False,
955961
) -> None:
956962
await self._reset(
957-
close=False, service_id=service_id, interrupt_connections=interrupt_connections
963+
close=False,
964+
service_id=service_id,
965+
interrupt_connections=interrupt_connections,
966+
from_server_description=from_server_description,
958967
)
959968

960969
async def reset_without_pause(self) -> None:

pymongo/asynchronous/topology.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,9 @@ async def on_change(
555555
if reset_pool:
556556
server = self._servers.get(server_description.address)
557557
if server:
558-
await server.pool.reset(interrupt_connections=interrupt_connections)
558+
await server.pool.reset(
559+
interrupt_connections=interrupt_connections, from_server_description=True
560+
)
559561

560562
async def _process_srv_update(self, seedlist: list[tuple[str, Any]]) -> None:
561563
"""Process a new seedlist on an opened topology.

pymongo/synchronous/pool.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -845,11 +845,14 @@ def _reset(
845845
pause: bool = True,
846846
service_id: Optional[ObjectId] = None,
847847
interrupt_connections: bool = False,
848+
from_server_description: bool = False,
848849
) -> None:
849850
old_state = self.state
850851
with self.size_cond:
851852
if self.closed:
852853
return
854+
if from_server_description and self.state == PoolState.BACKOFF:
855+
return
853856
# Clear the backoff amount.
854857
self._backoff = 0
855858
if self.opts.pause_enabled and pause and not self.opts.load_balanced:
@@ -949,9 +952,17 @@ def update_is_writable(self, is_writable: Optional[bool]) -> None:
949952
_socket.update_is_writable(self.is_writable) # type: ignore[arg-type]
950953

951954
def reset(
952-
self, service_id: Optional[ObjectId] = None, interrupt_connections: bool = False
955+
self,
956+
service_id: Optional[ObjectId] = None,
957+
interrupt_connections: bool = False,
958+
from_server_description: bool = False,
953959
) -> None:
954-
self._reset(close=False, service_id=service_id, interrupt_connections=interrupt_connections)
960+
self._reset(
961+
close=False,
962+
service_id=service_id,
963+
interrupt_connections=interrupt_connections,
964+
from_server_description=from_server_description,
965+
)
955966

956967
def reset_without_pause(self) -> None:
957968
self._reset(close=False, pause=False)

pymongo/synchronous/topology.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,9 @@ def on_change(
555555
if reset_pool:
556556
server = self._servers.get(server_description.address)
557557
if server:
558-
server.pool.reset(interrupt_connections=interrupt_connections)
558+
server.pool.reset(
559+
interrupt_connections=interrupt_connections, from_server_description=True
560+
)
559561

560562
def _process_srv_update(self, seedlist: list[tuple[str, Any]]) -> None:
561563
"""Process a new seedlist on an opened topology.
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
{
2+
"description": "heartbeat-failure-does-not-clear-backoff-pool",
3+
"schemaVersion": "1.4",
4+
"runOnRequirements": [
5+
{
6+
"minServerVersion": "4.4",
7+
"serverless": "forbid",
8+
"topologies": [
9+
"single",
10+
"replicaset",
11+
"sharded"
12+
]
13+
}
14+
],
15+
"createEntities": [
16+
{
17+
"client": {
18+
"id": "setupClient",
19+
"useMultipleMongoses": false
20+
}
21+
}
22+
],
23+
"initialData": [
24+
{
25+
"collectionName": "heartbeat-backoff-error",
26+
"databaseName": "sdam-tests",
27+
"documents": [
28+
{
29+
"_id": 1
30+
},
31+
{
32+
"_id": 2
33+
}
34+
]
35+
}
36+
],
37+
"tests": [
38+
{
39+
"description": "A heartbeat failure during backoff should not clear the pool",
40+
"operations": [
41+
{
42+
"name": "failPoint",
43+
"object": "testRunner",
44+
"arguments": {
45+
"client": "setupClient",
46+
"failPoint": {
47+
"configureFailPoint": "failCommand",
48+
"mode": "alwaysOn",
49+
"data": {
50+
"failCommands": [
51+
"saslContinue"
52+
],
53+
"appName": "heartbeatBackoffFailTest",
54+
"closeConnection": true
55+
}
56+
}
57+
}
58+
},
59+
{
60+
"name": "createEntities",
61+
"object": "testRunner",
62+
"arguments": {
63+
"entities": [
64+
{
65+
"client": {
66+
"id": "client",
67+
"useMultipleMongoses": false,
68+
"observeEvents": [
69+
"commandStartedEvent",
70+
"poolBackoffEvent",
71+
"poolReadyEvent",
72+
"poolClearedEvent",
73+
"serverHeartbeatFailedEvent",
74+
"serverHeartbeatSucceededEvent"
75+
],
76+
"uriOptions": {
77+
"retryWrites": false,
78+
"appname": "heartbeatBackoffFailTest"
79+
}
80+
}
81+
},
82+
{
83+
"database": {
84+
"id": "database",
85+
"client": "client",
86+
"databaseName": "sdam-tests"
87+
}
88+
},
89+
{
90+
"collection": {
91+
"id": "collection",
92+
"database": "database",
93+
"collectionName": "heartbeat-backoff-error"
94+
}
95+
}
96+
]
97+
}
98+
},
99+
{
100+
"name": "insertMany",
101+
"object": "collection",
102+
"arguments": {
103+
"documents": [
104+
{
105+
"_id": 3
106+
},
107+
{
108+
"_id": 4
109+
}
110+
]
111+
},
112+
"expectError": {
113+
"isError": true
114+
}
115+
},
116+
{
117+
"name": "failPoint",
118+
"object": "testRunner",
119+
"arguments": {
120+
"client": "setupClient",
121+
"failPoint": {
122+
"configureFailPoint": "failCommand",
123+
"mode": "alwaysOn",
124+
"data": {
125+
"failCommands": [
126+
"isMaster",
127+
"hello"
128+
],
129+
"appName": "heartbeatBackoffFailTest",
130+
"closeConnection": true
131+
}
132+
}
133+
}
134+
},
135+
{
136+
"name": "waitForEvent",
137+
"object": "testRunner",
138+
"arguments": {
139+
"client": "client",
140+
"event": {
141+
"serverHeartbeatFailedEvent": {}
142+
},
143+
"count": 1
144+
}
145+
},
146+
{
147+
"name": "failPoint",
148+
"object": "testRunner",
149+
"arguments": {
150+
"client": "setupClient",
151+
"failPoint": {
152+
"configureFailPoint": "failCommand",
153+
"mode": "off"
154+
}
155+
}
156+
},
157+
{
158+
"name": "waitForEvent",
159+
"object": "testRunner",
160+
"arguments": {
161+
"client": "client",
162+
"event": {
163+
"serverHeartbeatSucceededEvent": {}
164+
},
165+
"count": 1
166+
}
167+
}
168+
],
169+
"expectEvents": [
170+
{
171+
"client": "client",
172+
"eventType": "cmap",
173+
"events": [
174+
{
175+
"poolReadyEvent": {}
176+
},
177+
{
178+
"poolBackoffEvent": {}
179+
},
180+
{
181+
"poolBackoffEvent": {}
182+
},
183+
{
184+
"poolBackoffEvent": {}
185+
},
186+
{
187+
"poolBackoffEvent": {}
188+
},
189+
{
190+
"poolBackoffEvent": {}
191+
},
192+
{
193+
"poolBackoffEvent": {}
194+
}
195+
]
196+
}
197+
]
198+
}
199+
]
200+
}

0 commit comments

Comments
 (0)