Skip to content

Commit ddb638d

Browse files
requested changes at desk - not tested.. yet..
requested changes lint
1 parent a91e9af commit ddb638d

File tree

4 files changed

+47
-71
lines changed

4 files changed

+47
-71
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{"ev":{"name":"serverHeartbeatSucceeded","connectionId":"localhost:31000","duration":4,"reply":{"topologyVersion":{"processId":"67917651e47cc2d141909817","counter":6},"hosts":["localhost:31000","localhost:31001","localhost:31002"],"arbiters":["localhost:31003"],"setName":"rs","setVersion":1,"isWritablePrimary":true,"secondary":false,"primary":"localhost:31000","me":"localhost:31000","electionId":"7fffffff0000000000000001","lastWrite":{"opTime":{"ts":{"$timestamp":"7462881799971012609"},"t":1},"lastWriteDate":"2025-01-22T23:12:53.000Z","majorityOpTime":{"ts":{"$timestamp":"7462881799971012609"},"t":1},"majorityWriteDate":"2025-01-22T23:12:53.000Z"},"maxBsonObjectSize":16777216,"maxMessageSizeBytes":48000000,"maxWriteBatchSize":100000,"localTime":"2025-01-22T23:13:01.572Z","logicalSessionTimeoutMinutes":30,"connectionId":374,"minWireVersion":0,"maxWireVersion":21,"readOnly":false,"ok":1,"$clusterTime":{"clusterTime":{"$timestamp":"7462881799971012609"},"signature":{"hash":"0ZNDkBzDMPYZGu7Xf3UGFzhng/A=","keyId":{"low":5,"high":1737586273,"unsigned":false}}},"operationTime":{"$timestamp":"7462881799971012609"}},"awaited":true}}
2+
{"ev":{"name":"serverHeartbeatSucceeded","connectionId":"localhost:31003","duration":2,"reply":{"topologyVersion":{"processId":"679176542928a27b6927e95d","counter":2},"hosts":["localhost:31000","localhost:31001","localhost:31002"],"arbiters":["localhost:31003"],"setName":"rs","setVersion":1,"isWritablePrimary":false,"secondary":false,"primary":"localhost:31000","arbiterOnly":true,"me":"localhost:31003","lastWrite":{"opTime":{"ts":{"$timestamp":"7462881799971012609"},"t":1},"lastWriteDate":"2025-01-22T23:12:53.000Z","majorityOpTime":{"ts":{"$timestamp":"7462881799971012609"},"t":1},"majorityWriteDate":"2025-01-22T23:12:53.000Z"},"maxBsonObjectSize":16777216,"maxMessageSizeBytes":48000000,"maxWriteBatchSize":100000,"localTime":"2025-01-22T23:13:01.577Z","logicalSessionTimeoutMinutes":30,"connectionId":169,"minWireVersion":0,"maxWireVersion":21,"readOnly":false,"ok":1},"awaited":true}}
3+
{"ev":{"name":"serverHeartbeatSucceeded","connectionId":"localhost:31001","duration":2,"reply":{"topologyVersion":{"processId":"67917652195aa0dc84acece6","counter":4},"hosts":["localhost:31000","localhost:31001","localhost:31002"],"arbiters":["localhost:31003"],"setName":"rs","setVersion":1,"isWritablePrimary":false,"secondary":true,"primary":"localhost:31000","me":"localhost:31001","lastWrite":{"opTime":{"ts":{"$timestamp":"7462881799971012609"},"t":1},"lastWriteDate":"2025-01-22T23:12:53.000Z","majorityOpTime":{"ts":{"$timestamp":"7462881799971012609"},"t":1},"majorityWriteDate":"2025-01-22T23:12:53.000Z"},"maxBsonObjectSize":16777216,"maxMessageSizeBytes":48000000,"maxWriteBatchSize":100000,"localTime":"2025-01-22T23:13:01.578Z","logicalSessionTimeoutMinutes":30,"connectionId":200,"minWireVersion":0,"maxWireVersion":21,"readOnly":false,"ok":1,"$clusterTime":{"clusterTime":{"$timestamp":"7462881799971012609"},"signature":{"hash":"0ZNDkBzDMPYZGu7Xf3UGFzhng/A=","keyId":{"low":5,"high":1737586273,"unsigned":false}}},"operationTime":{"$timestamp":"7462881799971012609"}},"awaited":true}}
4+
{"ev":{"name":"serverHeartbeatSucceeded","connectionId":"localhost:31002","duration":2,"reply":{"topologyVersion":{"processId":"6791765368696db3e1252bb1","counter":4},"hosts":["localhost:31000","localhost:31001","localhost:31002"],"arbiters":["localhost:31003"],"setName":"rs","setVersion":1,"isWritablePrimary":false,"secondary":true,"primary":"localhost:31000","me":"localhost:31002","lastWrite":{"opTime":{"ts":{"$timestamp":"7462881799971012609"},"t":1},"lastWriteDate":"2025-01-22T23:12:53.000Z","majorityOpTime":{"ts":{"$timestamp":"7462881799971012609"},"t":1},"majorityWriteDate":"2025-01-22T23:12:53.000Z"},"maxBsonObjectSize":16777216,"maxMessageSizeBytes":48000000,"maxWriteBatchSize":100000,"localTime":"2025-01-22T23:13:01.579Z","logicalSessionTimeoutMinutes":30,"connectionId":201,"minWireVersion":0,"maxWireVersion":21,"readOnly":false,"ok":1,"$clusterTime":{"clusterTime":{"$timestamp":"7462881799971012609"},"signature":{"hash":"0ZNDkBzDMPYZGu7Xf3UGFzhng/A=","keyId":{"low":5,"high":1737586273,"unsigned":false}}},"operationTime":{"$timestamp":"7462881799971012609"}},"awaited":true}}
5+
{"socketsAfterClose":[{"type":"tcp","is_active":false,"is_referenced":true,"address":"0x0000000129e1e690","localEndpoint":null,"remoteEndpoint":null,"sendBufferSize":0,"recvBufferSize":0,"writeQueueSize":0,"readable":false,"writable":false},{"type":"tcp","is_active":false,"is_referenced":true,"address":"0x000000013b10eb50","localEndpoint":null,"remoteEndpoint":null,"sendBufferSize":0,"recvBufferSize":0,"writeQueueSize":0,"readable":false,"writable":false},{"type":"tcp","is_active":false,"is_referenced":true,"address":"0x000000013b009eb0","localEndpoint":null,"remoteEndpoint":null,"sendBufferSize":0,"recvBufferSize":0,"writeQueueSize":0,"readable":false,"writable":false},{"type":"tcp","is_active":false,"is_referenced":true,"address":"0x000000013b009c00","localEndpoint":null,"remoteEndpoint":null,"sendBufferSize":0,"recvBufferSize":0,"writeQueueSize":0,"readable":false,"writable":false},{"type":"tcp","is_active":false,"is_referenced":true,"address":"0x0000000139f41c80","localEndpoint":null,"remoteEndpoint":null,"sendBufferSize":0,"recvBufferSize":0,"writeQueueSize":0,"readable":false,"writable":false},{"type":"tcp","is_active":true,"is_referenced":true,"address":"0x000000013b00ff90","localEndpoint":{"host":"localhost","port":65364},"remoteEndpoint":{"host":"localhost","port":31000},"sendBufferSize":146808,"recvBufferSize":407800,"fd":26,"writeQueueSize":0,"readable":true,"writable":true},{"type":"tcp","is_active":true,"is_referenced":true,"address":"0x000000010ab0a9e0","localEndpoint":{"host":"localhost","port":65365},"remoteEndpoint":{"host":"localhost","port":31001},"sendBufferSize":146808,"recvBufferSize":407800,"fd":28,"writeQueueSize":0,"readable":true,"writable":true},{"type":"tcp","is_active":false,"is_referenced":true,"address":"0x000000010ab0ab90","localEndpoint":null,"remoteEndpoint":null,"sendBufferSize":0,"recvBufferSize":0,"writeQueueSize":0,"readable":false,"writable":false},{"type":"tcp","is_active":false,"is_referenced":true,"address":"0x000000010ab0af40","localEndpoint":null,"remoteEndpoint":null,"sendBufferSize":0,"recvBufferSize":0,"writeQueueSize":0,"readable":false,"writable":false}]}
6+
{"error":{"message":"expected [ 'localhost:31000', …(3) ] to have a length of +0 but got 4","stack":"AssertionError: expected [ 'localhost:31000', …(3) ] to have a length of +0 but got 4\n at func (/Users/aditi.khare/Desktop/node-mongodb-native/socket-connection-rtt-monitoring.cjs:35:81)\n at process.processTicksAndRejections (node:internal/process/task_queues:95:5)\n at async main (/Users/aditi.khare/Desktop/node-mongodb-native/socket-connection-rtt-monitoring.cjs:145:3)","resources":{"libuvResources":[{"type":"tcp","is_active":false,"is_referenced":true,"address":"0x0000000129e1e690","localEndpoint":null,"remoteEndpoint":null,"sendBufferSize":0,"recvBufferSize":0,"writeQueueSize":0,"readable":false,"writable":false},{"type":"tcp","is_active":false,"is_referenced":true,"address":"0x000000013b10eb50","localEndpoint":null,"remoteEndpoint":null,"sendBufferSize":0,"recvBufferSize":0,"writeQueueSize":0,"readable":false,"writable":false},{"type":"tcp","is_active":false,"is_referenced":true,"address":"0x000000013b009eb0","localEndpoint":null,"remoteEndpoint":null,"sendBufferSize":0,"recvBufferSize":0,"writeQueueSize":0,"readable":false,"writable":false},{"type":"tcp","is_active":false,"is_referenced":true,"address":"0x000000013b009c00","localEndpoint":null,"remoteEndpoint":null,"sendBufferSize":0,"recvBufferSize":0,"writeQueueSize":0,"readable":false,"writable":false},{"type":"tcp","is_active":false,"is_referenced":true,"address":"0x0000000139f41c80","localEndpoint":null,"remoteEndpoint":null,"sendBufferSize":0,"recvBufferSize":0,"writeQueueSize":0,"readable":false,"writable":false},{"type":"tcp","is_active":true,"is_referenced":true,"address":"0x000000013b00ff90","localEndpoint":{"host":"localhost","port":65364},"remoteEndpoint":{"host":"localhost","port":31000},"sendBufferSize":146808,"recvBufferSize":407800,"fd":26,"writeQueueSize":0,"readable":true,"writable":true},{"type":"tcp","is_active":true,"is_referenced":true,"address":"0x000000010ab0a9e0","localEndpoint":{"host":"localhost","port":65365},"remoteEndpoint":{"host":"localhost","port":31001},"sendBufferSize":146808,"recvBufferSize":407800,"fd":28,"writeQueueSize":0,"readable":true,"writable":true},{"type":"tcp","is_active":false,"is_referenced":true,"address":"0x000000010ab0ab90","localEndpoint":null,"remoteEndpoint":null,"sendBufferSize":0,"recvBufferSize":0,"writeQueueSize":0,"readable":false,"writable":false},{"type":"tcp","is_active":false,"is_referenced":true,"address":"0x000000010ab0af40","localEndpoint":null,"remoteEndpoint":null,"sendBufferSize":0,"recvBufferSize":0,"writeQueueSize":0,"readable":false,"writable":false}],"activeResources":["ConnectWrap","ConnectWrap","TCPSocketWrap","TCPSocketWrap","TCPSocketWrap","TCPSocketWrap","TCPSocketWrap","TCPSocketWrap","TCPSocketWrap","TCPSocketWrap","TCPSocketWrap","Timeout","Timeout"]}}}

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

