diff --git a/packages/compass-connect/test/renderer/stores/index.spec.js b/packages/compass-connect/test/renderer/stores/index.spec.js index a0e0680cbe3..6facd26a9a1 100644 --- a/packages/compass-connect/test/renderer/stores/index.spec.js +++ b/packages/compass-connect/test/renderer/stores/index.spec.js @@ -1052,7 +1052,7 @@ describe('Store', () => { it('sets the driverUrl', (done) => { const driverUrl = - 'mongodb://server.example.com:27017/?readPreference=primary&ssl=false'; + 'mongodb://server.example.com:27017/?readPreference=primary&directConnection=true&ssl=false'; const unsubscribe = Store.listen((state) => { try { unsubscribe(); diff --git a/packages/connection-model/lib/connect.js b/packages/connection-model/lib/connect.js index 950857162e6..43fee45a669 100644 --- a/packages/connection-model/lib/connect.js +++ b/packages/connection-model/lib/connect.js @@ -56,6 +56,22 @@ async function waitForTunnelError(tunnel) { throw error; } +function addDirectConnectionWhenNeeded(options, model) { + if ( + model.directConnection === undefined && + model.hosts.length === 1 && + !model.isSrvRecord && + (model.replicaSet === undefined || model.replicaSet === '') + ) { + return { + ...options, + directConnection: true + }; + } + + return options; +} + async function connect(model, setupListeners) { if (model.serialize === undefined) { // note this is only here for testing reasons and would not be @@ -68,7 +84,7 @@ async function connect(model, setupListeners) { const url = removeGssapiServiceName(model.driverUrlWithSsh); const options = { - ...model.driverOptions + ...addDirectConnectionWhenNeeded(model.driverOptions, model) }; // if `auth` is passed then username and password must be present, @@ -124,3 +140,4 @@ module.exports = (model, setupListeners, done) => connect(model, setupListeners) (res) => process.nextTick(() => done(null, ...res)), (err) => process.nextTick(() => done(err)) ); + diff --git a/packages/connection-model/lib/model.js b/packages/connection-model/lib/model.js index b60a0e52aa0..df817643969 100644 --- a/packages/connection-model/lib/model.js +++ b/packages/connection-model/lib/model.js @@ -169,9 +169,7 @@ const CONNECTION_STRING_OPTIONS = { ], default: undefined }, - // Driver brought this behaviour back in v3.6.3+ (but will remove in v4), we don't need to handle directConnection ourselves - // See https://github.com/mongodb/node-mongodb-native/pull/2719 - // directConnection: { type: 'boolean', default: undefined } + directConnection: { type: 'boolean', default: undefined } }; assign(props, CONNECTION_STRING_OPTIONS); diff --git a/packages/connection-model/test/connect.test.js b/packages/connection-model/test/connect.test.js index 832de4eb148..e7fa92836a2 100644 --- a/packages/connection-model/test/connect.test.js +++ b/packages/connection-model/test/connect.test.js @@ -27,22 +27,31 @@ describe('connection model connector', () => { model, setupListeners, (connectErr, client, _tunnel, { url, options }) => { - if (connectErr) throw connectErr; - - assert.strictEqual( - url, - 'mongodb://localhost:27018/?readPreference=primary&ssl=false' - ); - - assert.deepStrictEqual(options, { - // Driver brought this behaviour back in v3.6.3+ (but will remove in v4), we don't need to handle directConnection ourselves - // See https://github.com/mongodb/node-mongodb-native/pull/2719 - // directConnection: true, - readPreference: 'primary' - }); - - client.close(true); - done(); + if (connectErr) { + return done(connectErr); + } + + try { + assert.strictEqual( + url, + 'mongodb://localhost:27018/?readPreference=primary&directConnection=true&ssl=false' + ); + + assert.deepStrictEqual(options, { + // this is never truly added at the moment since Connection.from + // already adds this to the model and query string when necessary: + // directConnection: true, + readPreference: 'primary' + }); + + done(); + } catch (e) { + done(e); + } finally { + if (client) { + client.close(true); + } + } } ); }); @@ -51,11 +60,16 @@ describe('connection model connector', () => { it('should connect to `localhost:27018 with model`', (done) => { Connection.from('mongodb://localhost:27018', (parseErr, model) => { assert.equal(parseErr, null); - connect(model, setupListeners, (connectErr, client) => { - assert.equal(connectErr, null); - client.close(true); - done(); - }); + connect(model, setupListeners, + (connectErr, client) => { + if (connectErr) { + return done(connectErr); + } + + client.close(true); + done(); + } + ); }); }); @@ -63,8 +77,11 @@ describe('connection model connector', () => { connect( { port: 27018, host: 'localhost' }, setupListeners, - (err, client) => { - assert.equal(err, null); + (connectErr, client) => { + if (connectErr) { + return done(connectErr); + } + client.close(true); done(); } diff --git a/packages/connection-model/test/parse-and-build-uri.js b/packages/connection-model/test/parse-and-build-uri.js index 4ffdfeec372..9969181e442 100644 --- a/packages/connection-model/test/parse-and-build-uri.js +++ b/packages/connection-model/test/parse-and-build-uri.js @@ -31,20 +31,20 @@ const tests = [ description: 'with socketTimeoutMS', connectionString: 'mongodb://localhost:27017/sampleDb' + - '?socketTimeoutMS=30000&w=majority&readPreference=primary&ssl=false' + '?socketTimeoutMS=30000&w=majority&readPreference=primary&directConnection=true&ssl=false' // only: true // Uncomment this line to run only one test debugging purpose }, { description: 'with compression', connectionString: 'mongodb://localhost:27017/?compressors=snappy%2Czlib&' + - 'readPreference=primary&ssl=false' + 'readPreference=primary&directConnection=true&ssl=false' }, { description: 'with zlibCompressionLevel', connectionString: 'mongodb://localhost:27017/?zlibCompressionLevel=9&' + - 'readPreference=primary&ssl=false' + 'readPreference=primary&directConnection=true&ssl=false' }, { description: @@ -59,7 +59,7 @@ const tests = [ connectionString: 'mongodb://localhost:27017/test?' + 'maxPoolSize=50&minPoolSize=5&maxIdleTimeMS=1000&waitQueueMultiple=200&waitQueueTimeoutMS=100&' + - 'w=1&wTimeoutMS=2000&journal=true&readPreference=primary&ssl=false' + 'w=1&wTimeoutMS=2000&journal=true&readPreference=primary&directConnection=true&ssl=false' }, { description: 'with readConcernLevel', @@ -84,13 +84,13 @@ const tests = [ description: 'with authSource and authMechanism (SCRAM-SHA-1)', connectionString: 'mongodb://%40rlo:w%40of@localhost:27017/dogdb?authSource=catdb&' + - 'readPreference=primary&authMechanism=SCRAM-SHA-1&ssl=false' + 'readPreference=primary&authMechanism=SCRAM-SHA-1&directConnection=true&ssl=false' }, { description: 'with authSource and authMechanism (SCRAM-SHA-256)', connectionString: 'mongodb://%40rlo:w%40of@localhost:27017/dogdb?authSource=catdb&' + - 'authMechanism=SCRAM-SHA-256&readPreference=primary&ssl=false' + 'authMechanism=SCRAM-SHA-256&readPreference=primary&directConnection=true&ssl=false' }, { description: 'with password which is ignored for GSSAPI', @@ -101,7 +101,7 @@ const tests = [ expectedConnectionString: 'mongodb://%40rlo@localhost:27017/?' + 'authMechanism=GSSAPI&readPreference=primary&' + - 'authSource=%24external&ssl=false&authSource=$external' + 'authSource=%24external&directConnection=true&ssl=false&authSource=$external' }, { description: 'with authMechanismProperties and gssapiServiceName', @@ -109,7 +109,7 @@ const tests = [ 'mongodb://%40rlo@localhost:27017/?' + 'authMechanism=GSSAPI&readPreference=primary&' + 'authSource=%24external&authMechanismProperties=CANONICALIZE_HOST_NAME%3Atrue&' + - 'gssapiCanonicalizeHostName=true&ssl=false&authSource=$external' + 'gssapiCanonicalizeHostName=true&directConnection=true&ssl=false&authSource=$external' }, { description: @@ -123,22 +123,22 @@ const tests = [ description: 'with serverSelectionTryOnce', connectionString: 'mongodb://a:27017/?readPreference=primary&' + - 'serverSelectionTryOnce=false&ssl=false' + 'serverSelectionTryOnce=false&directConnection=true&ssl=false' }, { description: 'with appName', connectionString: - 'mongodb://localhost:27017/?readPreference=primary&appname=foo&ssl=false' + 'mongodb://localhost:27017/?readPreference=primary&appname=foo&directConnection=true&ssl=false' }, { description: 'with retryWrites', connectionString: - 'mongodb://hostname:27017/?readPreference=primary&retryWrites=true&ssl=false' + 'mongodb://hostname:27017/?readPreference=primary&retryWrites=true&directConnection=true&ssl=false' }, { description: 'with uuidRepresentation', connectionString: - 'mongodb://foo:27017/?readPreference=primary&uuidRepresentation=csharpLegacy&ssl=false' + 'mongodb://foo:27017/?readPreference=primary&uuidRepresentation=csharpLegacy&directConnection=true&ssl=false' } ]; @@ -151,8 +151,12 @@ describe('connection model', () => { const c = new Connection(result.toJSON()); - expect(c.driverUrl).to.be.equal(test.expectedConnectionString || test.connectionString); - done(); + try { + expect(c.driverUrl).to.be.equal(test.expectedConnectionString || test.connectionString); + done(); + } catch (e) { + done(e); + } }); const runMode = test.only ? it.only : it; runMode(test.description, runTest); diff --git a/packages/connection-model/test/parse-uri-components.test.js b/packages/connection-model/test/parse-uri-components.test.js index 4835edc372a..71ff67eb7ac 100644 --- a/packages/connection-model/test/parse-uri-components.test.js +++ b/packages/connection-model/test/parse-uri-components.test.js @@ -549,16 +549,33 @@ describe('connection model partser should parse URI components such as', () => { ); }); - // Driver brought this behaviour back in v3.6.3+ (but will remove in v4), we don't need to handle directConnection ourselves - // See https://github.com/mongodb/node-mongodb-native/pull/2719 - describe.skip('directConnection', () => { - it('defaults directConnection undefined', (done) => { + describe('directConnection', () => { + it('defaults directConnection undefined for srv records', (done) => { Connection.from( - 'mongodb://localhost:27017', + 'mongodb+srv://user:password@compass-data-sets.e06dc.mongodb.net', (error, result) => { - expect(error).to.not.exist; - expect(result.directConnection).to.be.equal(undefined); - done(); + try { + expect(error).to.not.exist; + expect(result.directConnection).to.be.equal(undefined); + done(); + } catch (e) { + done(e); + } + } + ); + }); + + it('defaults directConnection undefined for multiple hosts', (done) => { + Connection.from( + 'mongodb://host1,host2,host3', + (error, result) => { + try { + expect(error).to.not.exist; + expect(result.directConnection).to.be.equal(undefined); + done(); + } catch (e) { + done(e); + } } ); });