Details
-
Improvement
-
Resolution: Won't Do
-
Unknown
-
None
-
None
-
None
-
(copied to CRM)
Description
This request is specifically for server-side connection limits being reached and not communicated back to the client application, however other server-side failures could be better reported to clients.
For example, after adapting the connection pooling example as follows:
// file: test.cpp
|
// build: c++ --std=c++11 test.cpp -o test $(pkg-config --cflags --libs libmongocxx) -lpthread
|
#include <iostream>
|
#include <ostream>
|
#include <sstream>
|
#include <thread>
|
#include <vector>
|
|
|
#include <bsoncxx/builder/basic/document.hpp>
|
#include <bsoncxx/builder/basic/kvp.hpp>
|
#include <bsoncxx/json.hpp>
|
#include <bsoncxx/types.hpp>
|
#include <mongocxx/client.hpp>
|
#include <mongocxx/instance.hpp>
|
#include <mongocxx/pool.hpp>
|
#include <mongocxx/uri.hpp>
|
|
|
using bsoncxx::builder::basic::kvp; |
|
|
int main() { |
// The mongocxx::instance constructor and destructor initialize and shut down the driver, |
// respectively. Therefore, a mongocxx::instance must be created before using the driver and |
// must remain alive for as long as the driver is in use. |
mongocxx::instance inst{};
|
mongocxx::uri uri{"mongodb://localhost:27017/?minPoolSize=5&maxPoolSize=5"}; |
|
|
mongocxx::pool pool{uri};
|
|
|
std::vector<std::string> collection_names = {"foo", "bar", "baz"}; |
std::vector<std::thread> threads{}; |
|
|
for (auto i : {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}) { |
auto run = [&](std::int64_t j) {
|
// Each client and collection can only be used in a single thread. |
auto client = pool.acquire();
|
auto coll = (*client)["test"][collection_names[static_cast<std::size_t>(j)]]; |
coll.delete_many({});
|
|
|
bsoncxx::types::b_int64 index = {j};
|
coll.insert_one(bsoncxx::builder::basic::make_document(kvp("x", index))); |
|
|
if (auto doc = |
(*client)["test"][collection_names[static_cast<std::size_t>(j)]].find_one({})) { |
// In order to ensure that the newline is printed immediately after the document, |
// they need to be streamed to std::cout as a single string. |
std::stringstream ss;
|
ss << bsoncxx::to_json(*doc) << std::endl;
|
|
|
std::cout << ss.str();
|
}
|
|
|
// The client goes out of scope at the end of the lambda and is returned to the pool. |
};
|
|
|
std::thread runner{run, i}; |
|
|
threads.push_back(std::move(runner));
|
}
|
|
|
for (auto&& runner : threads) { |
runner.join();
|
}
|
}
|
And starting up a mongod with a hard limit of 5 simultaneous connections :
m 4.4.9-ent
|
rm -rf data && mkdir data |
mongod --dbpath data --maxConns 5
|
The application will fail with:
terminate called after throwing an instance of 'mongocxx::v_noabi::bulk_write_exception'
|
what(): Failed to send "isMaster" command with database "admin": socket error or timeout: generic server error
|
Aborted (core dumped)
|
The error message is not obviously actionable, though the mongod log in this case contains details that identify the cause of the failure:
{"t":{"$date":"2021-10-05T10:59:55.937-04:00"},"s":"I","c":"NETWORK","id":51800,"ctx":"conn24","msg":"client metadata","attr":{"remote":"127.0.0.1:36876","client":"conn24","doc":{"driver":{"name":"mongoc / mongocxx","version":"1.17.4 / 3.6.2"},"os":{"type":"Linux","name":"Linux Mint","version":"20.2","architecture":"x86_64"},"platform":"(null)cfg=0x02a15ea0e9 posix=200809 stdc=201710 CC=GCC 9.3.0 CFLAGS=\"\" LDFLAGS=\"\""}}}
{"t":{"$date":"2021-10-05T10:59:55.937-04:00"},"s":"I","c":"NETWORK","id":22942,"ctx":"listener","msg":"Connection refused because there are too many open connections","attr":{"connectionCount":6}}