Skip to content

Commit 5086ead

Browse files
authored
fix(NODE-4429): select server sync for endSessions during close (#3363)
1 parent f28ba0d commit 5086ead

File tree

2 files changed

+37
-1
lines changed

2 files changed

+37
-1
lines changed

src/mongo_client.ts

+15-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { PromiseProvider } from './promise_provider';
2121
import type { ReadConcern, ReadConcernLevel, ReadConcernLike } from './read_concern';
2222
import { ReadPreference, ReadPreferenceMode } from './read_preference';
2323
import type { TagSet } from './sdam/server_description';
24+
import { readPreferenceServerSelector } from './sdam/server_selection';
2425
import type { SrvPoller } from './sdam/srv_polling';
2526
import type { Topology, TopologyEvents } from './sdam/topology';
2627
import { ClientSession, ClientSessionOptions, ServerSessionPool } from './sessions';
@@ -500,6 +501,19 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> {
500501

501502
Promise.all(activeSessionEnds)
502503
.then(() => {
504+
if (this.topology == null) {
505+
return;
506+
}
507+
// If we would attempt to select a server and get nothing back we short circuit
508+
// to avoid the server selection timeout.
509+
const selector = readPreferenceServerSelector(ReadPreference.primaryPreferred);
510+
const topologyDescription = this.topology.description;
511+
const serverDescriptions = Array.from(topologyDescription.servers.values());
512+
const servers = selector(topologyDescription, serverDescriptions);
513+
if (servers.length === 0) {
514+
return;
515+
}
516+
503517
const endSessions = Array.from(this.s.sessionPool.sessions, ({ id }) => id);
504518
if (endSessions.length === 0) return;
505519
return this.db('admin')
@@ -511,7 +525,7 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> {
511525
})
512526
.then(() => {
513527
if (this.topology == null) {
514-
return callback();
528+
return;
515529
}
516530
// clear out references to old topology
517531
const topology = this.topology;

test/integration/node-specific/mongo_client.test.ts

+22
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
} from '../../../src';
1414
import { Connection } from '../../../src/cmap/connection';
1515
import { Db } from '../../../src/db';
16+
import { ServerDescription } from '../../../src/sdam/server_description';
1617
import { Topology } from '../../../src/sdam/topology';
1718
import { getTopology, isHello } from '../../../src/utils';
1819
import { runLater } from '../../tools/utils';
@@ -649,5 +650,26 @@ describe('class MongoClient', function () {
649650
expect(endEvents).to.have.lengthOf(1);
650651
expect(endEvents[0]).to.have.property('reply', undefined); // noReponse: true
651652
});
653+
654+
context('when server selection would return no servers', () => {
655+
const serverDescription = new ServerDescription('a:1');
656+
657+
it('short circuits and does not end sessions', async () => {
658+
const session = client.startSession(); // make a session to be ended
659+
await client.db('test').command({ ping: 1 }, { session });
660+
await session.endSession();
661+
662+
const startedEvents: CommandStartedEvent[] = [];
663+
client.on('commandStarted', event => startedEvents.push(event));
664+
665+
const servers = new Map<string, ServerDescription>();
666+
servers.set(serverDescription.address, serverDescription);
667+
client.topology.description.servers = servers;
668+
await client.close();
669+
670+
expect(startedEvents).to.be.empty;
671+
expect(client.s.sessionPool.sessions).to.have.lengthOf(1);
672+
});
673+
});
652674
});
653675
});

0 commit comments

Comments
 (0)