Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/cmap/connect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ export async function prepareHandshakeDocument(
const options = authContext.options;
const compressors = options.compressors ? options.compressors : [];
const { serverApi } = authContext.connection;
const clientMetadata: Document = await options.extendedMetadata;
const clientMetadata: Document = await options.metadata;

const handshakeDoc: HandshakeDocument = {
[serverApi?.version || options.loadBalanced === true ? 'hello' : LEGACY_HELLO_COMMAND]: 1,
Expand Down
3 changes: 1 addition & 2 deletions src/cmap/connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,8 @@ export interface ConnectionOptions
socketTimeoutMS?: number;
/** @internal */
cancellationToken?: CancellationToken;
metadata: ClientMetadata;
/** @internal */
extendedMetadata: Promise<Document>;
metadata: Promise<ClientMetadata>;
/** @internal */
mongoLogger?: MongoLogger | undefined;
}
Expand Down
8 changes: 4 additions & 4 deletions src/cmap/connection_pool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -601,17 +601,17 @@ export class ConnectionPool extends TypedEventEmitter<ConnectionPoolEvents> {
}

private createConnection(callback: Callback<Connection>) {
// Note that metadata and extendedMetadata may have changed on the client but have
// been frozen here, so we pull the extendedMetadata promise always from the client
// no mattter what options were set at the construction of the pool.
// Note that metadata may have changed on the client but have
// been frozen here, so we pull the metadata promise always from the client
// no matter what options were set at the construction of the pool.
const connectOptions: ConnectionOptions = {
...this.options,
id: this.connectionCounter.next().value,
generation: this.generation,
cancellationToken: this.cancellationToken,
mongoLogger: this.mongoLogger,
authProviders: this.server.topology.client.s.authProviders,
extendedMetadata: this.server.topology.client.options.extendedMetadata
metadata: this.server.topology.client.options.metadata
};

this.pending++;
Expand Down
31 changes: 18 additions & 13 deletions src/cmap/handshake/client_metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ export function isDriverInfoEqual(info1: DriverInfo, info2: DriverInfo): boolean
}

/**
* @public
* @deprecated This interface will be made internal in the next major release.
* @internal
* @see https://github.com/mongodb/specifications/blob/master/source/mongodb-handshake/handshake.md#hello-command
*/
export interface ClientMetadata {
Expand All @@ -48,11 +47,14 @@ export interface ClientMetadata {
};
/** FaaS environment information */
env?: {
name: 'aws.lambda' | 'gcp.func' | 'azure.func' | 'vercel';
name?: 'aws.lambda' | 'gcp.func' | 'azure.func' | 'vercel';
timeout_sec?: Int32;
memory_mb?: Int32;
region?: string;
url?: string;
container?: {
runtime?: string;
orchestrator?: string;
};
};
}

Expand Down Expand Up @@ -103,10 +105,10 @@ type MakeClientMetadataOptions = Pick<MongoOptions, 'appName'>;
* 3. Omit the `env` document entirely.
* 4. Truncate `platform`. -- special we do not truncate this field
*/
export function makeClientMetadata(
export async function makeClientMetadata(
driverInfoList: DriverInfo[],
{ appName = '' }: MakeClientMetadataOptions
): ClientMetadata {
): Promise<ClientMetadata> {
const metadataDocument = new LimitedSizeDocument(512);

// Add app name first, it must be sent
Expand Down Expand Up @@ -178,19 +180,21 @@ export function makeClientMetadata(
}
}
}
return metadataDocument.toObject() as ClientMetadata;
return await addContainerMetadata(metadataDocument.toObject() as ClientMetadata);
}

