Skip to main content

meta_srv/
cluster.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::any::Any;
16use std::collections::{HashMap, HashSet};
17use std::sync::Arc;
18use std::time::Duration;
19
20use api::v1::meta::cluster_client::ClusterClient;
21use api::v1::meta::{
22    BatchGetRequest as PbBatchGetRequest, BatchGetResponse as PbBatchGetResponse,
23    RangeRequest as PbRangeRequest, RangeResponse as PbRangeResponse, ResponseHeader,
24};
25use common_grpc::channel_manager::ChannelManager;
26use common_meta::datanode::{DatanodeStatKey, DatanodeStatValue};
27use common_meta::kv_backend::{KvBackend, ResettableKvBackendRef, TxnService};
28use common_meta::rpc::KeyValue;
29use common_meta::rpc::store::{
30    BatchDeleteRequest, BatchDeleteResponse, BatchGetRequest, BatchGetResponse, BatchPutRequest,
31    BatchPutResponse, CompareAndPutRequest, CompareAndPutResponse, DeleteRangeRequest,
32    DeleteRangeResponse, PutRequest, PutResponse, RangeRequest, RangeResponse,
33};
34use common_meta::util;
35use common_telemetry::warn;
36use derive_builder::Builder;
37use snafu::{OptionExt, ResultExt, ensure};
38
39use crate::error::{self, Result, match_for_io_error};
40use crate::metasrv::ElectionRef;
41
42pub type MetaPeerClientRef = Arc<MetaPeerClient>;
43
44#[derive(Builder)]
45pub struct MetaPeerClient {
46    election: Option<ElectionRef>,
47    in_memory: ResettableKvBackendRef,
48    #[builder(default = "ChannelManager::default()")]
49    channel_manager: ChannelManager,
50    #[builder(default = "3")]
51    max_retry_count: usize,
52    #[builder(default = "1000")]
53    retry_interval_ms: u64,
54}
55
56#[async_trait::async_trait]
57impl TxnService for MetaPeerClient {
58    type Error = error::Error;
59}
60
61#[async_trait::async_trait]
62impl KvBackend for MetaPeerClient {
63    fn name(&self) -> &str {
64        "MetaPeerClient"
65    }
66
67    fn as_any(&self) -> &dyn Any {
68        self
69    }
70
71    async fn range(&self, req: RangeRequest) -> Result<RangeResponse> {
72        if self.is_leader() {
73            return self
74                .in_memory
75                .range(req)
76                .await
77                .context(error::KvBackendSnafu);
78        }
79
80        let max_retry_count = self.max_retry_count;
81        let retry_interval_ms = self.retry_interval_ms;
82
83        for _ in 0..max_retry_count {
84            match self.remote_range(req.clone()).await {
85                Ok(res) => return Ok(res),
86                Err(e) => {
87                    if need_retry(&e) {
88                        warn!(e; "Encountered an error that need to retry");
89                        tokio::time::sleep(Duration::from_millis(retry_interval_ms)).await;
90                    } else {
91                        return Err(e);
92                    }
93                }
94            }
95        }
96
97        error::ExceededRetryLimitSnafu {
98            func_name: "range",
99            retry_num: max_retry_count,
100        }
101        .fail()
102    }
103
104    // MetaPeerClient does not support mutable methods listed below.
105    async fn put(&self, _req: PutRequest) -> Result<PutResponse> {
106        error::UnsupportedSnafu {
107            operation: "put".to_string(),
108        }
109        .fail()
110    }
111
112    async fn batch_put(&self, _req: BatchPutRequest) -> Result<BatchPutResponse> {
113        error::UnsupportedSnafu {
114            operation: "batch put".to_string(),
115        }
116        .fail()
117    }
118
119    // Get kv information from the leader's in_mem kv store
120    async fn batch_get(&self, req: BatchGetRequest) -> Result<BatchGetResponse> {
121        if self.is_leader() {
122            return self
123                .in_memory
124                .batch_get(req)
125                .await
126                .context(error::KvBackendSnafu);
127        }
128
129        let max_retry_count = self.max_retry_count;
130        let retry_interval_ms = self.retry_interval_ms;
131
132        for _ in 0..max_retry_count {
133            match self.remote_batch_get(req.keys.clone()).await {
134                Ok(res) => return Ok(res),
135                Err(e) => {
136                    if need_retry(&e) {
137                        warn!(e; "Encountered an error that need to retry");
138                        tokio::time::sleep(Duration::from_millis(retry_interval_ms)).await;
139                    } else {
140                        return Err(e);
141                    }
142                }
143            }
144        }
145
146        error::ExceededRetryLimitSnafu {
147            func_name: "batch_get",
148            retry_num: max_retry_count,
149        }
150        .fail()
151    }
152
153    async fn delete_range(&self, _req: DeleteRangeRequest) -> Result<DeleteRangeResponse> {
154        error::UnsupportedSnafu {
155            operation: "delete range".to_string(),
156        }
157        .fail()
158    }
159
160    async fn batch_delete(&self, _req: BatchDeleteRequest) -> Result<BatchDeleteResponse> {
161        error::UnsupportedSnafu {
162            operation: "batch delete".to_string(),
163        }
164        .fail()
165    }
166
167    async fn compare_and_put(&self, _req: CompareAndPutRequest) -> Result<CompareAndPutResponse> {
168        error::UnsupportedSnafu {
169            operation: "compare and put".to_string(),
170        }
171        .fail()
172    }
173
174    async fn put_conditionally(
175        &self,
176        _key: Vec<u8>,
177        _value: Vec<u8>,
178        _if_not_exists: bool,
179    ) -> Result<bool> {
180        error::UnsupportedSnafu {
181            operation: "put conditionally".to_string(),
182        }
183        .fail()
184    }
185
186    async fn delete(&self, _key: &[u8], _prev_kv: bool) -> Result<Option<KeyValue>> {
187        error::UnsupportedSnafu {
188            operation: "delete".to_string(),
189        }
190        .fail()
191    }
192}
193
194impl MetaPeerClient {
195    async fn get_dn_key_value(&self, keys_only: bool) -> Result<Vec<KeyValue>> {
196        let key = DatanodeStatKey::prefix_key();
197        let range_end = util::get_prefix_end_key(&key);
198        let range_request = RangeRequest {
199            key,
200            range_end,
201            keys_only,
202            ..Default::default()
203        };
204        self.range(range_request).await.map(|res| res.kvs)
205    }
206
207    // Get all datanode stat kvs from leader meta.
208    pub async fn get_all_dn_stat_kvs(&self) -> Result<HashMap<DatanodeStatKey, DatanodeStatValue>> {
209        let kvs = self.get_dn_key_value(false).await?;
210        to_stat_kv_map(kvs)
211    }
212
213    pub async fn get_node_cnt(&self) -> Result<i32> {
214        let kvs = self.get_dn_key_value(true).await?;
215        kvs.into_iter()
216            .map(|kv| {
217                kv.key
218                    .try_into()
219                    .context(error::InvalidDatanodeStatFormatSnafu {})
220            })
221            .collect::<Result<HashSet<DatanodeStatKey>>>()
222            .map(|hash_set| hash_set.len() as i32)
223    }
224
225    // Get datanode stat kvs from leader meta by input keys.
226    pub async fn get_dn_stat_kvs(
227        &self,
228        keys: Vec<DatanodeStatKey>,
229    ) -> Result<HashMap<DatanodeStatKey, DatanodeStatValue>> {
230        let stat_keys = keys.into_iter().map(|key| key.into()).collect();
231        let batch_get_req = BatchGetRequest { keys: stat_keys };
232
233        let res = self.batch_get(batch_get_req).await?;
234
235        to_stat_kv_map(res.kvs)
236    }
237
238    async fn remote_range(&self, req: RangeRequest) -> Result<RangeResponse> {
239        // Safety: when self.is_leader() == false, election must not empty.
240        let election = self.election.as_ref().unwrap();
241
242        let leader_addr = election.leader().await.context(error::KvBackendSnafu)?.0;
243
244        let channel = self
245            .channel_manager
246            .get(&leader_addr)
247            .context(error::CreateChannelSnafu)?;
248
249        let request = tonic::Request::new(PbRangeRequest::from(req));
250
251        let mut client =
252            common_grpc::configure_tonic_client!(ClusterClient::new(channel), self.channel_manager);
253        let response: PbRangeResponse = client
254            .range(request)
255            .await
256            .context(error::RangeSnafu)?
257            .into_inner();
258
259        check_resp_header(&response.header, Context { addr: &leader_addr })?;
260
261        Ok(RangeResponse {
262            kvs: response.kvs.into_iter().map(KeyValue::new).collect(),
263            more: response.more,
264        })
265    }
266
267    async fn remote_batch_get(&self, keys: Vec<Vec<u8>>) -> Result<BatchGetResponse> {
268        // Safety: when self.is_leader() == false, election must not empty.
269        let election = self.election.as_ref().unwrap();
270
271        let leader_addr = election.leader().await.context(error::KvBackendSnafu)?.0;
272
273        let channel = self
274            .channel_manager
275            .get(&leader_addr)
276            .context(error::CreateChannelSnafu)?;
277
278        let request = tonic::Request::new(PbBatchGetRequest {
279            keys,
280            ..Default::default()
281        });
282
283        let mut client =
284            common_grpc::configure_tonic_client!(ClusterClient::new(channel), self.channel_manager);
285        let response: PbBatchGetResponse = client
286            .batch_get(request)
287            .await
288            .context(error::BatchGetSnafu)?
289            .into_inner();
290
291        check_resp_header(&response.header, Context { addr: &leader_addr })?;
292
293        Ok(BatchGetResponse {
294            kvs: response.kvs.into_iter().map(KeyValue::new).collect(),
295        })
296    }
297
298    // Check if the meta node is a leader node.
299    // Note: when self.election is None, we also consider the meta node is leader
300    pub(crate) fn is_leader(&self) -> bool {
301        self.election
302            .as_ref()
303            .map(|election| election.is_leader())
304            .unwrap_or(true)
305    }
306
307    #[cfg(test)]
308    pub(crate) fn memory_backend(&self) -> ResettableKvBackendRef {
309        self.in_memory.clone()
310    }
311}
312
313fn to_stat_kv_map(kvs: Vec<KeyValue>) -> Result<HashMap<DatanodeStatKey, DatanodeStatValue>> {
314    let mut map = HashMap::with_capacity(kvs.len());
315    for kv in kvs {
316        let _ = map.insert(
317            kv.key
318                .try_into()
319                .context(error::InvalidDatanodeStatFormatSnafu {})?,
320            kv.value
321                .try_into()
322                .context(error::InvalidDatanodeStatFormatSnafu {})?,
323        );
324    }
325    Ok(map)
326}
327
328struct Context<'a> {
329    addr: &'a str,
330}
331
332fn check_resp_header(header: &Option<ResponseHeader>, ctx: Context) -> Result<()> {
333    let header = header
334        .as_ref()
335        .context(error::ResponseHeaderNotFoundSnafu)?;
336
337    ensure!(
338        !header.is_not_leader(),
339        error::IsNotLeaderSnafu {
340            node_addr: ctx.addr
341        }
342    );
343
344    Ok(())
345}
346
347fn need_retry(error: &error::Error) -> bool {
348    match error {
349        error::Error::IsNotLeader { .. } => true,
350        error::Error::Range { error, .. } | error::Error::BatchGet { error, .. } => {
351            match_for_io_error(error).is_some()
352        }
353        _ => false,
354    }
355}
356
357#[cfg(test)]
358mod tests {
359    use std::sync::Arc;
360    use std::sync::atomic::{AtomicI64, Ordering};
361
362    use api::v1::meta::cluster_server::{Cluster, ClusterServer};
363    use api::v1::meta::{
364        BatchGetRequest as PbBatchGetRequest, BatchGetResponse as PbBatchGetResponse, Error,
365        ErrorCode, MetasrvPeersRequest, MetasrvPeersResponse, RangeRequest as PbRangeRequest,
366        RangeResponse as PbRangeResponse, ResponseHeader,
367    };
368    use common_grpc::channel_manager::ChannelManager;
369    use common_meta::datanode::{DatanodeStatKey, DatanodeStatValue, Stat};
370    use common_meta::election::{Election, LeaderChangeMessage, LeaderValue, MetasrvNodeInfo};
371    use common_meta::kv_backend::KvBackend;
372    use common_meta::kv_backend::memory::MemoryKvBackend;
373    use common_meta::rpc::KeyValue;
374    use common_meta::rpc::store::RangeRequest;
375    use hyper_util::rt::TokioIo;
376    use tonic::{Request, Response, Status};
377    use tower::service_fn;
378
379    use super::{Context, MetaPeerClientBuilder, check_resp_header, to_stat_kv_map};
380    use crate::error;
381
382    struct FollowerElection {
383        leader_addr: String,
384    }
385
386    #[async_trait::async_trait]
387    impl Election for FollowerElection {
388        type Leader = LeaderValue;
389
390        fn is_leader(&self) -> bool {
391            false
392        }
393
394        fn in_leader_infancy(&self) -> bool {
395            false
396        }
397
398        async fn register_candidate(&self, _: &MetasrvNodeInfo) -> common_meta::error::Result<()> {
399            Ok(())
400        }
401
402        async fn all_candidates(&self) -> common_meta::error::Result<Vec<MetasrvNodeInfo>> {
403            Ok(vec![])
404        }
405
406        async fn campaign(&self) -> common_meta::error::Result<()> {
407            Ok(())
408        }
409
410        async fn leader(&self) -> common_meta::error::Result<Self::Leader> {
411            Ok(LeaderValue(self.leader_addr.clone()))
412        }
413
414        async fn resign(&self) -> common_meta::error::Result<()> {
415            Ok(())
416        }
417
418        fn subscribe_leader_change(&self) -> tokio::sync::broadcast::Receiver<LeaderChangeMessage> {
419            let (_, receiver) = tokio::sync::broadcast::channel(1);
420            receiver
421        }
422    }
423
424    struct RangeServer {
425        requested_limit: Arc<AtomicI64>,
426    }
427
428    #[async_trait::async_trait]
429    impl Cluster for RangeServer {
430        async fn batch_get(
431            &self,
432            _: Request<PbBatchGetRequest>,
433        ) -> std::result::Result<Response<PbBatchGetResponse>, Status> {
434            Err(Status::unimplemented("batch_get is not used in this test"))
435        }
436
437        async fn range(
438            &self,
439            request: Request<PbRangeRequest>,
440        ) -> std::result::Result<Response<PbRangeResponse>, Status> {
441            self.requested_limit
442                .store(request.into_inner().limit, Ordering::Relaxed);
443            Ok(Response::new(PbRangeResponse {
444                header: Some(ResponseHeader::success()),
445                kvs: vec![api::v1::meta::KeyValue {
446                    key: b"key".to_vec(),
447                    value: b"value".to_vec(),
448                }],
449                more: true,
450            }))
451        }
452
453        async fn metasrv_peers(
454            &self,
455            _: Request<MetasrvPeersRequest>,
456        ) -> std::result::Result<Response<MetasrvPeersResponse>, Status> {
457            Err(Status::unimplemented(
458                "metasrv_peers is not used in this test",
459            ))
460        }
461    }
462
463    #[tokio::test]
464    async fn test_follower_range_forwards_limit() {
465        let requested_limit = Arc::new(AtomicI64::new(0));
466        let range_server = RangeServer {
467            requested_limit: requested_limit.clone(),
468        };
469        let (client, server) = tokio::io::duplex(1024);
470        let _server_handle = tokio::spawn(async move {
471            tonic::transport::Server::builder()
472                .add_service(
473                    ClusterServer::new(range_server)
474                        .accept_compressed(tonic::codec::CompressionEncoding::Zstd)
475                        .send_compressed(tonic::codec::CompressionEncoding::Zstd),
476                )
477                .serve_with_incoming(futures::stream::iter([Ok::<_, std::io::Error>(server)]))
478                .await
479        });
480
481        let channel_manager = ChannelManager::new();
482        let mut client = Some(client);
483        channel_manager
484            .reset_with_connector(
485                "leader:0",
486                service_fn(move |_| {
487                    let client = client.take();
488                    async move {
489                        client
490                            .map(TokioIo::new)
491                            .ok_or_else(|| std::io::Error::other("client already taken"))
492                    }
493                }),
494            )
495            .unwrap();
496
497        let follower = MetaPeerClientBuilder::default()
498            .election(Some(Arc::new(FollowerElection {
499                leader_addr: "leader:0".to_string(),
500            })))
501            .in_memory(Arc::new(MemoryKvBackend::new()))
502            .channel_manager(channel_manager)
503            .max_retry_count(1)
504            .build()
505            .unwrap();
506
507        let response = follower
508            .range(RangeRequest {
509                key: b"key".to_vec(),
510                limit: 1,
511                ..Default::default()
512            })
513            .await
514            .unwrap();
515
516        assert_eq!(1, requested_limit.load(Ordering::Relaxed));
517        assert_eq!(1, response.kvs.len());
518        assert!(response.more);
519    }
520
521    #[test]
522    fn test_to_stat_kv_map() {
523        let stat_key = DatanodeStatKey { node_id: 100 };
524
525        let stat = Stat {
526            id: 100,
527            addr: "127.0.0.1:3001".to_string(),
528            ..Default::default()
529        };
530        let stat_val = DatanodeStatValue { stats: vec![stat] }.try_into().unwrap();
531
532        let kv = KeyValue {
533            key: stat_key.into(),
534            value: stat_val,
535        };
536
537        let kv_map = to_stat_kv_map(vec![kv]).unwrap();
538        assert_eq!(1, kv_map.len());
539        let _ = kv_map.get(&stat_key).unwrap();
540
541        let stat_val = kv_map.get(&stat_key).unwrap();
542        let stat = stat_val.stats.first().unwrap();
543
544        assert_eq!(100, stat.id);
545        assert_eq!("127.0.0.1:3001", stat.addr);
546    }
547
548    #[test]
549    fn test_check_resp_header() {
550        let header = Some(ResponseHeader {
551            error: None,
552            ..Default::default()
553        });
554        check_resp_header(&header, mock_ctx()).unwrap();
555
556        let result = check_resp_header(&None, mock_ctx());
557        assert!(result.is_err());
558        assert!(matches!(
559            result.err().unwrap(),
560            error::Error::ResponseHeaderNotFound { .. }
561        ));
562
563        let header = Some(ResponseHeader {
564            error: Some(Error {
565                code: ErrorCode::NotLeader as i32,
566                err_msg: "The current meta is not leader".to_string(),
567            }),
568            ..Default::default()
569        });
570        let result = check_resp_header(&header, mock_ctx());
571        assert!(result.is_err());
572        assert!(matches!(
573            result.err().unwrap(),
574            error::Error::IsNotLeader { .. }
575        ));
576    }
577
578    fn mock_ctx<'a>() -> Context<'a> {
579        Context { addr: "addr" }
580    }
581}