diff --git a/packages/data-service/src/connection-storage.spec.ts b/packages/data-service/src/connection-storage.spec.ts index a1e17f2a26b..798a9a8738e 100644 --- a/packages/data-service/src/connection-storage.spec.ts +++ b/packages/data-service/src/connection-storage.spec.ts @@ -91,7 +91,7 @@ describe('ConnectionStorage', function () { id, connectionOptions: { connectionString: - 'mongodb://localhost:27017/?readPreference=primary&ssl=false', + 'mongodb://localhost:27017/?readPreference=primary&ssl=false&directConnection=true', }, }, ]); diff --git a/packages/data-service/src/legacy/legacy-connection-model.spec.ts b/packages/data-service/src/legacy/legacy-connection-model.spec.ts index ee7a99f40f5..74be352af72 100644 --- a/packages/data-service/src/legacy/legacy-connection-model.spec.ts +++ b/packages/data-service/src/legacy/legacy-connection-model.spec.ts @@ -39,6 +39,97 @@ describe('LegacyConnectionModel', function () { expect(id).to.deep.equal('1234-1234-1234-1234'); }); + it('add directConnection=true if is a single one host', async function () { + const { connectionOptions } = await createAndConvertModel( + 'mongodb://localhost:27017/admin', + { _id: '1234-1234-1234-1234' } + ); + + expect( + new ConnectionString( + connectionOptions.connectionString + ).searchParams.get('directConnection') + ).to.equal('true'); + }); + + it('does not alter directConnection=true', async function () { + const { connectionOptions } = await createAndConvertModel( + 'mongodb://localhost:27017/admin?directConnection=true', + { _id: '1234-1234-1234-1234' } + ); + + expect( + new ConnectionString( + connectionOptions.connectionString + ).searchParams.get('directConnection') + ).to.equal('true'); + }); + + it('does not alter directConnection=false', async function () { + const { connectionOptions } = await createAndConvertModel( + 'mongodb://localhost:27017/admin?directConnection=false', + { _id: '1234-1234-1234-1234' } + ); + + expect( + new ConnectionString( + connectionOptions.connectionString + ).searchParams.get('directConnection') + ).to.equal('false'); + }); + + it('does not add directConnection=true if replicaSet', async function () { + const { connectionOptions } = await createAndConvertModel( + 'mongodb://localhost:27017/admin?replicaSet=rs1', + { _id: '1234-1234-1234-1234' } + ); + + expect( + new ConnectionString( + connectionOptions.connectionString + ).searchParams.has('directConnection') + ).to.be.false; + }); + + it('does not add directConnection=true if srv', async function () { + const { connectionOptions } = await createAndConvertModel( + 'mongodb+srv://compass-data-sets.e06dc.mongodb.net', + { _id: '1234-1234-1234-1234' } + ); + + expect( + new ConnectionString( + connectionOptions.connectionString + ).searchParams.has('directConnection') + ).to.be.false; + }); + + it('does not add directConnection=true if loadBalanced', async function () { + const { connectionOptions } = await createAndConvertModel( + 'mongodb://localhost:27017/admin?loadBalanced=true', + { _id: '1234-1234-1234-1234' } + ); + + expect( + new ConnectionString( + connectionOptions.connectionString + ).searchParams.has('directConnection') + ).to.be.false; + }); + + it('does not add directConnection=true if multiple hosts', async function () { + const { connectionOptions } = await createAndConvertModel( + 'mongodb://localhost:27017,localhost2:27017/admin', + { _id: '1234-1234-1234-1234' } + ); + + expect( + new ConnectionString( + connectionOptions.connectionString + ).searchParams.has('directConnection') + ).to.be.false; + }); + it('removes appName if matches MongoDB Compass', async function () { const { connectionOptions } = await createAndConvertModel( 'mongodb://localhost:27017/admin?appName=MongoDB+Compass', diff --git a/packages/data-service/src/legacy/legacy-connection-model.ts b/packages/data-service/src/legacy/legacy-connection-model.ts index 9d272d619e5..0d87bc940c8 100644 --- a/packages/data-service/src/legacy/legacy-connection-model.ts +++ b/packages/data-service/src/legacy/legacy-connection-model.ts @@ -253,7 +253,41 @@ export function convertConnectionModelToInfo( info.lastUsed = legacyModel.lastUsed; } - return deleteCompassAppNameParam(info); + return deleteCompassAppNameParam(setDirectConnectionForSingleHosts(info)); +} + +function setDirectConnectionForSingleHosts(connectionInfo: ConnectionInfo) { + let connectionStringUrl; + + try { + connectionStringUrl = new ConnectionString( + connectionInfo.connectionOptions.connectionString, + { looseValidation: true } + ); + } catch { + return connectionInfo; + } + + const isLoadBalanced = + connectionStringUrl.searchParams.get('loadBalanced') === 'true'; + const isReplicaSet = + connectionStringUrl.isSRV || + connectionStringUrl.hosts.length > 1 || + connectionStringUrl.searchParams.has('replicaSet'); + const hasDirectConnection = + connectionStringUrl.searchParams.has('directConnection'); + + if (!isReplicaSet && !isLoadBalanced && !hasDirectConnection) { + connectionStringUrl.searchParams.set('directConnection', 'true'); + } + + return { + ...connectionInfo, + connectionOptions: { + ...connectionInfo.connectionOptions, + connectionString: connectionStringUrl.href, + }, + }; } function setConnectionStringParam(