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;
16use std::time::Duration;
17
18use axum::extract::State;
19use axum::response::{IntoResponse, Response};
20use axum::Json;
21use serde::{Deserialize, Serialize};
22use snafu::ResultExt;
23use tonic::codegen::http;
24
25use crate::cluster::MetaPeerClientRef;
26use crate::error::{self, Result};
27use crate::key::{DatanodeLeaseKey, LeaseValue};
28use crate::lease;
29use crate::service::admin::util::ErrorHandler;
30use crate::service::admin::HttpHandler;
31
32#[derive(Clone)]
33pub struct NodeLeaseHandler {
34    pub meta_peer_client: MetaPeerClientRef,
35}
36
37impl NodeLeaseHandler {
38    async fn get_node_lease(&self) -> Result<LeaseValues> {
39        let leases =
40            lease::alive_datanodes(&self.meta_peer_client, Duration::from_secs(u64::MAX)).await?;
41        let leases = leases
42            .into_iter()
43            .map(|(k, v)| HumanLease {
44                name: k,
45                human_time: common_time::Timestamp::new_millisecond(v.timestamp_millis)
46                    .to_local_string(),
47                lease: v,
48            })
49            .collect::<Vec<_>>();
50        Ok(LeaseValues { leases })
51    }
52}
53
54/// Get the node lease handler.
55#[axum_macros::debug_handler]
56pub(crate) async fn get(State(handler): State<NodeLeaseHandler>) -> Response {
57    handler
58        .get_node_lease()
59        .await
60        .map_err(ErrorHandler::new)
61        .map(Json)
62        .into_response()
63}
64
65#[async_trait::async_trait]
66impl HttpHandler for NodeLeaseHandler {
67    async fn handle(
68        &self,
69        _: &str,
70        _: http::Method,
71        _: &HashMap<String, String>,
72    ) -> Result<http::Response<String>> {
73        let result = self.get_node_lease().await?.try_into()?;
74
75        http::Response::builder()
76            .status(http::StatusCode::OK)
77            .body(result)
78            .context(error::InvalidHttpBodySnafu)
79    }
80}
81
82#[derive(Debug, Serialize, Deserialize)]
83pub struct HumanLease {
84    pub name: DatanodeLeaseKey,
85    pub human_time: String,
86    pub lease: LeaseValue,
87}
88
89#[derive(Debug, Serialize, Deserialize)]
90#[serde(transparent)]
91pub struct LeaseValues {
92    pub leases: Vec<HumanLease>,
93}
94
95impl TryFrom<LeaseValues> for String {
96    type Error = error::Error;
97
98    fn try_from(vals: LeaseValues) -> Result<Self> {
99        serde_json::to_string(&vals).context(error::SerializeToJsonSnafu {
100            input: format!("{vals:?}"),
101        })
102    }
103}