mirror of
https://github.com/pocoproject/poco.git
synced 2025-12-11 02:25:59 +01:00
221 lines
7.1 KiB
C++
221 lines
7.1 KiB
C++
//
|
|
// ReplicaSet.h
|
|
//
|
|
// Library: MongoDB
|
|
// Package: MongoDB
|
|
// Module: ReplicaSet
|
|
//
|
|
// Definition of the ReplicaSet class.
|
|
//
|
|
// Copyright (c) 2025, Applied Informatics Software Engineering GmbH.
|
|
// and Contributors.
|
|
//
|
|
// SPDX-License-Identifier: BSL-1.0
|
|
//
|
|
|
|
|
|
#ifndef MongoDB_ReplicaSet_INCLUDED
|
|
#define MongoDB_ReplicaSet_INCLUDED
|
|
|
|
|
|
#include "Poco/MongoDB/MongoDB.h"
|
|
#include "Poco/MongoDB/Connection.h"
|
|
#include "Poco/MongoDB/ReadPreference.h"
|
|
#include "Poco/MongoDB/TopologyDescription.h"
|
|
#include "Poco/Net/SocketAddress.h"
|
|
#include "Poco/Logger.h"
|
|
#include "Poco/Timespan.h"
|
|
#include <vector>
|
|
#include <string>
|
|
#include <thread>
|
|
#include <atomic>
|
|
#include <mutex>
|
|
|
|
|
|
namespace Poco {
|
|
namespace MongoDB {
|
|
|
|
|
|
class MongoDB_API ReplicaSet
|
|
/// Class for working with a MongoDB replica set.
|
|
///
|
|
/// This class provides comprehensive replica set support including:
|
|
/// - Automatic topology discovery from seed servers
|
|
/// - Primary election detection
|
|
/// - Connection failover on errors
|
|
/// - Read preference routing (primary, secondary, nearest, etc.)
|
|
/// - Background topology monitoring
|
|
/// - Server health checking
|
|
///
|
|
/// Usage example:
|
|
/// ReplicaSet::Config config;
|
|
/// config.seeds = {
|
|
/// Net::SocketAddress("mongo1:27017"),
|
|
/// Net::SocketAddress("mongo2:27017"),
|
|
/// Net::SocketAddress("mongo3:27017")
|
|
/// };
|
|
/// config.setName = "rs0";
|
|
/// config.readPreference = ReadPreference::primaryPreferred();
|
|
///
|
|
/// ReplicaSet rs(config);
|
|
/// Connection::Ptr conn = rs.getPrimaryConnection();
|
|
/// // Use connection...
|
|
///
|
|
/// REQUIREMENTS:
|
|
/// Requires MongoDB 5.1 or later. Earlier versions using the legacy
|
|
/// isMaster command are not supported.
|
|
///
|
|
/// THREAD SAFETY:
|
|
/// The ReplicaSet class is thread-safe. Multiple threads can call
|
|
/// getConnection() and other methods concurrently. However, the
|
|
/// returned Connection objects are NOT thread-safe and must be used
|
|
/// by only one thread at a time, or protected by external synchronization.
|
|
///
|
|
/// For multi-threaded applications, use ReplicaSetConnection with
|
|
/// connection pooling (PoolableObjectFactory pattern).
|
|
{
|
|
public:
|
|
struct Config
|
|
/// Replica set configuration
|
|
{
|
|
std::vector<Net::SocketAddress> seeds;
|
|
/// Seed servers for initial topology discovery.
|
|
/// At least one seed must be reachable.
|
|
|
|
std::string setName;
|
|
/// Expected replica set name.
|
|
/// If empty, will be discovered from servers.
|
|
|
|
ReadPreference readPreference{ReadPreference::Primary};
|
|
/// Default read preference for this replica set.
|
|
|
|
Poco::Timespan connectTimeout{10, 0};
|
|
/// Connection timeout (default: 10 seconds)
|
|
|
|
Poco::Timespan socketTimeout{30, 0};
|
|
/// Socket send/receive timeout (default: 30 seconds)
|
|
|
|
Poco::Timespan heartbeatFrequency{10, 0};
|
|
/// Topology monitoring interval (default: 10 seconds)
|
|
|
|
std::size_t serverReconnectRetries { 10 };
|
|
// Number of connection retries to a server/replica set if no server is available temporarily
|
|
|
|
std::chrono::seconds serverReconnectDelay { 1 };
|
|
// Delay between re-connects to a server/replica set if no server is available temporarily
|
|
|
|
bool enableMonitoring{true};
|
|
/// Enable background topology monitoring (default: true)
|
|
|
|
Connection::SocketFactory* socketFactory{nullptr};
|
|
/// Optional socket factory for SSL/TLS connections
|
|
|
|
Logger::Ptr logger;
|
|
/// Optional logger to write important information about replica set activity
|
|
};
|
|
|
|
explicit ReplicaSet(const Config& config);
|
|
/// Creates a ReplicaSet with the given configuration.
|
|
/// Performs initial topology discovery.
|
|
/// Throws Poco::IOException if initial discovery fails.
|
|
|
|
explicit ReplicaSet(const std::vector<Net::SocketAddress>& seeds);
|
|
/// Creates a ReplicaSet with default configuration and the given seed addresses.
|
|
/// Performs initial topology discovery.
|
|
/// Throws Poco::IOException if initial discovery fails.
|
|
|
|
explicit ReplicaSet(const std::string& uri);
|
|
/// Creates a ReplicaSet from a MongoDB URI.
|
|
/// Format: mongodb://host1:port1,host2:port2,...?options
|
|
///
|
|
/// Supported URI options:
|
|
/// - replicaSet=name - Replica set name
|
|
/// - readPreference=mode - primary|primaryPreferred|secondary|secondaryPreferred|nearest
|
|
/// - connectTimeoutMS=ms - Connection timeout in milliseconds
|
|
/// - socketTimeoutMS=ms - Socket timeout in milliseconds
|
|
/// - heartbeatFrequencyMS=ms - Heartbeat frequency in milliseconds
|
|
///
|
|
/// Example: mongodb://mongo1:27017,mongo2:27017,mongo3:27017/?replicaSet=rs0&readPreference=primaryPreferred
|
|
///
|
|
/// Throws Poco::SyntaxException if URI is invalid.
|
|
/// Throws Poco::UnknownURISchemeException if scheme is not "mongodb".
|
|
|
|
virtual ~ReplicaSet();
|
|
/// Destroys the ReplicaSet and stops background monitoring.
|
|
|
|
Connection::Ptr getConnection(const ReadPreference& readPref);
|
|
/// Returns a connection to a server matching the read preference.
|
|
/// Returns null if no suitable server is available.
|
|
|
|
Connection::Ptr getPrimaryConnection();
|
|
/// Returns a connection to the primary server.
|
|
/// Returns null if no primary is available.
|
|
|
|
Connection::Ptr getSecondaryConnection();
|
|
/// Returns a connection to a secondary server.
|
|
/// Returns null if no secondary is available.
|
|
|
|
[[nodiscard]] Config configuration() const;
|
|
// Returns a copy of replica set configuration.
|
|
|
|
[[nodiscard]] TopologyDescription topology() const;
|
|
/// Returns a copy of the current topology description.
|
|
|
|
void refreshTopology();
|
|
/// Forces an immediate topology refresh by querying all known servers.
|
|
|
|
void startMonitoring();
|
|
/// Starts the background monitoring thread if not already running.
|
|
|
|
void stopMonitoring();
|
|
/// Stops the background monitoring thread.
|
|
|
|
void setLogger(Logger::Ptr logger);
|
|
/// Sets the logger to log important replica set activity.
|
|
|
|
void setReadPreference(const ReadPreference& pref);
|
|
/// Sets the default read preference.
|
|
|
|
[[nodiscard]] ReadPreference readPreference() const;
|
|
/// Returns the default read preference.
|
|
|
|
[[nodiscard]] std::string setName() const;
|
|
/// Returns the replica set name, or empty if not discovered.
|
|
|
|
[[nodiscard]] bool hasPrimary() const;
|
|
/// Returns true if a primary server is known.
|
|
|
|
private:
|
|
void monitor() noexcept;
|
|
/// Background monitoring thread function.
|
|
|
|
Connection::Ptr selectServer(const ReadPreference& readPref);
|
|
/// Selects a server based on read preference and creates a connection.
|
|
|
|
Connection::Ptr createConnection(const Net::SocketAddress& address);
|
|
/// Creates a new connection to the specified address.
|
|
|
|
void updateTopologyFromHello(const Net::SocketAddress& address) noexcept;
|
|
/// Queries a server with 'hello' command and updates topology.
|
|
|
|
void updateTopologyFromAllServers() noexcept;
|
|
/// Queries all known servers and updates topology.
|
|
|
|
void parseURI(const std::string& uri);
|
|
/// Parses a MongoDB URI into configuration.
|
|
/// Extracts hosts and query parameters into _config.
|
|
|
|
Config _config;
|
|
TopologyDescription _topology;
|
|
mutable std::mutex _mutex;
|
|
std::thread _monitorThread;
|
|
std::atomic<bool> _stopMonitoring{false};
|
|
std::atomic<bool> _monitoringActive{false};
|
|
};
|
|
|
|
|
|
} } // namespace Poco::MongoDB
|
|
|
|
|
|
#endif // MongoDB_ReplicaSet_INCLUDED
|