@@ -3,6 +3,7 @@ import { once } from 'node:events';
33import { expect } from 'chai' ;
44
55import { type ConnectionPoolCreatedEvent , type Db , type MongoClient } from '../../mongodb' ;
6+ import { clearFailPoint , configureFailPoint , sleep } from '../../tools/utils' ;
67
78describe ( 'Connection Pool' , function ( ) {
89 let client : MongoClient ;
@@ -64,5 +65,89 @@ describe('Connection Pool', function () {
6465 } ) ;
6566 } ) ;
6667 } ) ;
68+
69+ const metadata : MongoDBMetadataUI = { requires : { mongodb : '>=4.4' , topology : 'single' } } ;
70+
71+ describe ( 'ConnectionCheckedInEvent' , metadata , function ( ) {
72+ let client : MongoClient ;
73+
74+ beforeEach ( async function ( ) {
75+ if ( ! this . configuration . filters . MongoDBVersionFilter . filter ( { metadata } ) ) {
76+ return ;
77+ }
78+ if ( ! this . configuration . filters . MongoDBTopologyFilter . filter ( { metadata } ) ) {
79+ return ;
80+ }
81+
82+ await configureFailPoint ( this . configuration , {
83+ configureFailPoint : 'failCommand' ,
84+ mode : 'alwaysOn' ,
85+ data : {
86+ failCommands : [ 'insert' ] ,
87+ blockConnection : true ,
88+ blockTimeMS : 500
89+ }
90+ } ) ;
91+
92+ client = this . configuration . newClient ( ) ;
93+ await client . connect ( ) ;
94+ await Promise . all ( Array . from ( { length : 100 } , ( ) => client . db ( ) . command ( { ping : 1 } ) ) ) ;
95+ } ) ;
96+
97+ afterEach ( async function ( ) {
98+ if ( this . configuration . filters . MongoDBVersionFilter . filter ( { metadata } ) ) {
99+ await clearFailPoint ( this . configuration ) ;
100+ }
101+ await client . close ( ) ;
102+ } ) ;
103+
104+ describe ( 'when a MongoClient is closed' , function ( ) {
105+ it (
106+ 'a connection pool emits checked in events for closed connections' ,
107+ metadata ,
108+ async ( ) => {
109+ const allClientEvents = [ ] ;
110+ const pushToClientEvents = e => allClientEvents . push ( e ) ;
111+
112+ client
113+ . on ( 'connectionCheckedOut' , pushToClientEvents )
114+ . on ( 'connectionCheckedIn' , pushToClientEvents )
115+ . on ( 'connectionClosed' , pushToClientEvents ) ;
116+
117+ const inserts = Promise . allSettled ( [
118+ client . db ( 'test' ) . collection ( 'test' ) . insertOne ( { a : 1 } ) ,
119+ client . db ( 'test' ) . collection ( 'test' ) . insertOne ( { a : 1 } ) ,
120+ client . db ( 'test' ) . collection ( 'test' ) . insertOne ( { a : 1 } )
121+ ] ) ;
122+
123+ // wait until all pings are pending on the server
124+ while ( allClientEvents . filter ( e => e . name === 'connectionCheckedOut' ) . length < 3 ) {
125+ await sleep ( 1 ) ;
126+ }
127+
128+ const insertConnectionIds = allClientEvents
129+ . filter ( e => e . name === 'connectionCheckedOut' )
130+ . map ( ( { address, connectionId } ) => `${ address } + ${ connectionId } ` ) ;
131+
132+ await client . close ( ) ;
133+
134+ const insertCheckInAndCloses = allClientEvents
135+ . filter ( e => e . name === 'connectionCheckedIn' || e . name === 'connectionClosed' )
136+ . filter ( ( { address, connectionId } ) =>
137+ insertConnectionIds . includes ( `${ address } + ${ connectionId } ` )
138+ ) ;
139+
140+ expect ( insertCheckInAndCloses ) . to . have . lengthOf ( 6 ) ;
141+
142+ // check that each check-in is followed by a close (not proceeded by one)
143+ expect ( insertCheckInAndCloses . map ( e => e . name ) ) . to . deep . equal (
144+ Array . from ( { length : 3 } , ( ) => [ 'connectionCheckedIn' , 'connectionClosed' ] ) . flat ( 1 )
145+ ) ;
146+
147+ await inserts ;
148+ }
149+ ) ;
150+ } ) ;
151+ } ) ;
67152 } ) ;
68153} ) ;
0 commit comments