Request leadership on registering instance
This commit is contained in:
parent
17ad671773
commit
1ecf6ddab2
@ -42,6 +42,10 @@ auto CoordinatorClient::InstanceName() const -> std::string { return config_.ins
|
|||||||
auto CoordinatorClient::SocketAddress() const -> std::string { return rpc_client_.Endpoint().SocketAddress(); }
|
auto CoordinatorClient::SocketAddress() const -> std::string { return rpc_client_.Endpoint().SocketAddress(); }
|
||||||
|
|
||||||
void CoordinatorClient::StartFrequentCheck() {
|
void CoordinatorClient::StartFrequentCheck() {
|
||||||
|
if (instance_checker_.IsRunning()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
MG_ASSERT(config_.health_check_frequency_sec > std::chrono::seconds(0),
|
MG_ASSERT(config_.health_check_frequency_sec > std::chrono::seconds(0),
|
||||||
"Health check frequency must be greater than 0");
|
"Health check frequency must be greater than 0");
|
||||||
|
|
||||||
|
@ -220,13 +220,33 @@ auto CoordinatorInstance::RegisterReplicationInstance(CoordinatorClientConfig co
|
|||||||
return RegisterInstanceCoordinatorStatus::ENDPOINT_EXISTS;
|
return RegisterInstanceCoordinatorStatus::ENDPOINT_EXISTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!self_.RequestLeadership()) {
|
||||||
|
return RegisterInstanceCoordinatorStatus::NOT_LEADER;
|
||||||
|
}
|
||||||
|
|
||||||
|
// auto const res = self_.AppendRegisterReplicationInstance(config.instance_name);
|
||||||
|
|
||||||
|
// if (res->get_accepted()) {
|
||||||
|
// spdlog::info("Request for registering instance {} accepted", config.instance_name);
|
||||||
try {
|
try {
|
||||||
repl_instances_.emplace_back(this, std::move(config), replica_succ_cb_, replica_fail_cb_);
|
repl_instances_.emplace_back(this, std::move(config), replica_succ_cb_, replica_fail_cb_);
|
||||||
return RegisterInstanceCoordinatorStatus::SUCCESS;
|
|
||||||
|
|
||||||
} catch (CoordinatorRegisterInstanceException const &) {
|
} catch (CoordinatorRegisterInstanceException const &) {
|
||||||
return RegisterInstanceCoordinatorStatus::RPC_FAILED;
|
return RegisterInstanceCoordinatorStatus::RPC_FAILED;
|
||||||
}
|
}
|
||||||
|
// } else {
|
||||||
|
// spdlog::error(
|
||||||
|
// "Failed to accept request for registering instance {}. Most likely the reason is that the instance is not the
|
||||||
|
// " "leader.", config.instance_name);
|
||||||
|
// return RegisterInstanceCoordinatorStatus::RAFT_COULD_NOT_ACCEPT;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (res->get_result_code() != nuraft::cmd_result_code::OK) {
|
||||||
|
// spdlog::error("Failed to register instance {} with error code {}", config.instance_name, res->get_result_code());
|
||||||
|
// return RegisterInstanceCoordinatorStatus::RAFT_COULD_NOT_APPEND;
|
||||||
|
// }
|
||||||
|
|
||||||
|
spdlog::info("Instance {} registered", config.instance_name);
|
||||||
|
return RegisterInstanceCoordinatorStatus::SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto CoordinatorInstance::AddCoordinatorInstance(uint32_t raft_server_id, uint32_t raft_port, std::string raft_address)
|
auto CoordinatorInstance::AddCoordinatorInstance(uint32_t raft_server_id, uint32_t raft_port, std::string raft_address)
|
||||||
|
@ -50,5 +50,16 @@ class RaftAddServerException final : public utils::BasicException {
|
|||||||
SPECIALIZE_GET_EXCEPTION_NAME(RaftAddServerException)
|
SPECIALIZE_GET_EXCEPTION_NAME(RaftAddServerException)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class RaftBecomeLeaderException final : public utils::BasicException {
|
||||||
|
public:
|
||||||
|
explicit RaftBecomeLeaderException(std::string_view what) noexcept : BasicException(what) {}
|
||||||
|
|
||||||
|
template <class... Args>
|
||||||
|
explicit RaftBecomeLeaderException(fmt::format_string<Args...> fmt, Args &&...args) noexcept
|
||||||
|
: RaftBecomeLeaderException(fmt::format(fmt, std::forward<Args>(args)...)) {}
|
||||||
|
|
||||||
|
SPECIALIZE_GET_EXCEPTION_NAME(RaftBecomeLeaderException)
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace memgraph::coordination
|
} // namespace memgraph::coordination
|
||||||
#endif
|
#endif
|
||||||
|
@ -22,6 +22,7 @@ namespace memgraph::coordination {
|
|||||||
using BecomeLeaderCb = std::function<void()>;
|
using BecomeLeaderCb = std::function<void()>;
|
||||||
using BecomeFollowerCb = std::function<void()>;
|
using BecomeFollowerCb = std::function<void()>;
|
||||||
|
|
||||||
|
using nuraft::buffer;
|
||||||
using nuraft::logger;
|
using nuraft::logger;
|
||||||
using nuraft::ptr;
|
using nuraft::ptr;
|
||||||
using nuraft::raft_launcher;
|
using nuraft::raft_launcher;
|
||||||
@ -29,6 +30,7 @@ using nuraft::raft_server;
|
|||||||
using nuraft::srv_config;
|
using nuraft::srv_config;
|
||||||
using nuraft::state_machine;
|
using nuraft::state_machine;
|
||||||
using nuraft::state_mgr;
|
using nuraft::state_mgr;
|
||||||
|
using raft_result = nuraft::cmd_result<ptr<buffer>>;
|
||||||
|
|
||||||
class RaftInstance {
|
class RaftInstance {
|
||||||
public:
|
public:
|
||||||
@ -46,8 +48,11 @@ class RaftInstance {
|
|||||||
auto AddCoordinatorInstance(uint32_t raft_server_id, uint32_t raft_port, std::string raft_address) -> void;
|
auto AddCoordinatorInstance(uint32_t raft_server_id, uint32_t raft_port, std::string raft_address) -> void;
|
||||||
auto GetAllCoordinators() const -> std::vector<ptr<srv_config>>;
|
auto GetAllCoordinators() const -> std::vector<ptr<srv_config>>;
|
||||||
|
|
||||||
|
auto RequestLeadership() -> bool;
|
||||||
auto IsLeader() const -> bool;
|
auto IsLeader() const -> bool;
|
||||||
|
|
||||||
|
auto AppendRegisterReplicationInstance(std::string const &instance) -> ptr<raft_result>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ptr<state_machine> state_machine_;
|
ptr<state_machine> state_machine_;
|
||||||
ptr<state_mgr> state_manager_;
|
ptr<state_mgr> state_manager_;
|
||||||
|
@ -22,6 +22,9 @@ enum class RegisterInstanceCoordinatorStatus : uint8_t {
|
|||||||
ENDPOINT_EXISTS,
|
ENDPOINT_EXISTS,
|
||||||
NOT_COORDINATOR,
|
NOT_COORDINATOR,
|
||||||
RPC_FAILED,
|
RPC_FAILED,
|
||||||
|
NOT_LEADER,
|
||||||
|
RAFT_COULD_NOT_ACCEPT,
|
||||||
|
RAFT_COULD_NOT_APPEND,
|
||||||
SUCCESS
|
SUCCESS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -36,6 +36,19 @@ class CoordinatorStateMachine : public state_machine {
|
|||||||
CoordinatorStateMachine &operator=(CoordinatorStateMachine &&) = delete;
|
CoordinatorStateMachine &operator=(CoordinatorStateMachine &&) = delete;
|
||||||
~CoordinatorStateMachine() override {}
|
~CoordinatorStateMachine() override {}
|
||||||
|
|
||||||
|
static auto EncodeRegisterReplicationInstance(const std::string &name) -> ptr<buffer> {
|
||||||
|
std::string str_log = name + "_replica";
|
||||||
|
ptr<buffer> log = buffer::alloc(str_log.size());
|
||||||
|
buffer_serializer bs(log);
|
||||||
|
bs.put_str(str_log);
|
||||||
|
return log;
|
||||||
|
}
|
||||||
|
|
||||||
|
static auto DecodeRegisterReplicationInstance(buffer &data) -> std::string {
|
||||||
|
buffer_serializer bs(data);
|
||||||
|
return bs.get_str();
|
||||||
|
}
|
||||||
|
|
||||||
auto pre_commit(ulong log_idx, buffer &data) -> ptr<buffer> override;
|
auto pre_commit(ulong log_idx, buffer &data) -> ptr<buffer> override;
|
||||||
|
|
||||||
auto commit(ulong log_idx, buffer &data) -> ptr<buffer> override;
|
auto commit(ulong log_idx, buffer &data) -> ptr<buffer> override;
|
||||||
|
@ -72,6 +72,7 @@ RaftInstance::RaftInstance(BecomeLeaderCb become_leader_cb, BecomeFollowerCb bec
|
|||||||
|
|
||||||
raft_server_ = launcher_.init(state_machine_, state_manager_, logger_, static_cast<int>(raft_port_), asio_opts,
|
raft_server_ = launcher_.init(state_machine_, state_manager_, logger_, static_cast<int>(raft_port_), asio_opts,
|
||||||
params, init_opts);
|
params, init_opts);
|
||||||
|
raft_server_->request_leadership();
|
||||||
|
|
||||||
if (!raft_server_) {
|
if (!raft_server_) {
|
||||||
throw RaftServerStartException("Failed to launch raft server on {}", raft_endpoint);
|
throw RaftServerStartException("Failed to launch raft server on {}", raft_endpoint);
|
||||||
@ -111,5 +112,17 @@ auto RaftInstance::GetAllCoordinators() const -> std::vector<ptr<srv_config>> {
|
|||||||
|
|
||||||
auto RaftInstance::IsLeader() const -> bool { return raft_server_->is_leader(); }
|
auto RaftInstance::IsLeader() const -> bool { return raft_server_->is_leader(); }
|
||||||
|
|
||||||
|
auto RaftInstance::RequestLeadership() -> bool {
|
||||||
|
if (!raft_server_->is_leader()) {
|
||||||
|
raft_server_->request_leadership();
|
||||||
|
}
|
||||||
|
return raft_server_->is_leader();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto RaftInstance::AppendRegisterReplicationInstance(std::string const &instance) -> ptr<raft_result> {
|
||||||
|
auto new_log = CoordinatorStateMachine::EncodeRegisterReplicationInstance(instance);
|
||||||
|
return raft_server_->append_entries({new_log});
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace memgraph::coordination
|
} // namespace memgraph::coordination
|
||||||
#endif
|
#endif
|
||||||
|
@ -25,6 +25,8 @@ ReplicationInstance::ReplicationInstance(CoordinatorInstance *peer, CoordinatorC
|
|||||||
if (!client_.DemoteToReplica()) {
|
if (!client_.DemoteToReplica()) {
|
||||||
throw CoordinatorRegisterInstanceException("Failed to demote instance {} to replica", client_.InstanceName());
|
throw CoordinatorRegisterInstanceException("Failed to demote instance {} to replica", client_.InstanceName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
client_.StartFrequentCheck();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ReplicationInstance::OnSuccessPing() -> void {
|
auto ReplicationInstance::OnSuccessPing() -> void {
|
||||||
|
@ -500,6 +500,14 @@ class CoordQueryHandler final : public query::CoordinatorQueryHandler {
|
|||||||
"Couldn't register replica instance since instance with such endpoint already exists!");
|
"Couldn't register replica instance since instance with such endpoint already exists!");
|
||||||
case NOT_COORDINATOR:
|
case NOT_COORDINATOR:
|
||||||
throw QueryRuntimeException("REGISTER INSTANCE query can only be run on a coordinator!");
|
throw QueryRuntimeException("REGISTER INSTANCE query can only be run on a coordinator!");
|
||||||
|
case NOT_LEADER:
|
||||||
|
throw QueryRuntimeException("Couldn't register replica instance since coordinator is not a leader!");
|
||||||
|
case RAFT_COULD_NOT_ACCEPT:
|
||||||
|
throw QueryRuntimeException(
|
||||||
|
"Couldn't register replica instance since raft server couldn't accept the log! Most likely the raft "
|
||||||
|
"instance is not a leader!");
|
||||||
|
case RAFT_COULD_NOT_APPEND:
|
||||||
|
throw QueryRuntimeException("Couldn't register replica instance since raft server couldn't append the log!");
|
||||||
case RPC_FAILED:
|
case RPC_FAILED:
|
||||||
throw QueryRuntimeException(
|
throw QueryRuntimeException(
|
||||||
"Couldn't register replica instance because setting instance to replica failed! Check logs on replica to "
|
"Couldn't register replica instance because setting instance to replica failed! Check logs on replica to "
|
||||||
|
Loading…
Reference in New Issue
Block a user