meta_srv/service/admin/
node_lease.rs

1// Copyright 2023 Greptime Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::collections::HashMap;
16
17use axum::Json;
18use axum::extract::State;
19use axum::response::{IntoResponse, Response};
20use serde::{Deserialize, Serialize};
21use snafu::ResultExt;
22use tonic::codegen::http;
23
24use crate::cluster::MetaPeerClientRef;
25use crate::discovery::lease::{LeaseValueAccessor, LeaseValueType};
26use crate::error::{self, Result};
27use crate::key::{DatanodeLeaseKey, LeaseValue};
28use crate::service::admin::HttpHandler;
29use crate::service::admin::util::ErrorHandler;
30
31#[derive(Clone)]
32pub struct NodeLeaseHandler {
33    pub meta_peer_client: MetaPeerClientRef,
34}
35
36impl NodeLeaseHandler {
37    async fn get_node_lease(&self) -> Result<LeaseValues> {
38        let leases = self
39            .meta_peer_client
40            .lease_values(LeaseValueType::Datanode)
41            .await?
42            .into_iter()
43            .collect::<HashMap<_, _>>();
44
45        let leases = leases
46            .into_iter()
47            .map(|(k, v)| HumanLease {
48                name: DatanodeLeaseKey { node_id: k },
49                human_time: common_time::Timestamp::new_millisecond(v.timestamp_millis)
50                    .to_local_string(),
51                lease: v,
52            })
53            .collect::<Vec<_>>();
54        Ok(LeaseValues { leases })
55    }
56}
57
58/// Get the node lease handler.
59#[axum_macros::debug_handler]
60pub(crate) async fn get(State(handler): State<NodeLeaseHandler>) -> Response {
61    handler
62        .get_node_lease()
63        .await
64        .map_err(ErrorHandler::new)
65        .map(Json)
66        .into_response()
67}
68
69#[async_trait::async_trait]
70impl HttpHandler for NodeLeaseHandler {
71    async fn handle(
72        &self,
73        _: &str,
74        _: http::Method,
75        _: &HashMap<String, String>,
76    ) -> Result<http::Response<String>> {
77        let result = self.get_node_lease().await?.try_into()?;
78
79        http::Response::builder()
80            .status(http::StatusCode::OK)
81            .body(result)
82            .context(error::InvalidHttpBodySnafu)
83    }
84}
85
86#[derive(Debug, Serialize, Deserialize)]
87pub struct HumanLease {
88    pub name: DatanodeLeaseKey,
89    pub human_time: String,
90    pub lease: LeaseValue,
91}
92
93#[derive(Debug, Serialize, Deserialize)]
94#[serde(transparent)]
95pub struct LeaseValues {
96    pub leases: Vec<HumanLease>,
97}
98
99impl TryFrom<LeaseValues> for String {
100    type Error = error::Error;
101
102    fn try_from(vals: LeaseValues) -> Result<Self> {
103        serde_json::to_string(&vals).context(error::SerializeToJsonSnafu {
104            input: format!("{vals:?}"),
105        })
106    }
107}