Skip to content

Commit

Permalink
chore: prepare for BSON fix
Browse files Browse the repository at this point in the history
  • Loading branch information
nbbeeken committed Nov 25, 2024
1 parent a9de6b8 commit e5a7c4c
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 69 deletions.
58 changes: 25 additions & 33 deletions src/cmap/connect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -390,18 +390,31 @@ export async function makeSocket(options: MakeConnectionOptions): Promise<Stream
const connectEvent = useTLS ? 'secureConnect' : 'connect';
socket
.once(connectEvent, () => resolve(socket))
.once('error', error => reject(connectionFailureError('error', error)))
.once('error', cause =>
reject(new MongoNetworkError(MongoError.buildErrorMessage(cause), { cause }))
)
.once('timeout', () => {
reject(
new MongoNetworkTimeoutError(
`Socket '${connectEvent}' timed out after ${(performance.now() - start) | 0}ms (connectTimeoutMS: ${connectTimeoutMS})`
)
);
})
.once('close', () => reject(connectionFailureError('close')));
.once('close', () =>
reject(
new MongoNetworkError(
`Socket closed after ${(performance.now() - start) | 0} during connection establishment`
)
)
);

if (options.cancellationToken != null) {
cancellationHandler = () => reject(connectionFailureError('cancel'));
cancellationHandler = () =>
reject(
new MongoNetworkError(
`Socket connection establishment was cancelled after ${(performance.now() - start) | 0}`
)
);
options.cancellationToken.once('cancel', cancellationHandler);
}
}
Expand Down Expand Up @@ -454,9 +467,11 @@ async function makeSocks5Connection(options: MakeConnectionOptions): Promise<Str

socks ??= loadSocks();

let existingSocket: Stream;

try {
// Then, establish the Socks5 proxy connection:
const { socket } = await socks.SocksClient.createConnection({
const connection = await socks.SocksClient.createConnection({
existing_socket: rawSocket,
timeout: options.connectTimeoutMS,
command: 'connect',
Expand All @@ -473,35 +488,12 @@ async function makeSocks5Connection(options: MakeConnectionOptions): Promise<Str
password: options.proxyPassword || undefined
}
});

// Finally, now treat the resulting duplex stream as the
// socket over which we send and receive wire protocol messages:
return await makeSocket({
...options,
existingSocket: socket,
proxyHost: undefined
});
} catch (error) {
throw connectionFailureError('error', error);
existingSocket = connection.socket;
} catch (cause) {
throw new MongoNetworkError(MongoError.buildErrorMessage(cause), { cause });
}
}

function connectionFailureError(type: 'error', cause: Error): MongoNetworkError;
function connectionFailureError(type: 'close' | 'timeout' | 'cancel'): MongoNetworkError;
function connectionFailureError(
type: 'error' | 'close' | 'timeout' | 'cancel',
cause?: Error
): MongoNetworkError {
switch (type) {
case 'error':
return new MongoNetworkError(MongoError.buildErrorMessage(cause), { cause });
case 'timeout':
return new MongoNetworkTimeoutError('connection timed out');
case 'close':
return new MongoNetworkError('connection closed');
case 'cancel':
return new MongoNetworkError('connection establishment was cancelled');
default:
return new MongoNetworkError('unknown network error');
}
// Finally, now treat the resulting duplex stream as the
// socket over which we send and receive wire protocol messages:
return await makeSocket({ ...options, existingSocket, proxyHost: undefined });
}
22 changes: 22 additions & 0 deletions test/benchmarks/driverBench/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ const { Readable } = require('stream');
const { pipeline } = require('stream/promises');
const child_process = require('child_process');

