@@ -12,7 +12,7 @@ use self::server::Server;
12
12
use super :: TopologyDescription ;
13
13
use crate :: {
14
14
cmap:: { Command , Connection } ,
15
- error:: Result ,
15
+ error:: { Error , Result } ,
16
16
options:: { ClientOptions , StreamAddress } ,
17
17
sdam:: {
18
18
description:: server:: { ServerDescription , ServerType } ,
@@ -175,6 +175,54 @@ impl Topology {
175
175
}
176
176
}
177
177
178
+ pub ( crate ) fn handle_pre_handshake_error (
179
+ error : Error ,
180
+ address : StreamAddress ,
181
+ topology : Arc < RwLock < Topology > > ,
182
+ ) {
183
+ if error. is_network_error ( ) {
184
+ mark_server_as_unknown ( error, address, topology) ;
185
+ }
186
+ }
187
+
188
+ pub ( crate ) fn handle_post_handshake_error (
189
+ error : Error ,
190
+ conn : Connection ,
191
+ server : Arc < Server > ,
192
+ topology : Arc < RwLock < Topology > > ,
193
+ ) {
194
+ // If we encounter certain errors, we must update the topology as per the
195
+ // SDAM spec.
196
+ if error. is_non_timeout_network_error ( ) {
197
+ mark_server_as_unknown ( error, server. address . clone ( ) , topology) ;
198
+ server. clear_connection_pool ( ) ;
199
+ } else if error. is_recovering ( ) || error. is_not_master ( ) {
200
+ mark_server_as_unknown ( error. clone ( ) , server. address . clone ( ) , topology) ;
201
+
202
+ // For "node is recovering" or "not master" errors, we must request a
203
+ // topology check.
204
+ server. request_topology_check ( ) ;
205
+
206
+ let wire_version = conn
207
+ . stream_description ( )
208
+ . map ( |sd| sd. max_wire_version )
209
+ . ok ( )
210
+ . and_then ( std:: convert:: identity)
211
+ . unwrap_or ( 0 ) ;
212
+
213
+ // in 4.2+, we only clear connection pool if we've received a
214
+ // "node is shutting down" error. Otherwise, we always clear the pool.
215
+ if wire_version < 8 || error. is_shutting_down ( ) {
216
+ server. clear_connection_pool ( ) ;
217
+ }
218
+ }
219
+ }
220
+
221
+ fn mark_server_as_unknown ( error : Error , address : StreamAddress , topology : Arc < RwLock < Topology > > ) {
222
+ let description = ServerDescription :: new ( address, Some ( Err ( error) ) ) ;
223
+ update_topology ( topology, description) ;
224
+ }
225
+
178
226
/// Updates the provided topology in a minimally contentious way by cloning first.
179
227
pub ( crate ) fn update_topology (
180
228
topology : Arc < RwLock < Topology > > ,
0 commit comments