@@ -22,12 +22,13 @@ import {
2222import {
2323 type AnyError ,
2424 isNodeShuttingDownError ,
25- isSDAMUnrecoverableError ,
25+ isStateChangeError ,
2626 MONGODB_ERROR_CODES ,
2727 MongoError ,
2828 MongoErrorLabel ,
2929 MongoNetworkError ,
3030 MongoNetworkTimeoutError ,
31+ MongoParseError ,
3132 MongoRuntimeError ,
3233 MongoServerClosedError ,
3334 type MongoServerError ,
@@ -391,9 +392,7 @@ export class Server extends TypedEventEmitter<ServerEvents> {
391392 return ;
392393 }
393394
394- const isStaleError =
395- error . connectionGeneration && error . connectionGeneration < this . pool . generation ;
396- if ( isStaleError ) {
395+ if ( isStaleError ( this , error ) ) {
397396 return ;
398397 }
399398
@@ -402,32 +401,40 @@ export class Server extends TypedEventEmitter<ServerEvents> {
402401 const isNetworkTimeoutBeforeHandshakeError =
403402 error instanceof MongoNetworkError && error . beforeHandshake ;
404403 const isAuthHandshakeError = error . hasErrorLabel ( MongoErrorLabel . HandshakeError ) ;
405- if ( isNetworkNonTimeoutError || isNetworkTimeoutBeforeHandshakeError || isAuthHandshakeError ) {
406- // In load balanced mode we never mark the server as unknown and always
407- // clear for the specific service id.
404+
405+ // Perhaps questionable and divergent from the spec, but considering MongoParseErrors like state change errors was legacy behavior.
406+ if ( isStateChangeError ( error ) || error instanceof MongoParseError ) {
407+ const shouldClearPool = isNodeShuttingDownError ( error ) ;
408+
409+ // from the SDAM spec: The driver MUST synchronize clearing the pool with updating the topology.
410+ // In load balanced mode: there is no monitoring, so there is no topology to update. We simply clear the pool.
411+ // For other topologies: the `ResetPool` label instructs the topology to clear the server's pool in `updateServer()`.
412+ if ( ! this . loadBalanced ) {
413+ if ( shouldClearPool ) {
414+ error . addErrorLabel ( MongoErrorLabel . ResetPool ) ;
415+ }
416+ markServerUnknown ( this , error ) ;
417+ process . nextTick ( ( ) => this . requestCheck ( ) ) ;
418+ return ;
419+ }
420+
421+ if ( connection && shouldClearPool ) {
422+ this . pool . clear ( { serviceId : connection . serviceId } ) ;
423+ }
424+ } else if (
425+ isNetworkNonTimeoutError ||
426+ isNetworkTimeoutBeforeHandshakeError ||
427+ isAuthHandshakeError
428+ ) {
429+ // from the SDAM spec: The driver MUST synchronize clearing the pool with updating the topology.
430+ // In load balanced mode: there is no monitoring, so there is no topology to update. We simply clear the pool.
431+ // For other topologies: the `ResetPool` label instructs the topology to clear the server's pool in `updateServer()`.
408432 if ( ! this . loadBalanced ) {
409433 error . addErrorLabel ( MongoErrorLabel . ResetPool ) ;
410434 markServerUnknown ( this , error ) ;
411435 } else if ( connection ) {
412436 this . pool . clear ( { serviceId : connection . serviceId } ) ;
413437 }
414- } else {
415- if ( isSDAMUnrecoverableError ( error ) ) {
416- if ( shouldHandleStateChangeError ( this , error ) ) {
417- const shouldClearPool = isNodeShuttingDownError ( error ) ;
418- if ( this . loadBalanced && connection && shouldClearPool ) {
419- this . pool . clear ( { serviceId : connection . serviceId } ) ;
420- }
421-
422- if ( ! this . loadBalanced ) {
423- if ( shouldClearPool ) {
424- error . addErrorLabel ( MongoErrorLabel . ResetPool ) ;
425- }
426- markServerUnknown ( this , error ) ;
427- process . nextTick ( ( ) => this . requestCheck ( ) ) ;
428- }
429- }
430- }
431438 }
432439 }
433440
@@ -560,12 +567,6 @@ function connectionIsStale(pool: ConnectionPool, connection: Connection) {
560567 return connection . generation !== pool . generation ;
561568}
562569
563- function shouldHandleStateChangeError ( server : Server , err : MongoError ) {
564- const etv = err . topologyVersion ;
565- const stv = server . description . topologyVersion ;
566- return compareTopologyVersion ( stv , etv ) < 0 ;
567- }
568-
569570function inActiveTransaction ( session : ClientSession | undefined , cmd : Document ) {
570571 return session && session . inTransaction ( ) && ! isTransactionCommand ( cmd ) ;
571572}
@@ -575,3 +576,15 @@ function inActiveTransaction(session: ClientSession | undefined, cmd: Document)
575576function isRetryableWritesEnabled ( topology : Topology ) {
576577 return topology . s . options . retryWrites !== false ;
577578}
579+
580+ function isStaleError ( server : Server , error : MongoError ) : boolean {
581+ const currentGeneration = server . pool . generation ;
582+ const generation = error . connectionGeneration ;
583+
584+ if ( generation && generation < currentGeneration ) {
585+ return true ;
586+ }
587+
588+ const currentTopologyVersion = server . description . topologyVersion ;
589+ return compareTopologyVersion ( currentTopologyVersion , error . topologyVersion ) >= 0 ;
590+ }
0 commit comments