/**
* The path to the MongoDB Node.js driver.
* This MUST be set to the directory the driver is installed in
* NOT the file "lib/index.js" that is the driver's export.
*/
const MONGODB_DRIVER_PATH = (() => {
let driverPath = process.env.MONGODB_DRIVER_PATH;
if (!driverPath?.length) {
Expand All @@ -16,8 +21,13 @@ const MONGODB_DRIVER_PATH = (() => {

const { MongoClient, GridFSBucket } = require(MONGODB_DRIVER_PATH);

/** Grab the version from the package.json */
const { version: MONGODB_DRIVER_VERSION } = require(path.join(MONGODB_DRIVER_PATH, 'package.json'));

/**
* Use git to optionally determine the git revision,
* but the benchmarks could be run against an npm installed version so this should be allowed to fail
*/
const MONGODB_DRIVER_REVISION = (() => {
try {
return child_process
Expand All @@ -31,8 +41,20 @@ const MONGODB_DRIVER_REVISION = (() => {
}
})();

/**
* Find the BSON dependency inside the driver PATH given and grab the version from the package.json.
*/
const MONGODB_BSON_PATH = path.join(MONGODB_DRIVER_PATH, 'node_modules', 'bson');
const { version: MONGODB_BSON_VERSION } = require(path.join(MONGODB_BSON_PATH, 'package.json'));

/**
* If you need to test BSON changes, you should clone, checkout and build BSON.
* run: `npm link` with no arguments to register the link.
* Then in the driver you are testing run `npm link bson` to use your local build.
*
* This will symlink the BSON into the driver's node_modules directory. So here
* we can find the revision of the BSON we are testing against if .git exists.
*/
const MONGODB_BSON_REVISION = (() => {
if (!fs.existsSync(path.join(MONGODB_BSON_PATH, '.git'))) {
return 'installed from npm';
Expand Down
62 changes: 26 additions & 36 deletions test/benchmarks/driverBench/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

const MongoBench = require('../mongoBench');
const os = require('node:os');
const util = require('node:util');
const process = require('node:process');

const Runner = MongoBench.Runner;
Expand All @@ -11,18 +10,8 @@ let bsonType = 'js-bson';
// TODO(NODE-4606): test against different driver configurations in CI

const { writeFile } = require('fs/promises');
const {
makeParallelBenchmarks /* makeSingleBench, makeMultiBench */
} = require('../mongoBench/suites');
const {
MONGODB_CLIENT_OPTIONS,
MONGODB_DRIVER_PATH,
MONGODB_DRIVER_VERSION,
MONGODB_DRIVER_REVISION,
MONGODB_BSON_PATH,
MONGODB_BSON_VERSION,
MONGODB_BSON_REVISION
} = require('./common');
const { makeParallelBenchmarks, makeSingleBench, makeMultiBench } = require('../mongoBench/suites');
const { MONGODB_CLIENT_OPTIONS } = require('./common');

const hw = os.cpus();
const ram = os.totalmem() / 1024 ** 3;
Expand All @@ -35,10 +24,7 @@ const systemInfo = () =>
`- arch: ${os.arch()}`,
`- os: ${process.platform} (${os.release()})`,
`- ram: ${platform.ram}`,
`- node: ${process.version}`,
`- driver: ${MONGODB_DRIVER_VERSION} (${MONGODB_DRIVER_REVISION}): ${MONGODB_DRIVER_PATH}`,
` - options ${util.inspect(MONGODB_CLIENT_OPTIONS)}`,
`- bson: ${MONGODB_BSON_VERSION} (${MONGODB_BSON_REVISION}): (${MONGODB_BSON_PATH})\n`
`- node: ${process.version}\n`
].join('\n');
console.log(systemInfo());

Expand All @@ -47,19 +33,23 @@ function average(arr) {
}

const benchmarkRunner = new Runner()
// .suite('singleBench', suite => makeSingleBench(suite))
// .suite('multiBench', suite => makeMultiBench(suite))
.suite('singleBench', suite => makeSingleBench(suite))
.suite('multiBench', suite => makeMultiBench(suite))
.suite('parallel', suite => makeParallelBenchmarks(suite));

benchmarkRunner
.run()
.then(microBench => {
// const singleBench = average([
// microBench.singleBench.findOne,
// microBench.singleBench.smallDocInsertOne,
// microBench.singleBench.largeDocInsertOne
// ]);
// const multiBench = average(Object.values(microBench.multiBench));
const singleBench = average([
microBench.singleBench.findOne,
microBench.singleBench.smallDocInsertOne,
microBench.singleBench.largeDocInsertOne
]);
const multiBench = average(Object.values(microBench.multiBench));

// ldjsonMultiFileUpload and ldjsonMultiFileExport cause connection errors.
// While we investigate, we will use the last known good values:
// https://spruce.mongodb.com/task/mongo_node_driver_next_performance_tests_run_spec_benchmark_tests_node_server_4bc3e500b6f0e8ab01f052c4a1bfb782d6a29b4e_f168e1328f821bbda265e024cc91ae54_24_11_18_15_37_24/logs?execution=0

const parallelBench = average([
microBench.parallel.ldjsonMultiFileUpload,
Expand All @@ -69,27 +59,27 @@ benchmarkRunner
]);

const readBench = average([
// microBench.singleBench.findOne,
// microBench.multiBench.findManyAndEmptyCursor,
// microBench.multiBench.gridFsDownload,
microBench.singleBench.findOne,
microBench.multiBench.findManyAndEmptyCursor,
microBench.multiBench.gridFsDownload,
microBench.parallel.gridfsMultiFileDownload,
microBench.parallel.ldjsonMultiFileExport
]);
const writeBench = average([
// microBench.singleBench.smallDocInsertOne,
// microBench.singleBench.largeDocInsertOne,
// microBench.multiBench.smallDocBulkInsert,
// microBench.multiBench.largeDocBulkInsert,
// microBench.multiBench.gridFsUpload,
microBench.singleBench.smallDocInsertOne,
microBench.singleBench.largeDocInsertOne,
microBench.multiBench.smallDocBulkInsert,
microBench.multiBench.largeDocBulkInsert,
microBench.multiBench.gridFsUpload,
microBench.parallel.ldjsonMultiFileUpload,
microBench.parallel.gridfsMultiFileUpload
]);

const driverBench = average([readBench, writeBench]);

const benchmarkResults = {
// singleBench,
// multiBench,
singleBench,
multiBench,
parallelBench,
readBench,
writeBench,
Expand Down Expand Up @@ -123,6 +113,6 @@ benchmarkRunner
return writeFile('results.json', results);
})
.catch(err => {
console.error('failure: ', err.name, err.message, err.stack);
console.error('failure: ', err.name, err.message);
process.exit(1);
});

0 comments on commit e5a7c4c

Please sign in to comment.