Skip to content

Commit

Permalink
HTTP APIs : SHOW QUERY, SHOW TRANSACTIONS, SHOW TRANSACTION (#2007)
Browse files Browse the repository at this point in the history
### What problem does this PR solve?

New HTTP APIs of:

- SHOW QUERY {QUERY_ID} (not documented)
- SHOW TRANSACTIONS
- SHOW TRANSACTION

Issue link: #1937 

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
- [x] Documentation Update

---------

Signed-off-by: vsian <[email protected]>
  • Loading branch information
vsian authored Oct 11, 2024
1 parent cfbc37b commit f9bcc48
Show file tree
Hide file tree
Showing 2 changed files with 256 additions and 0 deletions.
143 changes: 143 additions & 0 deletions docs/references/http_api_reference.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2635,7 +2635,150 @@ A `500` HTTP status code indicates an error condition. The response includes a J
---
## Show transactions
**GET** `/instance/transactions`
Shows running transactions on database.
### Request
- Method: GET
- URL: `/instance/transactions`
- Headers: `accept: application/json`
#### Request example
```shell
curl --request GET \
--url http://localhost:23820/instance/transactions \
--header 'accept: application/json'
```
### Response
<Tabs
defaultValue="s200"
values={[
{label: 'Status code 200', value: 's200'},
{label: 'Status code 500', value: 's500'},
]}>
<TabItem value="s200">
The response includes a JSON object like the following:
```shell
{
"error_code":0,
"transactions": [
{
"transaction_id":"27275",
"transaction_text":""
},
{
"transaction_id":"27274",
"transaction_text":""
}
]
}
```
- `"error_code"`: `integer`
`0`: The operation succeeds.
</TabItem>
<TabItem value="s500">
A `500` HTTP status code indicates an error condition. The response includes a JSON object like the following:
```shell
{
"error_code": 2005,
"error_message": "Not support in maintenance mode"
}
```
- `"error_code"`: `integer`
A non-zero value indicates a specific error condition.
- `"error_message"`: `string`
When `error_code` is non-zero, `"error_message"` provides additional details about the error.
</TabItem>
</Tabs>
---
## Show transaction
**GET** `/instance/transactions/{trasaction_id}`
Shows running transactions on database by transaction_id.
### Request
- Method: GET
- URL: `/instance/transactions`
- Headers: `accept: application/json`
#### Request example
```shell
curl --request GET \
--url http://localhost:23820/instance/transactions/{transaction_id} \
--header 'accept: application/json'
```
#### Request parameters
- `transaction_id`: (*Path parameter*)
The id of the running transaction.
### Response
<Tabs
defaultValue="s200"
values={[
{label: 'Status code 200', value: 's200'},
{label: 'Status code 500', value: 's500'},
]}>
<TabItem value="s200">
The response includes a JSON object like the following:
```shell
{
"error_code":0,
"transaction": {
"transaction_id":"27275",
"transaction_text":""
}
}
```
- `"error_code"`: `integer`
`0`: The operation succeeds.
</TabItem>
<TabItem value="s500">
A `500` HTTP status code indicates an error condition. The response includes a JSON object like the following:
```shell
{
"error_code": 2005,
"error_message": "Not support in maintenance mode"
}
```
- `"error_code"`: `integer`
A non-zero value indicates a specific error condition.
- `"error_message"`: `string`
When `error_code` is non-zero, `"error_message"` provides additional details about the error.
</TabItem>
</Tabs>
---
## Admin set node role
Expand Down
113 changes: 113 additions & 0 deletions src/network/http_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3590,6 +3590,116 @@ class ShowFullCheckpointHandler final : public HttpRequestHandler {
}
};


class ShowQueryHandler final : public HttpRequestHandler {
public:
SharedPtr<OutgoingResponse> handle(const SharedPtr<IncomingRequest> &request) final {
auto infinity = Infinity::RemoteConnect();
DeferFn defer_fn([&]() { infinity->RemoteDisconnect(); });

nlohmann::json json_response;
nlohmann::json json_table;
HTTPStatus http_status;
String query_id = request->getPathVariable("query_id");
QueryResult result = infinity->Query(fmt::format("show query {}", query_id));

if (result.IsOk()) {
DataBlock *data_block = result.result_table_->GetDataBlockById(0).get();
auto column_cnt = result.result_table_->ColumnCount();
for (SizeT col = 0; col < column_cnt; ++col) {
const String &column_name = result.result_table_->GetColumnNameById(col);
Value value = data_block->GetValue(col, 0);
const String &column_value = value.ToString();
json_table[column_name] = column_value;
}
json_response["query"] = 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 ShowTransactionsHandler final : public HttpRequestHandler {
public:
SharedPtr<OutgoingResponse> handle(const SharedPtr<IncomingRequest> &request) final {
auto infinity = Infinity::RemoteConnect();
DeferFn defer_fn([&]() { infinity->RemoteDisconnect(); });

nlohmann::json json_response;
HTTPStatus http_status;
QueryResult result = infinity->Query("show transactions");

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["transactions"].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 ShowTransactionHandler final : public HttpRequestHandler {
public:
SharedPtr<OutgoingResponse> handle(const SharedPtr<IncomingRequest> &request) final {
auto infinity = Infinity::RemoteConnect();
DeferFn defer_fn([&]() { infinity->RemoteDisconnect(); });

nlohmann::json json_response;
nlohmann::json json_table;
HTTPStatus http_status;
String transaction_id = request->getPathVariable("transaction_id");
QueryResult result = infinity->Query(fmt::format("show transaction {}", transaction_id));

if (result.IsOk()) {
DataBlock *data_block = result.result_table_->GetDataBlockById(0).get();
auto column_cnt = result.result_table_->ColumnCount();
for (SizeT col = 0; col < column_cnt; ++col) {
const String &column_name = result.result_table_->GetColumnNameById(col);
Value value = data_block->GetValue(col, 0);
const String &column_value = value.ToString();
json_table[column_name] = column_value;
}
json_response["error_code"] = 0;
json_response["transaction"]= json_table;
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<OutgoingResponse> handle(const SharedPtr<IncomingRequest> &request) final {
Expand Down Expand Up @@ -3926,6 +4036,9 @@ void HTTPServer::Start(const String &ip_address, u16 port) {
router->route("GET", "/instance/logs", MakeShared<ShowLogsHandler>());
router->route("GET", "/instance/delta_checkpoint", MakeShared<ShowDeltaCheckpointHandler>());
router->route("GET", "/instance/global_checkpoint", MakeShared<ShowFullCheckpointHandler>());
router->route("GET", "/instance/queries/{query_id}", MakeShared<ShowQueryHandler>());
router->route("GET", "/instance/transactions", MakeShared<ShowTransactionsHandler>());
router->route("GET", "/instance/transactions/{transaction_id}", MakeShared<ShowTransactionHandler>());

// variable
router->route("GET", "/variables/global", MakeShared<ShowGlobalVariablesHandler>());
Expand Down

0 comments on commit f9bcc48

Please sign in to comment.