diff --git a/package-lock.json b/package-lock.json index 05084a792b8..59d024a7f31 100644 --- a/package-lock.json +++ b/package-lock.json @@ -62,7 +62,7 @@ "yargs": "^17.7.2" }, "engines": { - "node": ">=14.20.1" + "node": ">=16.20.1" }, "optionalDependencies": { "saslprep": "^1.0.3" diff --git a/src/cmap/connection_pool_events.ts b/src/cmap/connection_pool_events.ts index 4c904441332..379bc2d5217 100644 --- a/src/cmap/connection_pool_events.ts +++ b/src/cmap/connection_pool_events.ts @@ -54,14 +54,19 @@ export abstract class ConnectionPoolMonitoringEvent { */ export class ConnectionPoolCreatedEvent extends ConnectionPoolMonitoringEvent { /** The options used to create this connection pool */ - options?: ConnectionPoolOptions; + options: Pick< + ConnectionPoolOptions, + 'maxPoolSize' | 'minPoolSize' | 'maxConnecting' | 'maxIdleTimeMS' | 'waitQueueTimeoutMS' + >; /** @internal */ name = CONNECTION_POOL_CREATED; /** @internal */ constructor(pool: ConnectionPool) { super(pool); - this.options = pool.options; + const { maxConnecting, maxPoolSize, minPoolSize, maxIdleTimeMS, waitQueueTimeoutMS } = + pool.options; + this.options = { maxConnecting, maxPoolSize, minPoolSize, maxIdleTimeMS, waitQueueTimeoutMS }; } } diff --git a/test/integration/connection-monitoring-and-pooling/connection_pool.test.ts b/test/integration/connection-monitoring-and-pooling/connection_pool.test.ts new file mode 100644 index 00000000000..3f4317e372c --- /dev/null +++ b/test/integration/connection-monitoring-and-pooling/connection_pool.test.ts @@ -0,0 +1,66 @@ +import { once } from 'node:events'; + +import { expect } from 'chai'; + +import { type ConnectionPoolCreatedEvent, type Db, type MongoClient } from '../../mongodb'; + +describe('Connection Pool', function () { + let client: MongoClient; + let db: Db; + afterEach(async function () { + if (client) { + if (db) { + await db.dropDatabase(); + } + await client.close(); + } + }); + describe('Events', function () { + describe('ConnectionPoolCreatedEvent', function () { + context('when no connection pool options are passed in', function () { + let pConnectionPoolCreated: Promise; + let connectionPoolCreated: ConnectionPoolCreatedEvent; + beforeEach(async function () { + client = this.configuration.newClient({}, {}); + pConnectionPoolCreated = once(client, 'connectionPoolCreated'); + await client.connect(); + + connectionPoolCreated = (await pConnectionPoolCreated)[0]; + }); + + it('the options field matches the default options', function () { + expect(connectionPoolCreated).to.have.deep.property('options', { + waitQueueTimeoutMS: 0, + maxIdleTimeMS: 0, + maxConnecting: 2, + minPoolSize: 0, + maxPoolSize: 100 + }); + }); + }); + + context('when valid non-default connection pool options are passed in', function () { + let pConnectionPoolCreated: Promise; + let connectionPoolCreated: ConnectionPoolCreatedEvent; + const options = { + waitQueueTimeoutMS: 2000, + maxIdleTimeMS: 1, + maxConnecting: 3, + minPoolSize: 1, + maxPoolSize: 101 + }; + beforeEach(async function () { + client = this.configuration.newClient({}, options); + pConnectionPoolCreated = once(client, 'connectionPoolCreated'); + await client.connect(); + + connectionPoolCreated = (await pConnectionPoolCreated)[0]; + }); + + it('the options field only contains keys and values matching the non-default options', function () { + expect(connectionPoolCreated).to.have.deep.property('options', options); + }); + }); + }); + }); +}); diff --git a/test/types/connection_pool_events.test-d.ts b/test/types/connection_pool_events.test-d.ts new file mode 100644 index 00000000000..a059e782cc0 --- /dev/null +++ b/test/types/connection_pool_events.test-d.ts @@ -0,0 +1,20 @@ +import { once } from 'events'; +import { expectType } from 'tsd'; + +import type { ConnectionPoolCreatedEvent } from '../mongodb'; +import { MongoClient } from '../mongodb'; + +const client: MongoClient = new MongoClient(''); +const p = once(client, 'connectionPoolCreated'); +await client.connect(); + +const ev: ConnectionPoolCreatedEvent = (await p)[0]; +expectType(ev); + +expectType<{ + maxPoolSize: number; + minPoolSize: number; + maxConnecting: number; + maxIdleTimeMS: number; + waitQueueTimeoutMS: number; +}>(ev.options); diff --git a/test/unit/cmap/connection_pool_events.test.ts b/test/unit/cmap/connection_pool_events.test.ts new file mode 100644 index 00000000000..54337fbaa27 --- /dev/null +++ b/test/unit/cmap/connection_pool_events.test.ts @@ -0,0 +1,61 @@ +import { expect } from 'chai'; + +import { type ConnectionPool, ConnectionPoolCreatedEvent } from '../../mongodb'; + +describe('Connection Pool Events', function () { + const connectionPoolMock = { + address: 'localhost:9000', + time: new Date() + }; + + describe('ConnectionPoolCreatedEvent', function () { + describe('constructor', function () { + context('when provided expected option fields', function () { + it(`Sets the allowed fields appropriately`, function () { + const options = { + maxIdleTimeMS: 0, + maxConnecting: 2, + minPoolSize: 0, + maxPoolSize: 100, + waitQueueTimeoutMS: 1000 + }; + const event = new ConnectionPoolCreatedEvent({ + ...connectionPoolMock, + options + } as unknown as ConnectionPool); + + expect(event).to.have.deep.property('options', options); + }); + }); + context('when provided unallowed fields', function () { + it('only stores expected fields', function () { + const options = { + maxIdleTimeMS: 0, + maxConnecting: 2, + minPoolSize: 0, + maxPoolSize: 100, + waitQueueTimeoutMS: 1000, + credentials: { + user: 'user', + pass: 'pass' + }, + foo: 'foo', + hello: 'world' + }; + const event = new ConnectionPoolCreatedEvent({ + ...connectionPoolMock, + options + } as unknown as ConnectionPool); + + expect(event).to.have.deep.property('options', { + maxIdleTimeMS: 0, + maxConnecting: 2, + minPoolSize: 0, + maxPoolSize: 100, + waitQueueTimeoutMS: 1000 + }); + }); + }); + }); + }); +});