Skip to content

Commit d5b4d55

Browse files
committed
feat(NODE-6882): close checked out connection in MongoClient.close()
1 parent 32b3e34 commit d5b4d55

File tree

5 files changed

+84
-5
lines changed

5 files changed

+84
-5
lines changed

src/cmap/connection_pool.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
} from '../constants';
1818
import {
1919
type AnyError,
20+
ConnectionPoolClosedError,
2021
type MongoError,
2122
MongoInvalidArgumentError,
2223
MongoMissingCredentialsError,
@@ -489,6 +490,16 @@ export class ConnectionPool extends TypedEventEmitter<ConnectionPoolEvents> {
489490
}
490491
}
491492

493+
closeCheckedOutConnections() {
494+
for (const conn of this.checkedOut) {
495+
this.emitAndLog(
496+
ConnectionPool.CONNECTION_CLOSED,
497+
new ConnectionClosedEvent(this, conn, 'poolClosed')
498+
);
499+
conn.onError(new ConnectionPoolClosedError());
500+
}
501+
}
502+
492503
/** Close the pool */
493504
close(): void {
494505
if (this.closed) {

src/error.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,6 +1018,62 @@ export class MongoTopologyClosedError extends MongoAPIError {
10181018
}
10191019
}
10201020

1021+
/**
1022+
* An error generated when the MongoClient is closed and async
1023+
* operations are interrupted.
1024+
*
1025+
* @public
1026+
* @category Error
1027+
*/
1028+
export class MongoClientClosedError extends MongoAPIError {
1029+
/**
1030+
* **Do not use this constructor!**
1031+
*
1032+
* Meant for internal use only.
1033+
*
1034+
* @remarks
1035+
* This class is only meant to be constructed within the driver. This constructor is
1036+
* not subject to semantic versioning compatibility guarantees and may change at any time.
1037+
*
1038+
* @public
1039+
**/
1040+
constructor(message = 'MongoClient is closed') {
1041+
super(message);
1042+
}
1043+
1044+
override get name(): string {
1045+
return 'MongoClientClosedError';
1046+
}
1047+
}
1048+
1049+
/**
1050+
* An error generated when a ConnectionPool is closed and async
1051+
* operations are interrupted.
1052+
*
1053+
* @public
1054+
* @category Error
1055+
*/
1056+
export class ConnectionPoolClosedError extends MongoAPIError {
1057+
/**
1058+
* **Do not use this constructor!**
1059+
*
1060+
* Meant for internal use only.
1061+
*
1062+
* @remarks
1063+
* This class is only meant to be constructed within the driver. This constructor is
1064+
* not subject to semantic versioning compatibility guarantees and may change at any time.
1065+
*
1066+
* @public
1067+
**/
1068+
constructor(message = 'ConnectionPool is closed') {
1069+
super(message);
1070+
}
1071+
1072+
override get name(): string {
1073+
return 'ConnectionPoolClosedError';
1074+
}
1075+
}
1076+
10211077
/** @public */
10221078
export interface MongoNetworkErrorOptions {
10231079
/** Indicates the timeout happened before a connection handshake completed */

src/mongo_client.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,8 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
672672
writable: false
673673
});
674674

675+
this.topology?.closeCheckedOutConnections();
676+
675677
const activeCursorCloses = Array.from(this.s.activeCursors, cursor => cursor.close());
676678
this.s.activeCursors.clear();
677679

src/sdam/server.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,8 +246,12 @@ export class Server extends TypedEventEmitter<ServerEvents> {
246246
}
247247
}
248248

249+
closeCheckedOutConnections() {
250+
return this.pool.closeCheckedOutConnections();
251+
}
252+
249253
/** Destroy the server connection */
250-
destroy(): void {
254+
close(): void {
251255
if (this.s.state === STATE_CLOSED) {
252256
return;
253257
}

src/sdam/topology.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -490,14 +490,20 @@ export class Topology extends TypedEventEmitter<TopologyEvents> {
490490
}
491491
}
492492

493+
closeCheckedOutConnections() {
494+
for (const server of this.s.servers.values()) {
495+
return server.closeCheckedOutConnections();
496+
}
497+
}
498+
493499
/** Close this topology */
494500
close(): void {
495501
if (this.s.state === STATE_CLOSED || this.s.state === STATE_CLOSING) {
496502
return;
497503
}
498504

499505
for (const server of this.s.servers.values()) {
500-
destroyServer(server, this);
506+
closeServer(server, this);
501507
}
502508

503509
this.s.servers.clear();
@@ -791,12 +797,12 @@ export class Topology extends TypedEventEmitter<TopologyEvents> {
791797
}
792798

793799
/** Destroys a server, and removes all event listeners from the instance */
794-
function destroyServer(server: Server, topology: Topology) {
800+
function closeServer(server: Server, topology: Topology) {
795801
for (const event of LOCAL_SERVER_EVENTS) {
796802
server.removeAllListeners(event);
797803
}
798804

799-
server.destroy();
805+
server.close();
800806
topology.emitAndLog(
801807
Topology.SERVER_CLOSED,
802808
new ServerClosedEvent(topology.s.id, server.description.address)
@@ -903,7 +909,7 @@ function updateServers(topology: Topology, incomingServerDescription?: ServerDes
903909

904910
// prepare server for garbage collection
905911
if (server) {
906-
destroyServer(server, topology);
912+
closeServer(server, topology);
907913
}
908914
}
909915
}

0 commit comments

Comments
 (0)