Repository: robustmq/robustmq (language: rust)

Issue:
MINOR:  Add validation to the exists_idempotent_data method in GrpcPlacementService and fill in the test case
### What type of enhancement is this?

Refactor

### What does the enhancement do?

Add validation to the exists_idempotent_data method in GrpcPlacementService and fill in the test case. 

Tips:

You can implement the `ValidateExt` trait on `ExistsIdempotentDataRequest`, then invoke ` validate_ext ` function to achieve the validation functionality.

- you can locate the ValidateExt trait in the file: src\placement-center\src\server\grpc\validate.rs
- you need to add validation to the exists_idempotent_data method in this file:  src\placement-center\src\server\grpc\service_placement.rs
- you need to fill in the test case in this file: src\grpc-clients\tests\placement_test.rs

references:
- https://github.com/robustmq/robustmq/pull/548)https://github.com/robustmq/robustmq/pull/548

### Implementation challenges

_No response_


Discussion / hints:

Fix patch:
diff --git a/src/placement-center/src/server/grpc/service_inner.rs b/src/placement-center/src/server/grpc/service_inner.rs
index e0d3b104c..a9edc72e9 100644
--- a/src/placement-center/src/server/grpc/service_inner.rs
+++ b/src/placement-center/src/server/grpc/service_inner.rs
@@ -270,6 +270,9 @@ impl PlacementCenterService for GrpcPlacementService {
         request: Request<ExistsIdempotentDataRequest>,
     ) -> Result<Response<ExistsIdempotentDataReply>, Status> {
         let req = request.into_inner();
+
+        let _ = req.validate_ext()?;
+
         let storage = IdempotentStorage::new(self.rocksdb_engine_handler.clone());
         match storage.exists(&req.cluster_name, &req.producer_id, req.seq_num) {
             Ok(flag) => {
diff --git a/src/placement-center/src/server/grpc/validate.rs b/src/placement-center/src/server/grpc/validate.rs
index 3139da1be..e2c9eb3a0 100644
--- a/src/placement-center/src/server/grpc/validate.rs
+++ b/src/placement-center/src/server/grpc/validate.rs
@@ -16,8 +16,9 @@ use std::net::{IpAddr, SocketAddr};
 
 use common_base::error::common::CommonError;
 use protocol::placement_center::placement_center_inner::{
-    ClusterType, DeleteIdempotentDataRequest, GetResourceConfigRequest, NodeListRequest,
-    RegisterNodeRequest, SetIdempotentDataRequest, SetResourceConfigRequest, UnRegisterNodeRequest,
+    ClusterType, DeleteIdempotentDataRequest, ExistsIdempotentDataRequest,
+    GetResourceConfigRequest, NodeListRequest, RegisterNodeRequest, SetIdempotentDataRequest,
+    SetResourceConfigRequest, UnRegisterNodeRequest,
 };
 use protocol::placement_center::placement_center_mqtt::GetShareSubLeaderRequest;
 use tonic::Status;
@@ -165,6 +166,14 @@ impl ValidateExt for NodeListRequest {
     }
 }
 
+impl ValidateExt for ExistsIdempotentDataRequest {
+    fn validate_ext(&self) -> Result<(), Status> {
+        ensure_param_not_empty("cluster_name", &self.cluster_name)?;
+        ensure_param_not_empty("producer_id", &self.producer_id)?;
+        Ok(())
+    }
+}
+
 #[cfg(test)]
 mod validate_test {
     use super::*;


Test patch:
diff --git a/src/grpc-clients/tests/placement/mqtt/cluster_test.rs b/src/grpc-clients/tests/placement/mqtt/cluster_test.rs
index 6f97c0665..36eaad562 100644
--- a/src/grpc-clients/tests/placement/mqtt/cluster_test.rs
+++ b/src/grpc-clients/tests/placement/mqtt/cluster_test.rs
@@ -17,13 +17,14 @@ mod tests {
     use std::sync::Arc;
 
     use grpc_clients::placement::inner::call::{
-        cluster_status, delete_idempotent_data, get_resource_config, node_list, register_node,
-        set_resource_config, unregister_node,
+        cluster_status, delete_idempotent_data, exists_idempotent_data, get_resource_config,
+        node_list, register_node, set_resource_config, unregister_node,
     };
     use grpc_clients::pool::ClientPool;
     use protocol::placement_center::placement_center_inner::{
-        ClusterStatusRequest, ClusterType, DeleteIdempotentDataRequest, GetResourceConfigRequest,
-        NodeListRequest, RegisterNodeRequest, SetResourceConfigRequest, UnRegisterNodeRequest,
+        ClusterStatusRequest, ClusterType, DeleteIdempotentDataRequest,
+        ExistsIdempotentDataRequest, GetResourceConfigRequest, NodeListRequest,
+        RegisterNodeRequest, SetResourceConfigRequest, UnRegisterNodeRequest,
     };
 
     use crate::common::get_placement_addr;
@@ -253,4 +254,41 @@ mod tests {
                 .is_err()
         );
     }
+
+    #[tokio::test]
+    async fn exists_idempotent_data_test() {
+        let client_pool: Arc<ClientPool> = Arc::new(ClientPool::new(1));
+        let addrs = vec![get_placement_addr()];
+
+        let request = ClusterStatusRequest::default();
+        assert!(cluster_status(&client_pool, &addrs, request).await.is_ok());
+
+        let request = ExistsIdempotentDataRequest {
+            cluster_name: "test-cluster-name".to_string(),
+            producer_id: "2".to_string(),
+            seq_num: 1u64,
+        };
+        assert!(exists_idempotent_data(&client_pool, &addrs, request)
+            .await
+            .is_ok());
+
+        let request = ExistsIdempotentDataRequest {
+            cluster_name: "".to_string(),
+            producer_id: "2".to_string(),
+            seq_num: 2u64,
+        };
+        assert!(exists_idempotent_data(&client_pool, &addrs, request)
+            .await
+            .is_err());
+
+        let request = ExistsIdempotentDataRequest {
+            cluster_name: "test-cluster-name".to_string(),
+            producer_id: "".to_string(),
+            seq_num: 3u64,
+        };
+
+        assert!(exists_idempotent_data(&client_pool, &addrs, request)
+            .await
+            .is_err());
+    }
 }