From 628a1af910895c672a5844ed09fea4aafbba391b Mon Sep 17 00:00:00 2001 From: vsian Date: Thu, 10 Oct 2024 20:00:49 +0800 Subject: [PATCH 1/2] Unifies http admin calls using infinity::admin* functions and update doc (#2006) ### What problem does this PR solve? _unify http admin calls using infinity::admin* functions and update doc_ ### Type of change - [x] Documentation Update - [x] Refactoring --- docs/references/http_api_reference.mdx | 47 +++---------- src/network/http_server.cpp | 94 +++++++++++++++----------- 2 files changed, 65 insertions(+), 76 deletions(-) diff --git a/docs/references/http_api_reference.mdx b/docs/references/http_api_reference.mdx index 820d343407..1218f5e42f 100644 --- a/docs/references/http_api_reference.mdx +++ b/docs/references/http_api_reference.mdx @@ -2641,7 +2641,7 @@ A `500` HTTP status code indicates an error condition. The response includes a J **POST** `/admin/node/current` -Set a node role. +Sets role for a node. ### Request @@ -2662,8 +2662,7 @@ curl --request POST \ '{ "role" : "follower", "name" : "following", - "address" : "0.0.0.0", - "port" : 23851 + "address" : "0.0.0.0:23851" }' ``` @@ -2677,7 +2676,6 @@ curl --request POST \ - Parameter settings for setting a node to `follower` or `learner`: - "name" Required : Name of the node in the cluster. - "address" Required : Peer server address of the leader in the cluster. - - "port" Required : Peer server port of the leader in the cluster. ### Response @@ -2726,7 +2724,7 @@ A `500` HTTP status code indicates an error condition. The response includes a J **GET** `/admin/variables` -Show all node variables in admin mode. +Shows all node variables in admin mode. ### Request @@ -2748,12 +2746,7 @@ None. ### Response - - +#### Status code 200 The response includes a JSON object like the following: @@ -2767,14 +2760,13 @@ The response includes a JSON object like the following: - `"error_code"`: `integer` `0`: The operation succeeds. - --- ## Admin show node configs **GET** `/admin/configs` -Show all node configs in admin mode. +Shows all node configs in admin mode. ### Request @@ -2836,8 +2828,6 @@ The response includes a JSON object like the following: } ``` - - --- ## Admin show node variable @@ -2913,7 +2903,7 @@ The response includes a JSON object like the following: **GET** `/admin/node/current` -Get information about the currently connected node. +Gets information about the currently connected node. ### Request @@ -2934,12 +2924,8 @@ curl --request GET \ None. ### Response - - + +#### Status code 200 The response includes a JSON object like the following: @@ -2955,16 +2941,13 @@ The response includes a JSON object like the following: - `"node_role": string` The role of querying node. - - - --- ## Admin show node **GET** `/admin/node/{node_name}` -Get information about a node in the cluster. +Gets information about a node in the cluster. ### Request @@ -3033,7 +3016,7 @@ A `500` HTTP status code indicates an error condition. The response includes a J **GET** `/admin/nodes` -List all nodes in the cluster. +Lists all nodes in the cluster. ### Request @@ -3055,12 +3038,7 @@ None. ### Response - - +#### Status code 200 The response includes a JSON object like the following: @@ -3080,9 +3058,6 @@ The response includes a JSON object like the following: - `"nodes" : array` : Each element is in `[nodename, noderole]` format. - - - --- diff --git a/src/network/http_server.cpp b/src/network/http_server.cpp index b325b4d13f..88ba30a06e 100644 --- a/src/network/http_server.cpp +++ b/src/network/http_server.cpp @@ -3473,7 +3473,7 @@ class ShowQueriesHandler final : public HttpRequestHandler { } }; -class ShowCurrentNodeHandler final : public HttpRequestHandler { +class AdminShowCurrentNodeHandler final : public HttpRequestHandler { public: SharedPtr handle(const SharedPtr &request) final { @@ -3488,7 +3488,7 @@ class ShowCurrentNodeHandler final : public HttpRequestHandler { if (result.IsOk()) { json_response["error_code"] = 0; DataBlock *data_block = result.result_table_->GetDataBlockById(0).get(); - Value value = data_block->GetValue(1, 0); + Value value = data_block->GetValue(1, 1); const String &variable_value = value.ToString(); json_response["role"] = variable_value; @@ -3502,7 +3502,7 @@ class ShowCurrentNodeHandler final : public HttpRequestHandler { } }; -class ShowNodeByNameHandler final : public HttpRequestHandler { +class AdminShowNodeByNameHandler final : public HttpRequestHandler { public: SharedPtr handle(const SharedPtr &request) final { auto infinity = Infinity::RemoteConnect(); @@ -3512,24 +3512,27 @@ class ShowNodeByNameHandler final : public HttpRequestHandler { HTTPStatus http_status; String node_name = request->getPathVariable("node_name"); - infinity::Status status; - SharedPtr nodeinfo; - std::tie(status, nodeinfo) = InfinityContext::instance().cluster_manager()->GetNodeInfoPtrByName(node_name); - if (status.ok()) { - http_status = HTTPStatus::CODE_200; + QueryResult result = infinity->AdminShowNode(node_name); + + if (result.IsOk()) { + DataBlock *data_block = result.result_table_->GetDataBlockById(0).get(); + Value value = data_block->GetValue(1, 1); + const String &node_role = value.ToString(); + json_response["error_code"] = ErrorCode::kOk; - json_response["node_role"] = ToString(nodeinfo->node_role_); + json_response["role"] = node_role; + http_status = HTTPStatus::CODE_200; } else { + json_response["error_code"] = result.ErrorCode(); + json_response["error_msg"] = result.ErrorMsg(); http_status = HTTPStatus::CODE_500; - json_response["error_code"] = status.code(); - json_response["error_msg"] = status.message(); } return ResponseFactory::createResponse(http_status, json_response.dump()); } }; -class ListAllNodesHandler final : public HttpRequestHandler { +class AdminListAllNodesHandler final : public HttpRequestHandler { public: SharedPtr handle(const SharedPtr &request) final { auto infinity = Infinity::RemoteConnect(); @@ -3539,15 +3542,26 @@ class ListAllNodesHandler final : public HttpRequestHandler { nlohmann::json json_response; nlohmann::json nodes_json; - Vector> nodes = InfinityContext::instance().cluster_manager()->ListNodes(); - for (const auto &ptr : nodes) { - nodes_json.push_back({ptr->node_name_, ToString(ptr->node_role_)}); + QueryResult result = infinity->AdminShowNodes(); + if (result.IsOk()) { + SizeT block_rows = result.result_table_->DataBlockCount(); + for (SizeT block_id = 0; block_id < block_rows; ++block_id) { + DataBlock *data_block = result.result_table_->GetDataBlockById(block_id).get(); + auto row_count = data_block->row_count(); + for (int row = 0; row < row_count; ++row) { + String node_name = data_block->GetValue(0, row).ToString(); + String node_role = data_block->GetValue(1, row).ToString(); + nodes_json.push_back({node_name, node_role}); + } + } + http_status = HTTPStatus::CODE_200; + json_response["error_code"] = ErrorCode::kOk; + json_response["nodes"] = nodes_json; + } else { + json_response["error_code"] = result.ErrorCode(); + json_response["error_message"] = result.ErrorMsg(); + http_status = HTTPStatus::CODE_500; } - - http_status = HTTPStatus::CODE_200; - json_response["error_code"] = ErrorCode::kOk; - json_response["nodes"] = nodes_json; - return ResponseFactory::createResponse(http_status, json_response.dump()); } }; @@ -3566,8 +3580,7 @@ class AdminSetNodeRoleHandler final : public HttpRequestHandler { nlohmann::json http_body_json; try { http_body_json = nlohmann::json::parse(data_body); - } - catch (nlohmann::json::exception &e) { + } catch (nlohmann::json::exception &e) { http_status = HTTPStatus::CODE_500; json_response["error_code"] = ErrorCode::kInvalidJsonFormat; json_response["error_message"] = e.what(); @@ -3582,32 +3595,32 @@ class AdminSetNodeRoleHandler final : public HttpRequestHandler { } String role = http_body_json["role"]; + QueryResult result; ToLower(role); - if (role == "uninitialized") { - status = InfinityContext::instance().ChangeRole(NodeRole::kUnInitialized); - } else if (role == "admin") { - status = InfinityContext::instance().ChangeRole(NodeRole::kAdmin); + if (role == "admin") { + result = infinity->AdminSetAdmin(); } else if (role == "standalone") { - status = InfinityContext::instance().ChangeRole(NodeRole::kStandalone); + result = infinity->AdminSetStandalone(); } else if (role == "leader") { - status = InfinityContext::instance().ChangeRole(NodeRole::kLeader, http_body_json["name"]); + result = infinity->AdminSetLeader(http_body_json["name"]); } else if (role == "follower") { - String node_name = http_body_json["name"]; - status = InfinityContext::instance().ChangeRole(NodeRole::kFollower, http_body_json["name"], http_body_json["address"], http_body_json["port"]); + result = infinity->AdminSetFollower(http_body_json["name"], http_body_json["address"]); } else if (role == "learner") { - String node_name = http_body_json["name"]; - status = InfinityContext::instance().ChangeRole(NodeRole::kLearner, http_body_json["name"], http_body_json["address"], http_body_json["port"]); + result = infinity->AdminSetLearner(http_body_json["name"], http_body_json["address"]); } else { - status = infinity::Status::InvalidNodeRole("invalid node role"); + http_status = HTTPStatus::CODE_500; + json_response["error_code"] = ErrorCode::kInvalidNodeRole; + json_response["error_code"] = "invalid node role"; + return ResponseFactory::createResponse(http_status, json_response.dump()); } - if (status.ok()) { + if (result.IsOk()) { http_status = HTTPStatus::CODE_200; json_response["error_code"] = ErrorCode::kOk; } else { http_status = HTTPStatus::CODE_500; - json_response["error_code"] = status.code(); - json_response["error_code"] = status.message(); + json_response["error_code"] = result.ErrorCode(); + json_response["error_code"] = result.ErrorMsg(); } return ResponseFactory::createResponse(http_status, json_response.dump()); @@ -3626,7 +3639,8 @@ class AdminShowNodeVariablesHandler final : public HttpRequestHandler { auto result = infinity->AdminShowVariables(); if (result.IsOk()) { json_response["error_code"] = 0; - DataBlock *data_block = result.result_table_->GetDataBlockById(0).get(); // Assume the variables output data only included in one data block + DataBlock *data_block = + result.result_table_->GetDataBlockById(0).get(); // Assume the variables output data only included in one data block auto row_count = data_block->row_count(); for (int row = 0; row < row_count; ++row) { // variable name @@ -3806,9 +3820,9 @@ void HTTPServer::Start(const String &ip_address, u16 port) { router->route("GET", "/admin/variables", MakeShared()); router->route("GET", "/admin/configs", MakeShared()); router->route("GET", "/admin/variables/{variable_name}", MakeShared()); - router->route("GET", "/admin/node/current", MakeShared()); - router->route("GET", "/admin/node/{node_name}", MakeShared()); - router->route("GET", "/admin/nodes", MakeShared()); + router->route("GET", "/admin/node/current", MakeShared()); + router->route("GET", "/admin/node/{node_name}", MakeShared()); + router->route("GET", "/admin/nodes", MakeShared()); SharedPtr connection_provider = HttpConnectionProvider::createShared({ip_address, port, WebAddress::IP_4}); SharedPtr connection_handler = HttpConnectionHandler::createShared(router); From cfbc37b5e08eeb2a7286081e82d9c048a7f0a86a Mon Sep 17 00:00:00 2001 From: vsian Date: Fri, 11 Oct 2024 00:14:53 +0800 Subject: [PATCH 2/2] http instance apis : logs, delta_checkpoint, global_checkpoint (#2010) ### What problem does this PR solve? 3 HTTP instance APIs: - show logs (not documented) - show delta checkpoints (not documented) - show full checkpoints (not documented) Issue link: #1937 ### Type of change - [x] New Feature (non-breaking change which adds functionality) --- src/network/http_server.cpp | 120 ++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) diff --git a/src/network/http_server.cpp b/src/network/http_server.cpp index 88ba30a06e..67c116dc4c 100644 --- a/src/network/http_server.cpp +++ b/src/network/http_server.cpp @@ -3473,6 +3473,123 @@ class ShowQueriesHandler final : public HttpRequestHandler { } }; +class ShowLogsHandler final : public HttpRequestHandler { +public: + SharedPtr handle(const SharedPtr &request) final { + auto infinity = Infinity::RemoteConnect(); + DeferFn defer_fn([&]() { infinity->RemoteDisconnect(); }); + + nlohmann::json json_response; + HTTPStatus http_status; + QueryResult result = infinity->ShowLogs(); + + if (result.IsOk()) { + SizeT block_rows = result.result_table_->DataBlockCount(); + for (SizeT block_id = 0; block_id < block_rows; ++block_id) { + DataBlock *data_block = result.result_table_->GetDataBlockById(block_id).get(); + auto row_count = data_block->row_count(); + auto column_cnt = result.result_table_->ColumnCount(); + for (int row = 0; row < row_count; ++row) { + nlohmann::json json_table; + for (SizeT col = 0; col < column_cnt; ++col) { + const String &column_name = result.result_table_->GetColumnNameById(col); + Value value = data_block->GetValue(col, row); + const String &column_value = value.ToString(); + json_table[column_name] = column_value; + } + json_response["logs"].push_back(json_table); + } + } + json_response["error_code"] = 0; + http_status = HTTPStatus::CODE_200; + } else { + json_response["error_code"] = result.ErrorCode(); + json_response["error_message"] = result.ErrorMsg(); + http_status = HTTPStatus::CODE_500; + } + + return ResponseFactory::createResponse(http_status, json_response.dump()); + } +}; + +class ShowDeltaCheckpointHandler final : public HttpRequestHandler { +public: + SharedPtr handle(const SharedPtr &request) final { + auto infinity = Infinity::RemoteConnect(); + DeferFn defer_fn([&]() { infinity->RemoteDisconnect(); }); + + nlohmann::json json_response; + HTTPStatus http_status; + QueryResult result = infinity->ShowDeltaCheckpoint(); + + if (result.IsOk()) { + SizeT block_rows = result.result_table_->DataBlockCount(); + for (SizeT block_id = 0; block_id < block_rows; ++block_id) { + DataBlock *data_block = result.result_table_->GetDataBlockById(block_id).get(); + auto row_count = data_block->row_count(); + auto column_cnt = result.result_table_->ColumnCount(); + for (int row = 0; row < row_count; ++row) { + nlohmann::json json_table; + for (SizeT col = 0; col < column_cnt; ++col) { + const String &column_name = result.result_table_->GetColumnNameById(col); + Value value = data_block->GetValue(col, row); + const String &column_value = value.ToString(); + json_table[column_name] = column_value; + } + json_response["delta_checkpoint"].push_back(json_table); + } + } + json_response["error_code"] = 0; + http_status = HTTPStatus::CODE_200; + } else { + json_response["error_code"] = result.ErrorCode(); + json_response["error_message"] = result.ErrorMsg(); + http_status = HTTPStatus::CODE_500; + } + + return ResponseFactory::createResponse(http_status, json_response.dump()); + } +}; + +class ShowFullCheckpointHandler final : public HttpRequestHandler { +public: + SharedPtr handle(const SharedPtr &request) final { + auto infinity = Infinity::RemoteConnect(); + DeferFn defer_fn([&]() { infinity->RemoteDisconnect(); }); + + nlohmann::json json_response; + HTTPStatus http_status; + QueryResult result = infinity->ShowFullCheckpoint(); + + if (result.IsOk()) { + SizeT block_rows = result.result_table_->DataBlockCount(); + for (SizeT block_id = 0; block_id < block_rows; ++block_id) { + DataBlock *data_block = result.result_table_->GetDataBlockById(block_id).get(); + auto row_count = data_block->row_count(); + auto column_cnt = result.result_table_->ColumnCount(); + for (int row = 0; row < row_count; ++row) { + nlohmann::json json_table; + for (SizeT col = 0; col < column_cnt; ++col) { + const String &column_name = result.result_table_->GetColumnNameById(col); + Value value = data_block->GetValue(col, row); + const String &column_value = value.ToString(); + json_table[column_name] = column_value; + } + json_response["global_checkpoint"].push_back(json_table); + } + } + json_response["error_code"] = 0; + http_status = HTTPStatus::CODE_200; + } else { + json_response["error_code"] = result.ErrorCode(); + json_response["error_message"] = result.ErrorMsg(); + http_status = HTTPStatus::CODE_500; + } + + return ResponseFactory::createResponse(http_status, json_response.dump()); + } +}; + class AdminShowCurrentNodeHandler final : public HttpRequestHandler { public: SharedPtr handle(const SharedPtr &request) final { @@ -3806,6 +3923,9 @@ void HTTPServer::Start(const String &ip_address, u16 port) { router->route("GET", "/instance/profiles", MakeShared()); router->route("GET", "/instance/memindex", MakeShared()); router->route("GET", "/instance/queries", MakeShared()); + router->route("GET", "/instance/logs", MakeShared()); + router->route("GET", "/instance/delta_checkpoint", MakeShared()); + router->route("GET", "/instance/global_checkpoint", MakeShared()); // variable router->route("GET", "/variables/global", MakeShared());