diff --git a/include/config.h b/include/config.h index 401b9333..73ab9046 100644 --- a/include/config.h +++ b/include/config.h @@ -252,12 +252,12 @@ public: this->enable_cors = reader.GetBoolean("server", "enable-cors", false); } - if(reader.Exists("server", "raft-port")) { + if(reader.Exists("server", "peering-port")) { this->raft_port = reader.GetInteger("server", "raft-port", 8107); } - if(reader.Exists("server", "raft-peers")) { - this->raft_peers = reader.Get("server", "raft-peers", ""); + if(reader.Exists("server", "peers")) { + this->raft_peers = reader.Get("server", "peers", ""); } } @@ -302,12 +302,12 @@ public: this->enable_cors = options.exist("enable-cors"); } - if(options.exist("raft-port")) { - this->raft_port = options.get("raft-port"); + if(options.exist("peering-port")) { + this->raft_port = options.get("peering-port"); } - if(options.exist("raft-peers")) { - this->raft_peers = options.get("raft-peers"); + if(options.exist("peers")) { + this->raft_peers = options.get("peers"); } } diff --git a/src/raft_server.cpp b/src/raft_server.cpp index e1420fcd..a960b434 100644 --- a/src/raft_server.cpp +++ b/src/raft_server.cpp @@ -29,7 +29,15 @@ int ReplicationState::start(int port, int election_timeout_ms, int snapshot_inte butil::EndPoint addr(butil::my_ip(), port); braft::NodeOptions node_options; - if(node_options.initial_conf.parse_from(peers) != 0) { + std::string actual_peers = peers; + + if(actual_peers == "::") { + char str[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &(addr.ip.s_addr), str, INET_ADDRSTRLEN); + actual_peers = std::string(str) + ":" + std::to_string(port) + ":0"; + } + + if(node_options.initial_conf.parse_from(actual_peers) != 0) { LOG(ERROR) << "Fail to parse peer configuration `" << peers << "`"; return -1; } @@ -76,9 +84,7 @@ int ReplicationState::start(int port, int election_timeout_ms, int snapshot_inte if(peer_vec.size() == 1) { // NOTE: `reset_peers` is NOT safe to run on a cluster of nodes, but okay for standalone - braft::Configuration conf; - conf.parse_from(peers); - auto status = node->reset_peers(conf); + auto status = node->reset_peers(node_options.initial_conf); if(!status.ok()) { LOG(ERROR) << status.error_str(); } diff --git a/src/typesense_server_utils.cpp b/src/typesense_server_utils.cpp index 750be208..e49367ef 100644 --- a/src/typesense_server_utils.cpp +++ b/src/typesense_server_utils.cpp @@ -86,8 +86,8 @@ void init_cmdline_options(cmdline::parser & options, int argc, char **argv) { options.add("listen-address", 'h', "Address to which Typesense server binds.", false, "0.0.0.0"); options.add("listen-port", 'p', "Port on which Typesense server listens.", false, 8108); - options.add("raft-port", '\0', "Port on which Typesense raft service listens.", false, 8107); - options.add("raft-peers", '\0', "Path to file with comma separated string of Raft node IPs.", false); + options.add("peering-port", '\0', "Port on which Typesense peering service listens.", false, 8107); + options.add("peers", '\0', "Path to file with comma separated string of peer node IPs.", false); options.add("master", 'm', "To start the server as read-only replica, " "provide the master's address in http(s)://: format.", @@ -147,12 +147,18 @@ int start_raft_server(ReplicationState& replication_state, const std::string& st // TODO: early returns must quit parent process as well const Option & peers_op = fetch_file_contents(path_to_peers); - if(!peers_op.ok()) { - LOG(ERR) << peers_op.error(); - return -1; - } + std::string peer_ips_string = "::"; - const std::string & peer_ips_string = peers_op.get(); + if(!peers_op.ok()) { + if(peers_op.code() == 404) { + LOG(INFO) << "Since no --peers argument is provided, starting a single node Typesense cluster."; + } else { + LOG(ERR) << peers_op.error(); + return -1; + } + } else { + peer_ips_string = peers_op.get(); + } if(peer_ips_string.empty()) { LOG(ERR) << "File containing raft peers is empty."; @@ -167,7 +173,7 @@ int start_raft_server(ReplicationState& replication_state, const std::string& st return -1; } - if (raft_server.Start(raft_port, NULL) != 0) { + if (raft_server.Start(raft_port, nullptr) != 0) { LOG(ERR) << "Failed to start raft server"; return -1; } @@ -186,7 +192,7 @@ int start_raft_server(ReplicationState& replication_state, const std::string& st // Wait until 'CTRL-C' is pressed. then Stop() and Join() the service size_t raft_counter = 0; while (!brpc::IsAskedToQuit()) { - if(++raft_counter % 10 == 0) { + if(++raft_counter % 10 == 0 && !path_to_peers.empty()) { // reset peer configuration periodically to identify change in cluster membership const Option & refreshed_peers_op = fetch_file_contents(path_to_peers); if(!peers_op.ok()) { @@ -231,6 +237,12 @@ int run_server(const Config & config, const std::string & version, bool create_init_db_snapshot = false; // for importing raw DB from earlier versions if(!directory_exists(db_dir) && file_exists(data_dir+"/CURRENT") && file_exists(data_dir+"/IDENTITY")) { + if(!config.get_raft_peers().empty()) { + LOG(ERR) << "Your data directory needs to be migrated to the new format."; + LOG(ERR) << "To do that, please start the Typesense server without the --peers argument."; + return 1; + } + LOG(INFO) << "Migrating contents of data directory in a `db` sub-directory, as per the new data layout."; bool moved = mv_dir(data_dir, db_dir); if(!moved) {