let dockerPromise: Promise<boolean>;
type ContainerMetadata = NonNullable<NonNullable<ClientMetadata['env']>['container']>;
/** @internal */
async function getContainerMetadata() {
const containerMetadata: Record<string, any> = {};
async function getContainerMetadata(): Promise<ContainerMetadata> {
dockerPromise ??= fileIsAccessible('/.dockerenv');
const isDocker = await dockerPromise;

const { KUBERNETES_SERVICE_HOST = '' } = process.env;
const isKubernetes = KUBERNETES_SERVICE_HOST.length > 0 ? true : false;

const containerMetadata: ContainerMetadata = {};

if (isDocker) containerMetadata.runtime = 'docker';
if (isKubernetes) containerMetadata.orchestrator = 'kubernetes';

Expand All @@ -202,15 +206,16 @@ async function getContainerMetadata() {
* Re-add each metadata value.
* Attempt to add new env container metadata, but keep old data if it does not fit.
*/
export async function addContainerMetadata(
originalMetadata: ClientMetadata
): Promise<ClientMetadata> {
async function addContainerMetadata(originalMetadata: ClientMetadata): Promise<ClientMetadata> {
const containerMetadata = await getContainerMetadata();
if (Object.keys(containerMetadata).length === 0) return originalMetadata;

const extendedMetadata = new LimitedSizeDocument(512);

const extendedEnvMetadata = { ...originalMetadata?.env, container: containerMetadata };
const extendedEnvMetadata: NonNullable<ClientMetadata['env']> = {
...originalMetadata?.env,
container: containerMetadata
};

for (const [key, val] of Object.entries(originalMetadata)) {
if (key !== 'env') {
Expand Down
43 changes: 9 additions & 34 deletions src/mongo_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import { AuthMechanism } from './cmap/auth/providers';
import type { LEGAL_TCP_SOCKET_OPTIONS, LEGAL_TLS_SOCKET_OPTIONS } from './cmap/connect';
import type { Connection } from './cmap/connection';
import {
addContainerMetadata,
type ClientMetadata,
isDriverInfoEqual,
makeClientMetadata
Expand Down Expand Up @@ -408,31 +407,12 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
* The consolidate, parsed, transformed and merged options.
*/
public readonly options: Readonly<
Omit<
MongoOptions,
| 'monitorCommands'
| 'ca'
| 'crl'
| 'key'
| 'cert'
| 'driverInfo'
| 'additionalDriverInfo'
| 'metadata'
| 'extendedMetadata'
>
Omit<MongoOptions, 'monitorCommands' | 'ca' | 'crl' | 'key' | 'cert' | 'driverInfo'>
> &
Pick<
MongoOptions,
| 'monitorCommands'
| 'ca'
| 'crl'
| 'key'
| 'cert'
| 'driverInfo'
| 'additionalDriverInfo'
| 'metadata'
| 'extendedMetadata'
>;
Pick<MongoOptions, 'monitorCommands' | 'ca' | 'crl' | 'key' | 'cert' | 'driverInfo'> & {
/** @internal */
metadata: Promise<ClientMetadata>;
};

private driverInfoList: DriverInfo[] = [];

Expand Down Expand Up @@ -506,10 +486,9 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
if (isDuplicateDriverInfo) return;

this.driverInfoList.push(driverInfo);
this.options.metadata = makeClientMetadata(this.driverInfoList, this.options);
this.options.extendedMetadata = addContainerMetadata(this.options.metadata)
this.options.metadata = makeClientMetadata(this.driverInfoList, this.options)
.then(undefined, squashError)
.then(result => result ?? {}); // ensure Promise<Document>
.then(result => result ?? ({} as ClientMetadata)); // ensure Promise<Document>
}

/** @internal */
Expand Down Expand Up @@ -1105,12 +1084,8 @@ export interface MongoOptions
compressors: CompressorName[];
writeConcern: WriteConcern;
dbName: string;
/** @deprecated - Will be made internal in a future major release. */
metadata: ClientMetadata;
/** @deprecated - Will be made internal in a future major release. */
extendedMetadata: Promise<Document>;
/** @deprecated - Will be made internal in a future major release. */
additionalDriverInfo: DriverInfo[];
/** @internal */
metadata: Promise<ClientMetadata>;
/** @internal */
autoEncrypter?: AutoEncrypter;
/** @internal */
Expand Down
7 changes: 1 addition & 6 deletions src/sdam/topology.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,7 @@ export interface TopologyOptions extends BSONSerializeOptions, ServerOptions {
/** Indicates that a client should directly connect to a node without attempting to discover its topology type */
directConnection: boolean;
loadBalanced: boolean;
metadata: ClientMetadata;
extendedMetadata: Promise<Document>;
metadata: Promise<ClientMetadata>;
serverMonitoringMode: ServerMonitoringMode;
/** MongoDB server API version */
serverApi?: ServerApi;
Expand Down Expand Up @@ -750,10 +749,6 @@ export class Topology extends TypedEventEmitter<TopologyEvents> {
if (typeof callback === 'function') callback(undefined, true);
}

get clientMetadata(): ClientMetadata {
return this.s.options.metadata;
}

isConnected(): boolean {
return this.s.state === STATE_CONNECTED;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,7 @@ import {
} from '../../../src';
import { connect } from '../../../src/cmap/connect';
import { Connection } from '../../../src/cmap/connection';
import {
addContainerMetadata,
makeClientMetadata
} from '../../../src/cmap/handshake/client_metadata';
import { makeClientMetadata } from '../../../src/cmap/handshake/client_metadata';
import { MongoDBResponse } from '../../../src/cmap/wire_protocol/responses';
import { LEGACY_HELLO_COMMAND } from '../../../src/constants';
import { Topology } from '../../../src/sdam/topology';
Expand Down Expand Up @@ -51,8 +48,7 @@ describe('Connection', function () {
...commonConnectOptions,
connectionType: Connection,
...this.configuration.options,
metadata: makeClientMetadata([], {}),
extendedMetadata: addContainerMetadata(makeClientMetadata([], {}))
metadata: makeClientMetadata([], {})
};

let conn;
Expand All @@ -74,8 +70,7 @@ describe('Connection', function () {
connectionType: Connection,
...this.configuration.options,
monitorCommands: true,
metadata: makeClientMetadata([], {}),
extendedMetadata: addContainerMetadata(makeClientMetadata([], {}))
metadata: makeClientMetadata([], {})
};

let conn;
Expand Down Expand Up @@ -106,8 +101,7 @@ describe('Connection', function () {
connectionType: Connection,
...this.configuration.options,
monitorCommands: true,
metadata: makeClientMetadata([], {}),
extendedMetadata: addContainerMetadata(makeClientMetadata([], {}))
metadata: makeClientMetadata([], {})
};

let conn;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,8 @@ describe('Handshake Prose Tests', function () {
it('includes both container and FAAS provider information in the client metadata', async function () {
client = this.configuration.newClient();
await client.connect();
expect(client.topology?.s.options.extendedMetadata).to.exist;
const { env } = await client.topology.s.options.extendedMetadata;
expect(client.topology?.s.options.metadata).to.exist;
const { env } = await client.topology.s.options.metadata;

expect(env).to.deep.equal({
region: 'us-east-2',
Expand Down
Loading