enh(MongoDB): Add read-preference validation to replica set connection and pool.

This commit is contained in:
Matej Kenda
2025-12-02 13:20:59 +01:00
parent e61f096f05
commit 90832a9610
3 changed files with 46 additions and 2 deletions

View File

@@ -100,6 +100,12 @@ public:
[[nodiscard]] bool isConnected() const;
/// Returns true if currently connected to a server.
[[nodiscard]] bool matchesReadPreference() const;
/// Returns true if the currently connected server still matches the read preference.
/// Returns false if not connected or if the server no longer satisfies the read preference.
/// This is useful for connection pool validation to detect when a server role has changed
/// (e.g., primary became secondary).
private:
void ensureConnection();
/// Ensures we have an active connection, creating one if needed.

View File

@@ -62,8 +62,10 @@ public:
bool validateObject(MongoDB::ReplicaSetConnection::Ptr pObject)
{
// Check if the connection is still valid
return pObject->isConnected();
// Check if the connection is still valid and matches the read preference.
// This ensures that if a server changes role (e.g., primary becomes secondary),
// the cached connection is invalidated and a new one is created.
return pObject->isConnected() && pObject->matchesReadPreference();
}
void activateObject(MongoDB::ReplicaSetConnection::Ptr pObject)

View File

@@ -116,6 +116,42 @@ bool ReplicaSetConnection::isConnected() const
}
bool ReplicaSetConnection::matchesReadPreference() const
{
if (!isConnected())
{
return false;
}
// Get the current topology
TopologyDescription topology = _replicaSet.topology();
// Get the server description for the currently connected server
ServerDescription server = topology.getServer(_connection->address());
// Check if the server is Unknown or has an error
if (server.type() == ServerDescription::Unknown || server.hasError())
{
return false;
}
// Use ReadPreference::selectServers to check if our current server
// would be selected with the current read preference
std::vector<ServerDescription> eligibleServers = _readPreference.selectServers(topology);
// Check if our current server is in the list of eligible servers
for (const auto& eligible : eligibleServers)
{
if (eligible.address() == _connection->address())
{
return true;
}
}
return false;
}
void ReplicaSetConnection::ensureConnection()
{
if (_connection.isNull())