+24-56
Original file line numberDiff line numberDiff line change
@@ -120,22 +120,16 @@ describe.skip('MongoClient.close() Integration', () => {
120120
'monitor interval timer is cleaned up by client.close()',
121121
metadata,
122122
async function () {
123-
const run = async function ({
124-
MongoClient,
125-
uri,
126-
expect,
127-
getTimerCount,
128-
promiseWithResolvers
129-
}) {
123+
const run = async function ({ MongoClient, uri, expect, getTimerCount, once }) {
130124
const heartbeatFrequencyMS = 2000;
131125
const client = new MongoClient(uri, { heartbeatFrequencyMS });
132-
const { promise, resolve } = promiseWithResolvers();
133-
client.once('serverHeartbeatSucceeded', () => resolve());
126+
const willBeHeartbeatSucceeded = once(client, 'serverHeartbeatSucceeded');
134127
await client.connect();
135-
await promise;
128+
await willBeHeartbeatSucceeded;
136129

137130
function monitorTimersExist(servers) {
138131
for (const [, server] of servers) {
132+
// the current expected behavior is that timerId is set to undefined once it expires or is interrupted
139133
if (server?.monitor.monitorId.timerId === undefined) {
140134
return false;
141135
}
@@ -159,18 +153,12 @@ describe.skip('MongoClient.close() Integration', () => {
159153
'the new monitor interval timer is cleaned up by client.close()',
160154
metadata,
161155
async () => {
162-
const run = async function ({
163-
MongoClient,
164-
expect,
165-
getTimerCount,
166-
promiseWithResolvers
167-
}) {
156+
const run = async function ({ MongoClient, expect, getTimerCount, once }) {
168157
const heartbeatFrequencyMS = 2000;
169158
const client = new MongoClient('mongodb://fakeUri', { heartbeatFrequencyMS });
170-
const { promise, resolve } = promiseWithResolvers();
171-
client.once('serverHeartbeatFailed', () => resolve());
159+
const willBeHeartbeatFailed = once(client, 'serverHeartbeatFailed');
172160
client.connect();
173-
await promise;
161+
await willBeHeartbeatFailed;
174162

175163
function getMonitorTimer(servers) {
176164
for (const [, server] of servers) {
@@ -180,6 +168,7 @@ describe.skip('MongoClient.close() Integration', () => {
180168
const servers = client.topology.s.servers;
181169
expect(getMonitorTimer(servers)).to.exist;
182170
await client.close();
171+
// the current expected behavior is that timerId is set to undefined once it expires or is interrupted
183172
expect(getMonitorTimer(servers)).to.not.exist;
184173

185174
expect(getTimerCount()).to.equal(0);
@@ -225,22 +214,14 @@ describe.skip('MongoClient.close() Integration', () => {
225214
'the rtt pinger timer is cleaned up by client.close()',
226215
metadata,
227216
async function () {
228-
const run = async function ({
229-
MongoClient,
230-
uri,
231-
expect,
232-
getTimerCount,
233-
promiseWithResolvers
234-
}) {
217+
const run = async function ({ MongoClient, uri, expect, getTimerCount, once }) {
235218
const heartbeatFrequencyMS = 2000;
236219
const client = new MongoClient(uri, {
237220
serverMonitoringMode: 'stream',
238221
heartbeatFrequencyMS
239222
});
240223
await client.connect();
241-
const { promise, resolve } = promiseWithResolvers();
242-
client.once('serverHeartbeatSucceeded', () => resolve());
243-
await promise;
224+
await once(client, 'serverHeartbeatSucceeded');
244225

245226
function getRttTimer(servers) {
246227
for (const [, server] of servers) {
@@ -266,13 +247,7 @@ describe.skip('MongoClient.close() Integration', () => {
266247
describe('Node.js resource: Socket', () => {
267248
describe('when rtt monitoring is turned on', () => {
268249
it('no sockets remain after client.close()', metadata, async () => {
269-
const run = async ({
270-
MongoClient,
271-
uri,
272-
expect,
273-
getSockets,
274-
promiseWithResolvers
275-
}) => {
250+
const run = async ({ MongoClient, uri, expect, getSockets, once, log }) => {
276251
const heartbeatFrequencyMS = 500;
277252
const client = new MongoClient(uri, {
278253
serverMonitoringMode: 'stream',
@@ -288,12 +263,9 @@ describe.skip('MongoClient.close() Integration', () => {
288263
const servers = client.topology.s.servers;
289264

290265
while (heartbeatOccurredSet.size < servers.size) {
291-
const { promise, resolve } = promiseWithResolvers();
292-
client.once('serverHeartbeatSucceeded', ev => {
293-
heartbeatOccurredSet.add(ev.connectionId);
294-
resolve();
295-
});
296-
await promise;
266+
const ev = await once(client, 'serverHeartbeatSucceeded');
267+
log({ ev: ev[0] });
268+
heartbeatOccurredSet.add(ev[0].connectionId);
297269
}
298270

299271
const activeSocketsAfterHeartbeat = () =>
@@ -309,6 +281,7 @@ describe.skip('MongoClient.close() Integration', () => {
309281
// close the client
310282
await client.close();
311283

284+
log({ socketsAfterClose: getSockets() });
312285
// upon close, assert rttPinger sockets are cleaned up
313286
const activeSocketsAfterClose = activeSocketsAfterHeartbeat();
314287
expect(activeSocketsAfterClose).to.have.lengthOf(0);
@@ -456,24 +429,19 @@ describe.skip('MongoClient.close() Integration', () => {
456429
describe('SrvPoller', () => {
457430
describe('Node.js resource: Timer', () => {
458431
// requires an srv environment that can transition to sharded
459-
const metadata: MongoDBMetadataUI = {
460-
requires: {
461-
predicate: () =>
462-
process.env.ATLAS_SRV_REPL ? true : 'Skipped: this test requires an SRV environment'
463-
}
464-
};
432+
const metadata: MongoDBMetadataUI = { requires: { topology: 'sharded' } };
465433

466434
describe('after SRVPoller is created', () => {
467435
it('timers are cleaned up by client.close()', metadata, async () => {
468-
const run = async function ({ MongoClient, uri, expect, getTimerCount }) {
469-
const client = new MongoClient(uri);
436+
const run = async function ({ MongoClient, expect, getTimerCount }) {
437+
const SRV_CONNECTION_STRING = `mongodb+srv://test1.test.build.10gen.cc`;
438+
// 27018 localhost.test.build.10gen.cc.
439+
// 27017 localhost.test.build.10gen.cc.
440+
441+
const client = new MongoClient(SRV_CONNECTION_STRING);
470442
await client.connect();
471-
const description = client.topology.s.description;
472-
// simulate transition to sharded
473-
client.topology.emit('topologyDescriptionChanged', description, {
474-
...description,
475-
type: 'Sharded'
476-
});
443+
// the current expected behavior is that _timeout is set to undefined until SRV polling starts
444+
// then _timeout is set to undefined again when SRV polling stops
477445
expect(client.topology.s.srvPoller._timeout).to.exist;
478446
await client.close();
479447
expect(getTimerCount()).to.equal(0);

test/integration/node-specific/resource_tracking_script_builder.ts

+13-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { fork, spawn } from 'node:child_process';
22
import { on, once } from 'node:events';
3+
import { openSync, statSync } from 'node:fs';
34
import { readFile, unlink, writeFile } from 'node:fs/promises';
45
import * as path from 'node:path';
56

@@ -31,7 +32,7 @@ export type ProcessResourceTestFunction = (options: {
3132
timers?: typeof timers;
3233
getSocketReport?: () => { host: string; port: string };
3334
getSocketEndpointReport?: () => any;
34-
promiseWithResolvers?: () => any;
35+
once?: () => typeof once;
3536
}) => Promise<void>;
3637

3738
const HEAP_RESOURCE_SCRIPT_PATH = path.resolve(
@@ -176,7 +177,10 @@ export async function runScriptAndGetProcessInfo(
176177
await writeFile(scriptName, scriptContent, { encoding: 'utf8' });
177178
const logFile = name + '.logs.txt';
178179

179-
const script = spawn(process.execPath, [scriptName], { stdio: ['ignore', 'ignore', 'inherit'] });
180+
const stdErrFile = 'err.out';
181+
const script = spawn(process.execPath, [scriptName], {
182+
stdio: ['ignore', 'ignore', openSync(stdErrFile, 'w')]
183+
});
180184

181185
const willClose = once(script, 'close');
182186

@@ -190,9 +194,12 @@ export async function runScriptAndGetProcessInfo(
190194
.map(line => JSON.parse(line))
191195
.reduce((acc, curr) => ({ ...acc, ...curr }), {});
192196

197+
const stdErrSize = statSync(stdErrFile).size;
198+
193199
// delete temporary files
194200
await unlink(scriptName);
195-
await unlink(logFile);
201+
// await unlink(logFile);
202+
await unlink(stdErrFile);
196203

197204
// assertions about exit status
198205
if (exitCode) {
@@ -203,6 +210,9 @@ export async function runScriptAndGetProcessInfo(
203210
throw assertionError;
204211
}
205212

213+
// assertion about error output
214+
expect(stdErrSize).to.equal(0);
215+
206216
// assertions about resource status
207217
expect(messages.beforeExitHappened).to.be.true;
208218
expect(messages.newResources.libuvResources).to.be.empty;

0 commit comments

Comments
 (0)