diff --git a/src/client/options/mod.rs b/src/client/options/mod.rs index 604316fd1..59f7d2e32 100644 --- a/src/client/options/mod.rs +++ b/src/client/options/mod.rs @@ -1178,6 +1178,12 @@ impl ClientOptions { } } + if let Some(0) = self.max_pool_size { + return Err(crate::error::Error::invalid_argument( + "cannot specify maxPoolSize=0", + )); + } + Ok(()) } diff --git a/src/client/options/test.rs b/src/client/options/test.rs index 0281b0ccc..3266b66ff 100644 --- a/src/client/options/test.rs +++ b/src/client/options/test.rs @@ -53,6 +53,8 @@ async fn run_test(test_file: TestFile) { ) ) ) + // The Rust driver disallows `maxPoolSize=0`. + || test_case.description.contains("maxPoolSize=0 does not error") { continue; } @@ -113,6 +115,15 @@ async fn run_test(test_file: TestFile) { } } + // The default types parsed from the test file don't match those serialized + // from the `ClientOptions` struct. + if let Ok(min) = json_options.get_i32("minpoolsize") { + json_options.insert("minpoolsize", Bson::Int64(min.into())); + } + if let Ok(max) = json_options.get_i32("maxpoolsize") { + json_options.insert("maxpoolsize", Bson::Int64(max.into())); + } + options_doc = options_doc .into_iter() .filter(|(ref key, _)| json_options.contains_key(key)) diff --git a/src/cmap/worker.rs b/src/cmap/worker.rs index 3f32de55b..4a9fef297 100644 --- a/src/cmap/worker.rs +++ b/src/cmap/worker.rs @@ -340,6 +340,10 @@ impl ConnectionPoolWorker { }); } + fn below_max_connections(&self) -> bool { + self.total_connection_count < self.max_pool_size + } + fn can_service_connection_request(&self) -> bool { if !matches!(self.state, PoolState::Ready) { return false; @@ -349,8 +353,7 @@ impl ConnectionPoolWorker { return true; } - self.total_connection_count < self.max_pool_size - && self.pending_connection_count < MAX_CONNECTING + self.below_max_connections() && self.pending_connection_count < MAX_CONNECTING } async fn check_out(&mut self, request: ConnectionRequest) { @@ -381,7 +384,7 @@ impl ConnectionPoolWorker { } // otherwise, attempt to create a connection. - if self.total_connection_count < self.max_pool_size { + if self.below_max_connections() { let event_handler = self.event_handler.clone(); let establisher = self.establisher.clone(); let pending_connection = self.create_pending_connection(); diff --git a/src/error.rs b/src/error.rs index 08265a159..71dbd1d24 100644 --- a/src/error.rs +++ b/src/error.rs @@ -94,6 +94,13 @@ impl Error { .into() } + pub(crate) fn invalid_argument(message: impl Into) -> Error { + ErrorKind::InvalidArgument { + message: message.into(), + } + .into() + } + pub(crate) fn is_state_change_error(&self) -> bool { self.is_recovering() || self.is_not_master() } diff --git a/src/test/spec/json/uri-options/connection-pool-options.json b/src/test/spec/json/uri-options/connection-pool-options.json index be401f55d..aae16190b 100644 --- a/src/test/spec/json/uri-options/connection-pool-options.json +++ b/src/test/spec/json/uri-options/connection-pool-options.json @@ -2,13 +2,15 @@ "tests": [ { "description": "Valid connection pool options are parsed correctly", - "uri": "mongodb://example.com/?maxIdleTimeMS=50000", + "uri": "mongodb://example.com/?maxIdleTimeMS=50000&maxPoolSize=5&minPoolSize=3", "valid": true, "warning": false, "hosts": null, "auth": null, "options": { - "maxIdleTimeMS": 50000 + "maxIdleTimeMS": 50000, + "maxPoolSize": 5, + "minPoolSize": 3 } }, { @@ -28,6 +30,28 @@ "hosts": null, "auth": null, "options": {} + }, + { + "description": "maxPoolSize=0 does not error", + "uri": "mongodb://example.com/?maxPoolSize=0", + "valid": true, + "warning": false, + "hosts": null, + "auth": null, + "options": { + "maxPoolSize": 0 + } + }, + { + "description": "minPoolSize=0 does not error", + "uri": "mongodb://example.com/?minPoolSize=0", + "valid": true, + "warning": false, + "hosts": null, + "auth": null, + "options": { + "minPoolSize": 0 + } } ] } diff --git a/src/test/spec/json/uri-options/connection-pool-options.yml b/src/test/spec/json/uri-options/connection-pool-options.yml index 54cee220b..c0aeb01e7 100644 --- a/src/test/spec/json/uri-options/connection-pool-options.yml +++ b/src/test/spec/json/uri-options/connection-pool-options.yml @@ -1,13 +1,15 @@ tests: - description: "Valid connection pool options are parsed correctly" - uri: "mongodb://example.com/?maxIdleTimeMS=50000" + uri: "mongodb://example.com/?maxIdleTimeMS=50000&maxPoolSize=5&minPoolSize=3" valid: true warning: false hosts: ~ auth: ~ options: maxIdleTimeMS: 50000 + maxPoolSize: 5 + minPoolSize: 3 - description: "Non-numeric maxIdleTimeMS causes a warning" uri: "mongodb://example.com/?maxIdleTimeMS=invalid" @@ -24,3 +26,23 @@ tests: hosts: ~ auth: ~ options: {} + + - + description: "maxPoolSize=0 does not error" + uri: "mongodb://example.com/?maxPoolSize=0" + valid: true + warning: false + hosts: ~ + auth: ~ + options: + maxPoolSize: 0 + + - + description: "minPoolSize=0 does not error" + uri: "mongodb://example.com/?minPoolSize=0" + valid: true + warning: false + hosts: ~ + auth: ~ + options: + minPoolSize: 0