@@ -45,6 +45,8 @@ internal class ConnectionPool {
4545 case opening( future: EventLoopFuture < OpaquePointer > )
4646 /// Indicates that the `ConnectionPool` is open and using the associated pointer to a `mongoc_client_pool_t`.
4747 case open( pool: OpaquePointer )
48+ /// Indicates that the `ConnectionPool` failed to open due to the associated error.
49+ case failedToOpen( error: Error )
4850 /// Indicates that the `ConnectionPool` is in the process of closing. Connections can be checked back in, but
4951 /// no new connections can be checked out.
5052 case closing( pool: OpaquePointer )
@@ -86,23 +88,38 @@ internal class ConnectionPool {
8688 ) throws {
8789 let poolFut = executor. execute ( on: nil ) { ( ) -> OpaquePointer in
8890 try connString. withMongocURI { uriPtr in
89- guard let pool = mongoc_client_pool_new ( uriPtr) else {
90- throw MongoError . InternalError ( message: " Failed to initialize libmongoc client pool " )
91+ var error = bson_error_t ( )
92+ // this can fail if e.g. an invalid option is specified via a TXT record.
93+ guard let pool = mongoc_client_pool_new_with_error ( uriPtr, & error) else {
94+ throw extractMongoError ( error: error)
9195 }
9296
93- guard mongoc_client_pool_set_error_api ( pool, MONGOC_ERROR_API_VERSION_2) else {
94- fatalError ( " Could not configure error handling on client pool " )
95- }
96-
97- // We always set min_heartbeat_frequency because the hard-coded default in the vendored mongoc
98- // was lowered to 50. Setting it here brings it to whatever was specified, or 500 if it wasn't.
99- mongoc_client_pool_set_min_heartbeat_frequency_msec ( pool, UInt64 ( connString. minHeartbeatFrequencyMS) )
97+ do {
98+ // this should only fail due to an error of our own, e.g. calling this method multiple times or
99+ // passing in an invalid error API version.
100+ guard mongoc_client_pool_set_error_api ( pool, MONGOC_ERROR_API_VERSION_2) else {
101+ throw MongoError . InternalError ( message: " Could not configure error handling on client pool " )
102+ }
100103
101- try serverAPI? . withMongocServerAPI { apiPtr in
102- var error = bson_error_t ( )
103- guard mongoc_client_pool_set_server_api ( pool, apiPtr, & error) else {
104- throw extractMongoError ( error: error)
104+ // We always set min_heartbeat_frequency because the hard-coded default in the vendored mongoc
105+ // was lowered to 50. Setting it here brings it to whatever was specified, or 500 if it wasn't.
106+ mongoc_client_pool_set_min_heartbeat_frequency_msec (
107+ pool,
108+ UInt64 ( connString. minHeartbeatFrequencyMS)
109+ )
110+
111+ // this should only fail due to an error of our own, e.g. calling this method multiple times or
112+ // passing in an invalid API version.
113+ try serverAPI? . withMongocServerAPI { apiPtr in
114+ guard mongoc_client_pool_set_server_api ( pool, apiPtr, & error) else {
115+ throw extractMongoError ( error: error)
116+ }
105117 }
118+ } catch {
119+ // manually clean up the pool since we won't return it, which would be necessary for the usual
120+ // cleanup logic to execute.
121+ mongoc_client_pool_destroy ( pool)
122+ throw error
106123 }
107124
108125 return pool
@@ -130,9 +147,16 @@ internal class ConnectionPool {
130147 case let . open( pool) :
131148 return try body ( pool)
132149 case let . opening( future) :
133- let pool = try future. wait ( )
134- self . state = . open( pool: pool)
135- return try body ( pool)
150+ do {
151+ let pool = try future. wait ( )
152+ self . state = . open( pool: pool)
153+ return try body ( pool)
154+ } catch {
155+ self . state = . failedToOpen( error: error)
156+ throw error
157+ }
158+ case let . failedToOpen( error) :
159+ throw error
136160 case . closed, . closing:
137161 throw Self . PoolClosedError
138162 }
@@ -147,10 +171,18 @@ internal class ConnectionPool {
147171 case let . open( pool) :
148172 self . state = . closing( pool: pool)
149173 case let . opening( future) :
150- let pool = try future. wait ( )
151- self . state = . closing( pool: pool)
174+ do {
175+ let pool = try future. wait ( )
176+ self . state = . closing( pool: pool)
177+ } catch {
178+ self . state = . closed
179+ return
180+ }
152181 case . closing, . closed:
153182 throw Self . PoolClosedError
183+ case . failedToOpen:
184+ self . state = . closed
185+ return
154186 }
155187
156188 while self . connCount > 0 {
@@ -159,7 +191,7 @@ internal class ConnectionPool {
159191 }
160192
161193 switch self . state {
162- case . open, . closed, . opening:
194+ case . open, . closed, . opening, . failedToOpen :
163195 throw MongoError . InternalError (
164196 message: " ConnectionPool in unexpected state \( self . state) during close() "
165197 )
@@ -209,7 +241,7 @@ internal class ConnectionPool {
209241 self . stateLock. signal ( )
210242 case . closed:
211243 throw Self . PoolClosedError
212- case . opening:
244+ case . opening, . failedToOpen :
213245 fatalError ( " ConnectionPool in unexpected state \( self . state) while checking in a connection " )
214246 }
215247 }
0 commit comments