26#ifndef MYSQLROUTER_CLUSTER_AWARE_SESSION_INCLUDED
27#define MYSQLROUTER_CLUSTER_AWARE_SESSION_INCLUDED
41#include <system_error>
45#include "mysqld_error.h"
67 const std::string &cluster_initial_username,
68 const std::string &cluster_initial_password,
69 const std::string &cluster_initial_hostname,
70 unsigned long cluster_initial_port,
71 const std::string &cluster_initial_socket,
72 unsigned long connection_timeout,
75 : metadata_(metadata),
76 cluster_initial_username_(cluster_initial_username),
77 cluster_initial_password_(cluster_initial_password),
78 cluster_initial_hostname_(cluster_initial_hostname),
79 cluster_initial_port_(cluster_initial_port),
80 cluster_initial_socket_(cluster_initial_socket),
81 connection_timeout_(connection_timeout),
82 failure_codes_(std::move(failure_codes)) {}
97 bool fetched_cluster_servers =
false;
98 std::vector<std::tuple<std::string, unsigned long>> cluster_servers;
100 auto cluster_servers_it = cluster_servers.begin();
101 const auto cluster_specific_initial_id =
102 metadata_.get_cluster_type_specific_id();
104 bool initial_node =
true;
106 bool skip_node =
false;
110 const auto cluster_specific_id =
111 metadata_.get_cluster_type_specific_id();
113 if (cluster_specific_id != cluster_specific_initial_id) {
115 "Node on '%s' that the bootstrap failed over to, seems to belong "
116 "to different cluster(%s != %s), skipping...",
117 metadata_.get_session().get_address().c_str(),
118 cluster_specific_initial_id.c_str(), cluster_specific_id.c_str());
122 initial_node =
false;
127 return wrapped_func();
132 "Executing statements failed with: '%s' (%d), trying to connect "
138 if (failure_codes_.find(ec) == failure_codes_.end()) {
146 if (!fetched_cluster_servers) {
149 fetched_cluster_servers =
true;
151 log_info(
"Fetching Cluster Members");
153 for (
auto &cluster_node : metadata_.fetch_cluster_hosts()) {
154 auto const &node_host = std::get<0>(cluster_node);
155 auto node_port = std::get<1>(cluster_node);
158 if (cluster_initial_socket_.size() == 0 &&
159 (node_host == cluster_initial_hostname_ &&
160 node_port == cluster_initial_port_)) {
164 log_debug(
"added cluster node: %s:%ld", node_host.c_str(),
166 cluster_servers.emplace_back(node_host, node_port);
170 cluster_servers_it = cluster_servers.begin();
172 std::advance(cluster_servers_it, 1);
175 if (cluster_servers_it == cluster_servers.end()) {
176 throw std::runtime_error(
177 "no more nodes to fail-over too, giving up.");
180 if (metadata_.get_session().is_connected()) {
181 log_debug(
"%s",
"disconnecting from mysql-server");
182 metadata_.get_session().disconnect();
185 auto const &tp = *cluster_servers_it;
187 auto const &
host = std::get<0>(tp);
188 auto port = std::get<1>(tp);
190 log_info(
"trying to connect to mysql-server at %s:%ld",
host.c_str(),
195 }
catch (
const std::exception &inner_e) {
196 log_info(
"Failed connecting to %s:%ld: %s, trying next",
host.c_str(),
197 port, inner_e.what());
204 metadata_.get_session().disconnect();
206 "Failed setting up a metadata session %s:%ld: %s, trying next",
211 }
while (!metadata_.get_session().is_connected());
219 const unsigned port);
Cluster (GR or AR)-aware decorator for MySQL Sessions.
Definition: cluster_aware_session.h:63
unsigned long cluster_initial_port_
Definition: cluster_aware_session.h:225
const std::string & cluster_initial_password_
Definition: cluster_aware_session.h:223
mysqlrouter::ClusterMetadata & metadata_
Definition: cluster_aware_session.h:221
virtual ~ClusterAwareDecorator()=default
R failover_on_failure(std::function< R()> wrapped_func)
Cluster (GR or AR) aware failover.
Definition: cluster_aware_session.h:96
ClusterAwareDecorator(mysqlrouter::ClusterMetadata &metadata, const std::string &cluster_initial_username, const std::string &cluster_initial_password, const std::string &cluster_initial_hostname, unsigned long cluster_initial_port, const std::string &cluster_initial_socket, unsigned long connection_timeout, std::set< MySQLErrorc > failure_codes={MySQLErrorc::kSuperReadOnly, MySQLErrorc::kLostConnection})
Definition: cluster_aware_session.h:65
const std::string & cluster_initial_username_
Definition: cluster_aware_session.h:222
unsigned long connection_timeout_
Definition: cluster_aware_session.h:227
std::set< MySQLErrorc > failure_codes_
Definition: cluster_aware_session.h:228
const std::string & cluster_initial_hostname_
Definition: cluster_aware_session.h:224
const std::string & cluster_initial_socket_
Definition: cluster_aware_session.h:226
Definition: mysql_session.h:288
unsigned int code() const
Definition: mysql_session.h:302
Definition: mysql_session.h:157
Log log_debug(std::cout, "DEBUG")
MySQLErrorc
Error codes for MySQL Errors that we handle specifically.
Definition: cluster_aware_session.h:55
#define CR_SERVER_LOST
Definition: errmsg.h:72
#define log_warning(...)
Definition: log_client.h:154
#define log_info(...)
Definition: log_client.h:153
Logging interface for using and extending the logging subsystem.
#define IMPORT_LOG_FUNCTIONS()
convenience macro to avoid common boilerplate
Definition: logging.h:323
const char * host
Definition: mysqladmin.cc:66
stdx::expected< void, std::string > ROUTER_CLUSTER_EXPORT setup_metadata_session(MySQLSession &session)
Definition: cluster_metadata.cc:1348
stdx::expected< void, error_type > connect(native_handle_type native_handle, const struct sockaddr *addr, size_t addr_len)
wrap connect() in a portable way.
Definition: socket.h:353
required uint64 port
Definition: replication_asynchronous_connection_failover.proto:33
#define ROUTER_CLUSTER_EXPORT
Definition: router_cluster_export.h:15