diff --git a/src/mongocxx/include/mongocxx/v_noabi/mongocxx/exception/error_code.hpp b/src/mongocxx/include/mongocxx/v_noabi/mongocxx/exception/error_code.hpp index f319162a26..c75c0d0b79 100644 --- a/src/mongocxx/include/mongocxx/v_noabi/mongocxx/exception/error_code.hpp +++ b/src/mongocxx/include/mongocxx/v_noabi/mongocxx/exception/error_code.hpp @@ -108,6 +108,9 @@ enum class error_code : std::int32_t { // used. k_invalid_search_index_view, + // Timed out while waiting for a client to be returned to the pool + k_pool_wait_queue_timeout, + // Add new constant string message to error_code.cpp as well! }; diff --git a/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/exception/error_code.cpp b/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/exception/error_code.cpp index 01a850c77a..88c010ff76 100644 --- a/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/exception/error_code.cpp +++ b/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/exception/error_code.cpp @@ -92,6 +92,8 @@ class error_category final : public std::error_category { case error_code::k_invalid_search_index_view: return "invalid use of default constructed or moved-from " "mongocxx::search_index_view object"; + case error_code::k_pool_wait_queue_timeout: + return "timed out while waiting for a client to be returned to the pool"; default: return "unknown mongocxx error"; } diff --git a/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/pool.cpp b/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/pool.cpp index 2bb2ba4c3f..4f8b1d6690 100644 --- a/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/pool.cpp +++ b/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/pool.cpp @@ -131,8 +131,14 @@ pool::entry::operator bool() const noexcept { pool::entry::entry(pool::entry::unique_client p) : _client(std::move(p)) {} pool::entry pool::acquire() { - return entry(entry::unique_client(new client(libmongoc::client_pool_pop(_impl->client_pool_t)), - [this](client* client) { _release(client); })); + auto cli = libmongoc::client_pool_pop(_impl->client_pool_t); + if (!cli) + throw exception{ + error_code::k_pool_wait_queue_timeout, + "failed to acquire client, possibly due to parameter 'waitQueueTimeoutMS' limits."}; + + return entry( + entry::unique_client(new client(cli), [this](client* client) { _release(client); })); } stdx::optional pool::try_acquire() { diff --git a/src/mongocxx/test/pool.cpp b/src/mongocxx/test/pool.cpp index a2f713264c..4fb1a29074 100644 --- a/src/mongocxx/test/pool.cpp +++ b/src/mongocxx/test/pool.cpp @@ -26,6 +26,7 @@ #include #include +#include namespace { using namespace mongocxx; @@ -183,4 +184,18 @@ TEST_CASE("a pool is created with an invalid connection string", "[pool]") { REQUIRE_THROWS_AS(pool{mongocxx::uri(uristr)}, operation_exception); } + +TEST_CASE("acquiring a client throws if waitQueueTimeoutMS expires", "[pool]") { + instance::current(); + mongocxx::pool pool{ + mongocxx::uri{"mongodb://localhost:27017/?waitQueueTimeoutMS=1&maxPoolSize=1"}, + options::pool(test_util::add_test_server_api())}; + // Acquire only available client: + auto client = pool.acquire(); + CHECK(client); + // Try to acquire again. Expect timeout: + REQUIRE_THROWS_WITH(pool.acquire(), + Catch::Matchers::ContainsSubstring("failed to acquire client")); +} + } // namespace