From 58e5214125c8270b665b9979d9504d9151a60758 Mon Sep 17 00:00:00 2001 From: Durran Jordan Date: Tue, 16 Aug 2022 16:58:31 -0400 Subject: [PATCH 1/4] fix(NODE-4516): short circuit end sessions during close --- src/mongo_client.ts | 11 ++++++++++ .../node-specific/mongo_client.test.ts | 21 +++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/src/mongo_client.ts b/src/mongo_client.ts index 45f8a240f9..1a76d0082b 100644 --- a/src/mongo_client.ts +++ b/src/mongo_client.ts @@ -21,6 +21,7 @@ import { PromiseProvider } from './promise_provider'; import type { ReadConcern, ReadConcernLevel, ReadConcernLike } from './read_concern'; import { ReadPreference, ReadPreferenceMode } from './read_preference'; import type { TagSet } from './sdam/server_description'; +import { readPreferenceServerSelector } from './sdam/server_selection'; import type { SrvPoller } from './sdam/srv_polling'; import type { Topology, TopologyEvents } from './sdam/topology'; import { ClientSession, ClientSessionOptions, ServerSessionPool } from './sessions'; @@ -500,6 +501,16 @@ export class MongoClient extends TypedEventEmitter { Promise.all(activeSessionEnds) .then(() => { + // If we would attempt to select a server and get nothing back we short circuit + // to avoid the server selection timeout. + const selector = readPreferenceServerSelector(ReadPreference.primaryPreferred); + const topologyDescription = this.topology.description; + const serverDescriptions = Array.from(topologyDescription.servers.values()); + const servers = selector(topologyDescription, serverDescriptions); + if (servers.length === 0) { + return callback(); + } + const endSessions = Array.from(this.s.sessionPool.sessions, ({ id }) => id); if (endSessions.length === 0) return; return this.db('admin') diff --git a/test/integration/node-specific/mongo_client.test.ts b/test/integration/node-specific/mongo_client.test.ts index f459ae3615..6081af99c6 100644 --- a/test/integration/node-specific/mongo_client.test.ts +++ b/test/integration/node-specific/mongo_client.test.ts @@ -13,6 +13,7 @@ import { } from '../../../src'; import { Connection } from '../../../src/cmap/connection'; import { Db } from '../../../src/db'; +import { ServerDescription } from '../../../src/sdam/server_description'; import { Topology } from '../../../src/sdam/topology'; import { getTopology, isHello } from '../../../src/utils'; import { runLater } from '../../tools/utils'; @@ -649,5 +650,25 @@ describe('class MongoClient', function () { expect(endEvents).to.have.lengthOf(1); expect(endEvents[0]).to.have.property('reply', undefined); // noReponse: true }); + + context('when server selection would return no servers', () => { + const serverDescription = new ServerDescription('a:1'); + + it('short circuits and does not end sessions', async () => { + const session = client.startSession(); // make a session to be ended + await client.db('test').command({ ping: 1 }, { session }); + await session.endSession(); + + const startedEvents: CommandStartedEvent[] = []; + client.on('commandStarted', event => startedEvents.push(event)); + + const servers = new Map(); + servers.set(serverDescription.address, serverDescription); + client.topology.description.servers = servers; + await client.close(); + + expect(startedEvents).to.be.empty; + }); + }); }); }); From 901f0609ef454306ec9a31c6b8f9621b749c28ed Mon Sep 17 00:00:00 2001 From: Durran Jordan Date: Tue, 16 Aug 2022 17:17:15 -0400 Subject: [PATCH 2/4] tet(NODE-4429): check pool size and only return --- src/mongo_client.ts | 2 +- test/integration/node-specific/mongo_client.test.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mongo_client.ts b/src/mongo_client.ts index 1a76d0082b..ee54e60961 100644 --- a/src/mongo_client.ts +++ b/src/mongo_client.ts @@ -508,7 +508,7 @@ export class MongoClient extends TypedEventEmitter { const serverDescriptions = Array.from(topologyDescription.servers.values()); const servers = selector(topologyDescription, serverDescriptions); if (servers.length === 0) { - return callback(); + return; } const endSessions = Array.from(this.s.sessionPool.sessions, ({ id }) => id); diff --git a/test/integration/node-specific/mongo_client.test.ts b/test/integration/node-specific/mongo_client.test.ts index 6081af99c6..e0e005a899 100644 --- a/test/integration/node-specific/mongo_client.test.ts +++ b/test/integration/node-specific/mongo_client.test.ts @@ -668,6 +668,7 @@ describe('class MongoClient', function () { await client.close(); expect(startedEvents).to.be.empty; + expect(client.s.sessionPool.sessions).to.have.lengthOf(1); }); }); }); From c79802b3bc6ee41bffaebd5bcbd148fc678a76e4 Mon Sep 17 00:00:00 2001 From: Durran Jordan Date: Tue, 16 Aug 2022 17:19:11 -0400 Subject: [PATCH 3/4] fix(NODE-4429): dont return and callback --- src/mongo_client.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mongo_client.ts b/src/mongo_client.ts index ee54e60961..8f457cdb5a 100644 --- a/src/mongo_client.ts +++ b/src/mongo_client.ts @@ -522,7 +522,7 @@ export class MongoClient extends TypedEventEmitter { }) .then(() => { if (this.topology == null) { - return callback(); + return; } // clear out references to old topology const topology = this.topology; From 0677840feebf200036902bbacfd532fa5ee2054c Mon Sep 17 00:00:00 2001 From: Durran Jordan Date: Wed, 17 Aug 2022 11:52:37 -0400 Subject: [PATCH 4/4] fix(NODE-4429): check for null topology --- src/mongo_client.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/mongo_client.ts b/src/mongo_client.ts index 8f457cdb5a..d980f3e792 100644 --- a/src/mongo_client.ts +++ b/src/mongo_client.ts @@ -501,6 +501,9 @@ export class MongoClient extends TypedEventEmitter { Promise.all(activeSessionEnds) .then(() => { + if (this.topology == null) { + return; + } // If we would attempt to select a server and get nothing back we short circuit // to avoid the server selection timeout. const selector = readPreferenceServerSelector(ReadPreference.primaryPreferred);