@@ -27,8 +27,8 @@ import {
2727} from '../error' ;
2828import { CancellationToken , TypedEventEmitter } from '../mongo_types' ;
2929import type { Server } from '../sdam/server' ;
30- import { Timeout , TimeoutError } from '../timeout' ;
31- import { type Callback , csotMin , List , makeCounter , promiseWithResolvers } from '../utils' ;
30+ import { type TimeoutContext , TimeoutError } from '../timeout' ;
31+ import { type Callback , List , makeCounter , promiseWithResolvers } from '../utils' ;
3232import { connect } from './connect' ;
3333import { Connection , type ConnectionEvents , type ConnectionOptions } from './connection' ;
3434import {
@@ -355,41 +355,15 @@ export class ConnectionPool extends TypedEventEmitter<ConnectionPoolEvents> {
355355 * will be held by the pool. This means that if a connection is checked out it MUST be checked back in or
356356 * explicitly destroyed by the new owner.
357357 */
358- async checkOut ( options ? : { timeout ?: Timeout } ) : Promise < Connection > {
358+ async checkOut ( options : { timeoutContext : TimeoutContext } ) : Promise < Connection > {
359359 this . emitAndLog (
360360 ConnectionPool . CONNECTION_CHECK_OUT_STARTED ,
361361 new ConnectionCheckOutStartedEvent ( this )
362362 ) ;
363363
364- const waitQueueTimeoutMS = this . options . waitQueueTimeoutMS ;
365- const serverSelectionTimeoutMS = this [ kServer ] . topology . s . serverSelectionTimeoutMS ;
366-
367364 const { promise, resolve, reject } = promiseWithResolvers < Connection > ( ) ;
368365
369- let timeout : Timeout | null = null ;
370- if ( options ?. timeout ) {
371- // CSOT enabled
372- // Determine if we're using the timeout passed in or a new timeout
373- if ( options . timeout . duration > 0 || serverSelectionTimeoutMS > 0 ) {
374- // This check determines whether or not Topology.selectServer used the configured
375- // `timeoutMS` or `serverSelectionTimeoutMS` value for its timeout
376- if (
377- options . timeout . duration === serverSelectionTimeoutMS ||
378- csotMin ( options . timeout . duration , serverSelectionTimeoutMS ) < serverSelectionTimeoutMS
379- ) {
380- // server selection used `timeoutMS`, so we should use the existing timeout as the timeout
381- // here
382- timeout = options . timeout ;
383- } else {
384- // server selection used `serverSelectionTimeoutMS`, so we construct a new timeout with
385- // the time remaining to ensure that Topology.selectServer and ConnectionPool.checkOut
386- // cumulatively don't spend more than `serverSelectionTimeoutMS` blocking
387- timeout = Timeout . expires ( serverSelectionTimeoutMS - options . timeout . timeElapsed ) ;
388- }
389- }
390- } else {
391- timeout = Timeout . expires ( waitQueueTimeoutMS ) ;
392- }
366+ const timeout = options . timeoutContext . connectionCheckoutTimeout ;
393367
394368 const waitQueueMember : WaitQueueMember = {
395369 resolve,
@@ -404,6 +378,7 @@ export class ConnectionPool extends TypedEventEmitter<ConnectionPoolEvents> {
404378 return await ( timeout ? Promise . race ( [ promise , timeout ] ) : promise ) ;
405379 } catch ( error ) {
406380 if ( TimeoutError . is ( error ) ) {
381+ timeout ?. clear ( ) ;
407382 waitQueueMember [ kCancelled ] = true ;
408383
409384 this . emitAndLog (
@@ -416,7 +391,7 @@ export class ConnectionPool extends TypedEventEmitter<ConnectionPoolEvents> {
416391 : 'Timed out while checking out a connection from connection pool' ,
417392 this . address
418393 ) ;
419- if ( options ?. timeout ) {
394+ if ( options . timeoutContext . csotEnabled ( ) ) {
420395 throw new MongoOperationTimeoutError ( 'Timed out during connection checkout' , {
421396 cause : timeoutError
422397 } ) ;
@@ -425,7 +400,7 @@ export class ConnectionPool extends TypedEventEmitter<ConnectionPoolEvents> {
425400 }
426401 throw error ;
427402 } finally {
428- if ( timeout !== options ?. timeout ) timeout ?. clear ( ) ;
403+ if ( options . timeoutContext . clearConnectionCheckoutTimeout ) timeout ?. clear ( ) ;
429404 }
430405 }
431406
0 commit comments