From 9793c44b49e45dd06305fffbe4d118b8cb54073a Mon Sep 17 00:00:00 2001 From: Aditi Khare Date: Thu, 9 Jan 2025 02:58:42 -0500 Subject: [PATCH] rebase --- srv-poller-timer.cjs | 146 -------------------------------- srv-poller-timer.logs.txt | 3 - timer-server-selection.cjs | 136 ----------------------------- timer-server-selection.logs.txt | 2 - 4 files changed, 287 deletions(-) delete mode 100644 srv-poller-timer.cjs delete mode 100644 srv-poller-timer.logs.txt delete mode 100644 timer-server-selection.cjs delete mode 100644 timer-server-selection.logs.txt diff --git a/srv-poller-timer.cjs b/srv-poller-timer.cjs deleted file mode 100644 index ee45321f1e..0000000000 --- a/srv-poller-timer.cjs +++ /dev/null @@ -1,146 +0,0 @@ -'use strict'; - -/* eslint-disable no-undef */ -/* eslint-disable no-unused-vars */ -const driverPath = "/Users/aditi.khare/Desktop/node-mongodb-native/lib"; -const func = (async function ({ MongoClient, uri, expect, log, sinon, mongodb, getTimerCount }) { - const dns = require('dns'); - sinon.stub(dns.promises, 'resolveTxt').callsFake(async () => { - throw { code: 'ENODATA' }; - }); - sinon.stub(dns.promises, 'resolveSrv').callsFake(async () => { - const formattedUri = mongodb.HostAddress.fromString(uri.split('//')[1]); - return [ - { - name: formattedUri.host, - port: formattedUri.port, - weight: 0, - priority: 0, - protocol: formattedUri.host.isIPv6 ? 'IPv6' : 'IPv4' - } - ]; - }); - /* sinon.stub(mongodb, 'checkParentDomainMatch').callsFake(async () => { - console.log('in here!!!'); - }); */ - const client = new MongoClient('mongodb+srv://localhost'); - await client.connect(); - await client.close(); - expect(getTimerCount()).to.equal(0); - sinon.restore(); - }); -const scriptName = "srv-poller-timer"; -const uri = "mongodb://localhost:27017/integration_tests?authSource=admin"; - -const mongodb = require(driverPath); -const { MongoClient } = mongodb; -const process = require('node:process'); -const util = require('node:util'); -const timers = require('node:timers'); -const fs = require('node:fs'); -const sinon = require('sinon'); -const { expect } = require('chai'); -const { setTimeout } = require('timers'); - -let originalReport; -const logFile = scriptName + '.logs.txt'; -const sleep = util.promisify(setTimeout); - -const run = func; - -/** - * - * Returns an array containing the new libuv resources created after script started. - * A new resource is something that will keep the event loop running. - * - * In order to be counted as a new resource, a resource MUST: - * - Must NOT share an address with a libuv resource that existed at the start of script - * - Must be referenced. See [here](https://nodejs.org/api/timers.html#timeoutref) for more context. - * - * We're using the following tool to track resources: `process.report.getReport().libuv` - * For more context, see documentation for [process.report.getReport()](https://nodejs.org/api/report.html), and [libuv](https://docs.libuv.org/en/v1.x/handle.html). - * - */ -function getNewLibuvResourceArray() { - let currReport = process.report.getReport().libuv; - const originalReportAddresses = originalReport.map(resource => resource.address); - - /** - * @typedef {Object} LibuvResource - * @property {string} type What is the resource type? For example, 'tcp' | 'timer' | 'udp' | 'tty'... (See more in [docs](https://docs.libuv.org/en/v1.x/handle.html)). - * @property {boolean} is_referenced Is the resource keeping the JS event loop active? - * - * @param {LibuvResource} resource - */ - function isNewLibuvResource(resource) { - const serverType = ['tcp', 'udp']; - return ( - !originalReportAddresses.includes(resource.address) && resource.is_referenced // if a resource is unreferenced, it's not keeping the event loop open - ); - } - - currReport = currReport.filter(resource => isNewLibuvResource(resource)); - return currReport; -} - -/** - * Returns an object of the new resources created after script started. - * - * - * In order to be counted as a new resource, a resource MUST either: - * - Meet the criteria to be returned by our helper utility `getNewLibuvResourceArray()` - * OR - * - Be returned by `process.getActiveResourcesInfo() - * - * The reason we are using both methods to detect active resources is: - * - `process.report.getReport().libuv` does not detect active requests (such as timers or file reads) accurately - * - `process.getActiveResourcesInfo()` does not contain enough server information we need for our assertions - * - */ -function getNewResources() { - return { - libuvResources: getNewLibuvResourceArray(), - activeResources: process.getActiveResourcesInfo() - }; -} - -/** - * @returns Number of active timers in event loop - */ -const getTimerCount = () => process.getActiveResourcesInfo().filter(r => r === 'Timeout').length; - -// A log function for debugging -function log(message) { - // remove outer parentheses for easier parsing - const messageToLog = JSON.stringify(message) + ' \n'; - fs.writeFileSync(logFile, messageToLog, { flag: 'a' }); -} - -async function main() { - originalReport = process.report.getReport().libuv; - process.on('beforeExit', () => { - log({ beforeExitHappened: true }); - }); - await run({ MongoClient, uri, log, expect, mongodb, sleep, sinon, getTimerCount }); - log({ newResources: getNewResources() }); -} - -main() - .then(() => {}) - .catch(e => { - log({ error: { message: e.message, stack: e.stack, resources: getNewResources() } }); - process.exit(1); - }); - -setTimeout(() => { - // this means something was in the event loop such that it hung for more than 10 seconds - // so we kill the process - log({ - error: { - message: 'Process timed out: resources remain in the event loop', - resources: getNewResources() - } - }); - process.exit(99); - // using `unref` will ensure this setTimeout call is not a resource / does not keep the event loop running -}, 10000).unref(); diff --git a/srv-poller-timer.logs.txt b/srv-poller-timer.logs.txt deleted file mode 100644 index 3e2667b147..0000000000 --- a/srv-poller-timer.logs.txt +++ /dev/null @@ -1,3 +0,0 @@ -{"domainMatch":{"BSON":{"BSONType":{"double":1,"string":2,"object":3,"array":4,"binData":5,"undefined":6,"objectId":7,"bool":8,"date":9,"null":10,"regex":11,"dbPointer":12,"javascript":13,"symbol":14,"javascriptWithScope":15,"int":16,"timestamp":17,"long":18,"decimal":19,"minKey":-1,"maxKey":127},"EJSON":{},"onDemand":{"ByteUtils":{},"NumberUtils":{}}},"BSONType":{"double":1,"string":2,"object":3,"array":4,"binData":5,"undefined":6,"objectId":7,"bool":8,"date":9,"null":10,"regex":11,"dbPointer":12,"javascript":13,"symbol":14,"javascriptWithScope":15,"int":16,"timestamp":17,"long":18,"decimal":19,"minKey":-1,"maxKey":127},"BatchType":{"INSERT":1,"UPDATE":2,"DELETE":3},"AutoEncryptionLoggerLevel":{"FatalError":0,"Error":1,"Warning":2,"Info":3,"Trace":4},"GSSAPICanonicalizationValue":{"on":true,"off":false,"none":"none","forward":"forward","forwardAndReverse":"forwardAndReverse"},"AuthMechanism":{"MONGODB_AWS":"MONGODB-AWS","MONGODB_CR":"MONGODB-CR","MONGODB_DEFAULT":"DEFAULT","MONGODB_GSSAPI":"GSSAPI","MONGODB_PLAIN":"PLAIN","MONGODB_SCRAM_SHA1":"SCRAM-SHA-1","MONGODB_SCRAM_SHA256":"SCRAM-SHA-256","MONGODB_X509":"MONGODB-X509","MONGODB_OIDC":"MONGODB-OIDC"},"Compressor":{"none":0,"snappy":1,"zlib":2,"zstd":3},"CURSOR_FLAGS":["tailable","oplogReplay","noCursorTimeout","awaitData","exhaust","partial"],"CursorTimeoutMode":{"ITERATION":"iteration","LIFETIME":"cursorLifetime"},"MongoErrorLabel":{"RetryableWriteError":"RetryableWriteError","TransientTransactionError":"TransientTransactionError","UnknownTransactionCommitResult":"UnknownTransactionCommitResult","ResumableChangeStreamError":"ResumableChangeStreamError","HandshakeError":"HandshakeError","ResetPool":"ResetPool","PoolRequstedRetry":"PoolRequstedRetry","InterruptInUseConnections":"InterruptInUseConnections","NoWritesPerformed":"NoWritesPerformed"},"ExplainVerbosity":{"queryPlanner":"queryPlanner","queryPlannerExtended":"queryPlannerExtended","executionStats":"executionStats","allPlansExecution":"allPlansExecution"},"ServerApiVersion":{"v1":"1"},"ReturnDocument":{"BEFORE":"before","AFTER":"after"},"ProfilingLevel":{"off":"off","slowOnly":"slow_only","all":"all"},"ReadConcernLevel":{"local":"local","majority":"majority","linearizable":"linearizable","available":"available","snapshot":"snapshot"},"ReadPreferenceMode":{"primary":"primary","primaryPreferred":"primaryPreferred","secondary":"secondary","secondaryPreferred":"secondaryPreferred","nearest":"nearest"},"ServerType":{"Standalone":"Standalone","Mongos":"Mongos","PossiblePrimary":"PossiblePrimary","RSPrimary":"RSPrimary","RSSecondary":"RSSecondary","RSArbiter":"RSArbiter","RSOther":"RSOther","RSGhost":"RSGhost","Unknown":"Unknown","LoadBalancer":"LoadBalancer"},"TopologyType":{"Single":"Single","ReplicaSetNoPrimary":"ReplicaSetNoPrimary","ReplicaSetWithPrimary":"ReplicaSetWithPrimary","Sharded":"Sharded","Unknown":"Unknown","LoadBalanced":"LoadBalanced"}}} -{"error":{"message":"Cannot read properties of undefined (reading 'fromString')","stack":"TypeError: Cannot read properties of undefined (reading 'fromString')\n at Object. (/Users/aditi.khare/Desktop/node-mongodb-native/srv-poller-timer.cjs:12:74)\n at Object.invoke (/Users/aditi.khare/Desktop/node-mongodb-native/node_modules/sinon/lib/sinon/behavior.js:177:32)\n at Object.functionStub (/Users/aditi.khare/Desktop/node-mongodb-native/node_modules/sinon/lib/sinon/stub.js:44:43)\n at Function.invoke (/Users/aditi.khare/Desktop/node-mongodb-native/node_modules/sinon/lib/sinon/proxy-invoke.js:53:47)\n at bound querySrv [as resolveSrv] (/Users/aditi.khare/Desktop/node-mongodb-native/node_modules/sinon/lib/sinon/proxy.js:275:26)\n at resolveSRVRecord (/Users/aditi.khare/Desktop/node-mongodb-native/lib/connection_string.js:43:42)\n at MongoClient._connect (/Users/aditi.khare/Desktop/node-mongodb-native/lib/mongo_client.js:200:74)\n at MongoClient.connect (/Users/aditi.khare/Desktop/node-mongodb-native/lib/mongo_client.js:164:40)\n at func (/Users/aditi.khare/Desktop/node-mongodb-native/srv-poller-timer.cjs:27:42)\n at main (/Users/aditi.khare/Desktop/node-mongodb-native/srv-poller-timer.cjs:124:9)","resources":{"libuvResources":[],"activeResources":["FSReqPromise","TTYWrap"]}}} -{"error":{"message":"Cannot read properties of undefined (reading 'fromString')","stack":"TypeError: Cannot read properties of undefined (reading 'fromString')\n at Object. (/Users/aditi.khare/Desktop/node-mongodb-native/srv-poller-timer.cjs:12:74)\n at Object.invoke (/Users/aditi.khare/Desktop/node-mongodb-native/node_modules/sinon/lib/sinon/behavior.js:177:32)\n at Object.functionStub (/Users/aditi.khare/Desktop/node-mongodb-native/node_modules/sinon/lib/sinon/stub.js:44:43)\n at Function.invoke (/Users/aditi.khare/Desktop/node-mongodb-native/node_modules/sinon/lib/sinon/proxy-invoke.js:53:47)\n at bound querySrv [as resolveSrv] (/Users/aditi.khare/Desktop/node-mongodb-native/node_modules/sinon/lib/sinon/proxy.js:275:26)\n at resolveSRVRecord (/Users/aditi.khare/Desktop/node-mongodb-native/lib/connection_string.js:43:42)\n at MongoClient._connect (/Users/aditi.khare/Desktop/node-mongodb-native/lib/mongo_client.js:200:74)\n at MongoClient.connect (/Users/aditi.khare/Desktop/node-mongodb-native/lib/mongo_client.js:164:40)\n at func (/Users/aditi.khare/Desktop/node-mongodb-native/srv-poller-timer.cjs:27:42)\n at main (/Users/aditi.khare/Desktop/node-mongodb-native/srv-poller-timer.cjs:124:9)","resources":{"libuvResources":[],"activeResources":["FSReqPromise","TTYWrap"]}}} diff --git a/timer-server-selection.cjs b/timer-server-selection.cjs deleted file mode 100644 index bdb07b4d24..0000000000 --- a/timer-server-selection.cjs +++ /dev/null @@ -1,136 +0,0 @@ -'use strict'; - -/* eslint-disable no-undef */ -/* eslint-disable no-unused-vars */ -const driverPath = "/Users/aditi.khare/Desktop/node-mongodb-native/lib"; -const func = (async function ({ MongoClient, uri, expect, sinon, sleep, mongodb, getTimerCount }) { - const serverSelectionTimeoutMS = 777; - const client = new MongoClient(uri, { minPoolSize: 1, serverSelectionTimeoutMS }); - const timeoutStartedSpy = sinon.spy(mongodb.Timeout, 'expires'); - let serverSelectionTimeoutStarted = false; - // make server selection hang so check out timer isn't cleared and check that the timeout has started - sinon.stub(Promise, 'race').callsFake(() => { - serverSelectionTimeoutStarted = timeoutStartedSpy.getCalls().map(r => r.args).filter(r => r.includes(777)) ? true : false; - }); - client.db('db').collection('collection').insertOne({ x: 1 }).catch(e => e); - // don't allow entire checkout timer to elapse to ensure close is called mid-timeout - await sleep(serverSelectionTimeoutMS / 2); - expect(serverSelectionTimeoutStarted).to.be.true; - await client.close(); - expect(getTimerCount()).to.equal(0); - }); -const scriptName = "timer-server-selection"; -const uri = "mongodb://localhost:27017/integration_tests?authSource=admin"; - -const mongodb = require(driverPath); -const { MongoClient } = mongodb; -const process = require('node:process'); -const util = require('node:util'); -const timers = require('node:timers'); -const fs = require('node:fs'); -const sinon = require('sinon'); -const { expect } = require('chai'); -const { setTimeout } = require('timers'); - -let originalReport; -const logFile = scriptName + '.logs.txt'; -const sleep = util.promisify(setTimeout); - -const run = func; - -/** - * - * Returns an array containing the new libuv resources created after script started. - * A new resource is something that will keep the event loop running. - * - * In order to be counted as a new resource, a resource MUST: - * - Must NOT share an address with a libuv resource that existed at the start of script - * - Must be referenced. See [here](https://nodejs.org/api/timers.html#timeoutref) for more context. - * - * We're using the following tool to track resources: `process.report.getReport().libuv` - * For more context, see documentation for [process.report.getReport()](https://nodejs.org/api/report.html), and [libuv](https://docs.libuv.org/en/v1.x/handle.html). - * - */ -function getNewLibuvResourceArray() { - let currReport = process.report.getReport().libuv; - const originalReportAddresses = originalReport.map(resource => resource.address); - - /** - * @typedef {Object} LibuvResource - * @property {string} type What is the resource type? For example, 'tcp' | 'timer' | 'udp' | 'tty'... (See more in [docs](https://docs.libuv.org/en/v1.x/handle.html)). - * @property {boolean} is_referenced Is the resource keeping the JS event loop active? - * - * @param {LibuvResource} resource - */ - function isNewLibuvResource(resource) { - const serverType = ['tcp', 'udp']; - return ( - !originalReportAddresses.includes(resource.address) && resource.is_referenced // if a resource is unreferenced, it's not keeping the event loop open - ); - } - - currReport = currReport.filter(resource => isNewLibuvResource(resource)); - return currReport; -} - -/** - * Returns an object of the new resources created after script started. - * - * - * In order to be counted as a new resource, a resource MUST either: - * - Meet the criteria to be returned by our helper utility `getNewLibuvResourceArray()` - * OR - * - Be returned by `process.getActiveResourcesInfo() - * - * The reason we are using both methods to detect active resources is: - * - `process.report.getReport().libuv` does not detect active requests (such as timers or file reads) accurately - * - `process.getActiveResourcesInfo()` does not contain enough server information we need for our assertions - * - */ -function getNewResources() { - return { - libuvResources: getNewLibuvResourceArray(), - activeResources: process.getActiveResourcesInfo() - }; -} - -/** - * @returns Number of active timers in event loop - */ -const getTimerCount = () => process.getActiveResourcesInfo().filter(r => r === 'Timeout').length; - -// A log function for debugging -function log(message) { - // remove outer parentheses for easier parsing - const messageToLog = JSON.stringify(message) + ' \n'; - fs.writeFileSync(logFile, messageToLog, { flag: 'a' }); -} - -async function main() { - originalReport = process.report.getReport().libuv; - process.on('beforeExit', () => { - log({ beforeExitHappened: true }); - }); - await run({ MongoClient, uri, log, expect, mongodb, sleep, sinon, getTimerCount }); - log({ newResources: getNewResources() }); -} - -main() - .then(() => {}) - .catch(e => { - log({ error: { message: e.message, stack: e.stack, resources: getNewResources() } }); - process.exit(1); - }); - -setTimeout(() => { - // this means something was in the event loop such that it hung for more than 10 seconds - // so we kill the process - log({ - error: { - message: 'Process timed out: resources remain in the event loop', - resources: getNewResources() - } - }); - process.exit(99); - // using `unref` will ensure this setTimeout call is not a resource / does not keep the event loop running -}, 10000).unref(); diff --git a/timer-server-selection.logs.txt b/timer-server-selection.logs.txt deleted file mode 100644 index 4dcdc45ba0..0000000000 --- a/timer-server-selection.logs.txt +++ /dev/null @@ -1,2 +0,0 @@ -{"error":{"message":"Cannot read properties of undefined (reading 'expires')","stack":"TypeError: Cannot read properties of undefined (reading 'expires')\n at Function.spy (/Users/aditi.khare/Desktop/node-mongodb-native/node_modules/sinon/lib/sinon/spy.js:178:61)\n at Sandbox.spy (/Users/aditi.khare/Desktop/node-mongodb-native/node_modules/sinon/lib/sinon/sandbox.js:449:37)\n at func (/Users/aditi.khare/Desktop/node-mongodb-native/timer-server-selection.cjs:9:57)\n at main (/Users/aditi.khare/Desktop/node-mongodb-native/timer-server-selection.cjs:114:9)\n at Object. (/Users/aditi.khare/Desktop/node-mongodb-native/timer-server-selection.cjs:118:1)\n at Module._compile (node:internal/modules/cjs/loader:1376:14)\n at Module._extensions..js (node:internal/modules/cjs/loader:1435:10)\n at Module.load (node:internal/modules/cjs/loader:1207:32)\n at Module._load (node:internal/modules/cjs/loader:1023:12)\n at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:135:12)","resources":{"libuvResources":[],"activeResources":["FSReqPromise","TTYWrap"]}}} -{"error":{"message":"Cannot read properties of undefined (reading 'expires')","stack":"TypeError: Cannot read properties of undefined (reading 'expires')\n at Function.spy (/Users/aditi.khare/Desktop/node-mongodb-native/node_modules/sinon/lib/sinon/spy.js:178:61)\n at Sandbox.spy (/Users/aditi.khare/Desktop/node-mongodb-native/node_modules/sinon/lib/sinon/sandbox.js:449:37)\n at func (/Users/aditi.khare/Desktop/node-mongodb-native/timer-server-selection.cjs:9:57)\n at main (/Users/aditi.khare/Desktop/node-mongodb-native/timer-server-selection.cjs:114:9)\n at Object. (/Users/aditi.khare/Desktop/node-mongodb-native/timer-server-selection.cjs:118:1)\n at Module._compile (node:internal/modules/cjs/loader:1376:14)\n at Module._extensions..js (node:internal/modules/cjs/loader:1435:10)\n at Module.load (node:internal/modules/cjs/loader:1207:32)\n at Module._load (node:internal/modules/cjs/loader:1023:12)\n at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:135:12)","resources":{"libuvResources":[],"activeResources":["FSReqPromise","TTYWrap"]}}}