Skip to content

Commit 5a7cd7f

Browse files
requested change (simpler)
1 parent a79ed0a commit 5a7cd7f

File tree

3 files changed

+63
-72
lines changed

3 files changed

+63
-72
lines changed

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

Lines changed: 45 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -135,24 +135,25 @@ describe.skip('MongoClient.close() Integration', () => {
135135
'monitor interval timer is cleaned up by client.close()',
136136
metadata,
137137
async function () {
138-
const run = async function ({ MongoClient, uri, expect, sleep, getTimerCount }) {
138+
const run = async function ({ MongoClient, uri, expect, getTimerCount }) {
139139
const heartbeatFrequencyMS = 2000;
140140
const client = new MongoClient(uri, { heartbeatFrequencyMS });
141-
let heartbeatHappened = false;
142-
client.on('serverHeartbeatSucceeded', () => (heartbeatHappened = true));
141+
const heartbeatPromise = client.once('serverHeartbeatSucceeded');
143142
await client.connect();
144-
await sleep(heartbeatFrequencyMS * 2.5);
145-
expect(heartbeatHappened).to.be.true;
143+
await heartbeatPromise;
146144

147-
function getMonitorTimer(servers) {
148-
for (const server of servers) {
149-
return server[1]?.monitor.monitorId.timerId;
145+
function monitorTimersExist(servers) {
146+
for (const [, server] of servers) {
147+
if (server?.monitor.monitorId.timerId === undefined) {
148+
return false;
149+
}
150150
}
151+
return true;
151152
}
152153
const servers = client.topology.s.servers;
153-
expect(getMonitorTimer(servers)).to.exist;
154+
expect(monitorTimersExist(servers)).to.be.true;
154155
await client.close();
155-
expect(getMonitorTimer(servers)).to.not.exist;
156+
expect(monitorTimersExist(servers)).to.be.true;
156157

157158
expect(getTimerCount()).to.equal(0);
158159
};
@@ -166,19 +167,16 @@ describe.skip('MongoClient.close() Integration', () => {
166167
'the new monitor interval timer is cleaned up by client.close()',
167168
metadata,
168169
async () => {
169-
/* eslint-disable-next-line @typescript-eslint/no-unused-vars */
170-
const run = async function ({ MongoClient, uri, expect, sleep, getTimerCount }) {
170+
const run = async function ({ MongoClient, expect, getTimerCount }) {
171171
const heartbeatFrequencyMS = 2000;
172172
const client = new MongoClient('mongodb://fakeUri', { heartbeatFrequencyMS });
173-
let heartbeatHappened = false;
174-
client.on('serverHeartbeatFailed', () => (heartbeatHappened = true));
173+
const heartbeatPromise = client.once('serverHeartbeatFailed');
175174
client.connect();
176-
await sleep(heartbeatFrequencyMS * 2.5);
177-
expect(heartbeatHappened).to.be.true;
175+
await heartbeatPromise;
178176

179177
function getMonitorTimer(servers) {
180-
for (const server of servers) {
181-
return server[1]?.monitor.monitorId.timerId;
178+
for (const [, server] of servers) {
179+
return server?.monitor.monitorId.timerId;
182180
}
183181
}
184182
const servers = client.topology.s.servers;
@@ -195,33 +193,26 @@ describe.skip('MongoClient.close() Integration', () => {
195193
});
196194
});
197195

198-
describe('Connection Monitoring', () => {
196+
describe('Monitoring Connection', () => {
199197
describe('Node.js resource: Socket', () => {
200198
it('no sockets remain after client.close()', metadata, async function () {
201-
const run = async function ({ MongoClient, uri, expect }) {
199+
const run = async function ({ MongoClient, uri, expect, getSocketEndpoints }) {
202200
const client = new MongoClient(uri);
203201
await client.connect();
204202

205-
// returns all active tcp endpoints
206-
const connectionMonitoringReport = () =>
207-
process.report
208-
.getReport()
209-
.libuv.filter(r => r.type === 'tcp')
210-
.map(r => r.remoteEndpoint);
211-
212203
const servers = client.topology?.s.servers;
213204
// assert socket creation
214-
for (const server of servers) {
215-
const { host, port } = server[1].s.description.hostAddress;
216-
expect(connectionMonitoringReport()).to.deep.include({ host, port });
205+
for (const [, server] of servers) {
206+
const { host, port } = server.s.description.hostAddress;
207+
expect(getSocketEndpoints()).to.deep.include({ host, port });
217208
}
218209

219210
await client.close();
220211

221212
// assert socket destruction
222-
for (const server of servers) {
223-
const { host, port } = server[1].s.description.hostAddress;
224-
expect(connectionMonitoringReport()).to.not.deep.include({ host, port });
213+
for (const [, server] of servers) {
214+
const { host, port } = server.s.description.hostAddress;
215+
expect(getSocketEndpoints()).to.not.deep.include({ host, port });
225216
}
226217
};
227218
await runScriptAndGetProcessInfo('socket-connection-monitoring', config, run);
@@ -236,22 +227,18 @@ describe.skip('MongoClient.close() Integration', () => {
236227
'the rtt pinger timer is cleaned up by client.close()',
237228
metadata,
238229
async function () {
239-
const run = async function ({ MongoClient, uri, expect, sleep, getTimerCount }) {
230+
const run = async function ({ MongoClient, uri, expect, getTimerCount }) {
240231
const heartbeatFrequencyMS = 2000;
241232
const client = new MongoClient(uri, {
242233
serverMonitoringMode: 'stream',
243234
heartbeatFrequencyMS
244235
});
245236
await client.connect();
246-
247-
let heartbeatHappened = false;
248-
client.on('serverHeartbeatSucceeded', () => (heartbeatHappened = true));
249-
await sleep(heartbeatFrequencyMS * 2.5);
250-
expect(heartbeatHappened).to.be.true;
237+
await client.once('serverHeartbeatSucceeded');
251238

252239
function getRttTimer(servers) {
253-
for (const server of servers) {
254-
return server[1]?.monitor.rttPinger.monitorId;
240+
for (const [, server] of servers) {
241+
return server?.monitor.rttPinger.monitorId;
255242
}
256243
}
257244

@@ -273,40 +260,33 @@ describe.skip('MongoClient.close() Integration', () => {
273260
describe('Node.js resource: Socket', () => {
274261
describe('when rtt monitoring is turned on', () => {
275262
it('no sockets remain after client.close()', metadata, async () => {
276-
const run = async ({ MongoClient, uri, expect, sleep }) => {
263+
const run = async ({ MongoClient, uri, expect, getSockets }) => {
277264
const heartbeatFrequencyMS = 100;
278265
const client = new MongoClient(uri, {
279266
serverMonitoringMode: 'stream',
280267
heartbeatFrequencyMS
281268
});
282269
await client.connect();
283270

284-
const activeSocketsReport = () =>
285-
process.report.getReport().libuv.filter(r => r.type === 'tcp');
286-
287-
const socketsAddressesBeforeHeartbeat = activeSocketsReport().map(
288-
r => r.address
289-
);
271+
const socketsAddressesBeforeHeartbeat = getSockets().map(r => r.address);
290272

291273
const activeSocketsAfterHeartbeat = () =>
292-
activeSocketsReport()
274+
getSockets()
293275
.filter(r => !socketsAddressesBeforeHeartbeat.includes(r.address))
294276
.map(r => r.remoteEndpoint?.host + ':' + r.remoteEndpoint?.port);
295277

296278
// set of servers whose hearbeats have occurred
297279
const heartbeatOccurredSet = new Set();
298280

299-
client.on('serverHeartbeatSucceeded', async ev =>
300-
heartbeatOccurredSet.add(ev.connectionId)
301-
);
302-
303-
// ensure there is enough time for the events to occur
304-
await sleep(heartbeatFrequencyMS * 10);
281+
while (heartbeatOccurredSet.size < client.topology.s.servers.batchSize) {
282+
await client.once('serverHeartbeatSucceeded', async ev =>
283+
heartbeatOccurredSet.add(ev.connectionId)
284+
);
285+
}
305286

306287
// all servers should have had a heartbeat event and had a new socket created for rtt pinger
307288
const servers = client.topology.s.servers;
308289
for (const server of servers) {
309-
expect(heartbeatOccurredSet).to.deep.contain(server[0]);
310290
expect(activeSocketsAfterHeartbeat()).to.deep.contain(server[0]);
311291
}
312292

@@ -315,7 +295,7 @@ describe.skip('MongoClient.close() Integration', () => {
315295

316296
// upon close, assert rttPinger sockets are cleaned up
317297
const activeSocketsAfterClose = activeSocketsAfterHeartbeat();
318-
expect(activeSocketsAfterClose).to.have.length(0);
298+
expect(activeSocketsAfterClose).to.have.lengthOf(0);
319299
};
320300

321301
await runScriptAndGetProcessInfo('socket-connection-rtt-monitoring', config, run);
@@ -341,8 +321,8 @@ describe.skip('MongoClient.close() Integration', () => {
341321
const servers = client.topology?.s.servers;
342322

343323
function getMinPoolSizeTimer(servers) {
344-
for (const server of servers) {
345-
return server[1].pool.minPoolSizeTimer;
324+
for (const [, server] of servers) {
325+
return server.pool.minPoolSizeTimer;
346326
}
347327
}
348328
// note: minPoolSizeCheckFrequencyMS = 100 ms by client, so this test has a chance of being flaky
@@ -388,7 +368,6 @@ describe.skip('MongoClient.close() Integration', () => {
388368
const timeoutStartedSpy = sinon.spy(timers, 'setTimeout');
389369

390370
const client = new MongoClient(uri, {
391-
minPoolSize: 1,
392371
maxPoolSize: 1,
393372
waitQueueTimeoutMS
394373
});
@@ -414,7 +393,7 @@ describe.skip('MongoClient.close() Integration', () => {
414393

415394
await client.close();
416395
expect(getTimerCount()).to.equal(0);
417-
// un-configure fail{oint
396+
// un-configure failpoint
418397
await utilClient.db().admin().command({
419398
configureFailPoint: 'failCommand',
420399
mode: 'off'
@@ -437,26 +416,21 @@ describe.skip('MongoClient.close() Integration', () => {
437416
describe('Node.js resource: Socket', () => {
438417
describe('after a minPoolSize has been set on the ConnectionPool', () => {
439418
it('no sockets remain after client.close()', async function () {
440-
const run = async function ({ MongoClient, uri, expect }) {
441-
const connectionMonitoringReport = () =>
442-
process.report.getReport().libuv.filter(r => r.type === 'tcp');
443-
419+
const run = async function ({ MongoClient, uri, expect, getSockets }) {
444420
// assert no sockets to start with
445-
expect(connectionMonitoringReport()).to.have.length(0);
421+
expect(getSockets()).to.have.lengthOf(0);
446422
const options = { minPoolSize: 1 };
447423
const client = new MongoClient(uri, options);
448424
await client.connect();
449425

450426
// regardless of pool size: there should be a client connection socket for each server, and one monitor socket total
451427
// with minPoolSize = 1, there should be one or more extra active sockets
452-
expect(connectionMonitoringReport()).to.have.length.gte(
453-
client.topology?.s.servers.size + 2
454-
);
428+
expect(getSockets()).to.have.length.gte(client.topology?.s.servers.size + 2);
455429

456430
await client.close();
457431

458432
// assert socket clean-up
459-
expect(connectionMonitoringReport()).to.have.length(0);
433+
expect(getSockets()).to.have.lengthOf(0);
460434
};
461435

462436
await runScriptAndGetProcessInfo('socket-minPoolSize', config, run);
@@ -538,7 +512,7 @@ describe.skip('MongoClient.close() Integration', () => {
538512
describe('KMS Request', () => {
539513
describe('Node.js resource: TLS file read', () => {
540514
describe('when KMSRequest reads an infinite TLS file', () => {
541-
it('the file read is interrupted by client.close()', async () => {
515+
it('the file read is interrupted by client.close()', metadata, async () => {
542516
await runScriptAndGetProcessInfo(
543517
'tls-file-read-auto-encryption',
544518
config,

test/integration/node-specific/resource_tracking_script_builder.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,16 @@ export type HeapResourceTestFunction = (options: {
2323

2424
export type ProcessResourceTestFunction = (options: {
2525
MongoClient: typeof MongoClient;
26-
uri: string;
26+
uri?: string;
2727
log?: (out: any) => void;
2828
expect: typeof expect;
2929
mongodb?: typeof mongodb;
3030
sleep?: typeof sleep;
3131
sinon?: typeof sinon;
3232
getTimerCount?: () => number;
3333
timers?: typeof timers;
34+
getSocketReport?: () => { host: string; port: string };
35+
getSocketEndpointReport?: () => any;
3436
}) => Promise<void>;
3537

3638
const HEAP_RESOURCE_SCRIPT_PATH = path.resolve(

test/tools/fixtures/process_resource_script.in.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,21 @@ function getNewResources() {
8484
*/
8585
const getTimerCount = () => process.getActiveResourcesInfo().filter(r => r === 'Timeout').length;
8686

87+
/**
88+
* @returns Array of socket resources in the event loop
89+
*/
90+
const getSockets = () => process.report.getReport().libuv.filter(r => r.type === 'tcp');
91+
92+
/**
93+
* @returns Array of remote endpoints of socket resources in the event loop
94+
* @example [{ host: 'localhost', port: 27020 }, { host: 'localhost', port: 27107 }]
95+
*/
96+
const getSocketEndpoints = () =>
97+
process.report
98+
.getReport()
99+
.libuv.filter(r => r.type === 'tcp')
100+
.map(r => r.remoteEndpoint);
101+
87102
// A log function for debugging
88103
function log(message) {
89104
// remove outer parentheses for easier parsing

0 commit comments

Comments
 (0)