@@ -3,6 +3,7 @@ import { once } from 'node:events';
3
3
import { expect } from 'chai' ;
4
4
5
5
import { type ConnectionPoolCreatedEvent , type Db , type MongoClient } from '../../mongodb' ;
6
+ import { clearFailPoint , configureFailPoint , sleep } from '../../tools/utils' ;
6
7
7
8
describe ( 'Connection Pool' , function ( ) {
8
9
let client : MongoClient ;
@@ -64,5 +65,89 @@ describe('Connection Pool', function () {
64
65
} ) ;
65
66
} ) ;
66
67
} ) ;
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
+ } ) ;
67
152
} ) ;
68
153
} ) ;
0 commit comments