rocketmq_protocol/protocol/header/controller/
clean_broker_data_request_header.rs1use cheetah_string::CheetahString;
16use rocketmq_macros::RequestHeaderCodec;
17use serde::Deserialize;
18use serde::Serialize;
19
20fn default_invoke_time() -> u64 {
21 rocketmq_model::time::current_millis()
22}
23
24#[derive(Clone, Debug, Serialize, Deserialize, RequestHeaderCodec)]
25#[header(
26 type_id = "rocketmq_protocol::protocol::header::controller::clean_broker_data_request_header::CleanBrokerDataRequestHeader",
27 java_class = "org.apache.rocketmq.remoting.protocol.header.controller.admin.CleanControllerBrokerDataRequestHeader",
28 fast
29)]
30#[serde(rename_all = "camelCase")]
31pub struct CleanBrokerDataRequestHeader {
32 pub cluster_name: Option<CheetahString>,
33 #[header(required)]
34 pub broker_name: CheetahString,
35 pub broker_controller_ids_to_clean: Option<CheetahString>,
36 #[serde(rename = "isCleanLivingBroker", alias = "cleanLivingBroker")]
37 #[header(
38 key = "isCleanLivingBroker",
39 alias = "cleanLivingBroker",
40 alias_conflict = "prefer_canonical",
41 default,
42 default_semantic = "literal:false"
43 )]
44 pub clean_living_broker: bool,
45 #[serde(default = "default_invoke_time")]
46 #[header(
47 default_with = "default_invoke_time",
48 default_semantic = "dynamic:current_time_millis",
49 range = "i64"
50 )]
51 pub invoke_time: u64,
52}
53
54pub type CleanControllerBrokerDataRequestHeader = CleanBrokerDataRequestHeader;
55
56impl Default for CleanBrokerDataRequestHeader {
57 fn default() -> Self {
58 Self {
59 cluster_name: None,
60 broker_name: CheetahString::new(),
61 broker_controller_ids_to_clean: None,
62 clean_living_broker: false,
63 invoke_time: default_invoke_time(),
64 }
65 }
66}
67
68#[cfg(test)]
69mod tests {
70 use std::collections::HashMap;
71
72 use super::*;
73 use crate::protocol::command_custom_header::CommandCustomHeader;
74 use crate::protocol::command_custom_header::FromMap;
75
76 #[test]
77 fn clean_broker_data_request_header_serializes_correctly() {
78 let header = CleanBrokerDataRequestHeader {
79 cluster_name: Some(CheetahString::from_static_str("test_cluster")),
80 broker_name: CheetahString::from_static_str("test_broker"),
81 broker_controller_ids_to_clean: Some(CheetahString::from_static_str("1;2")),
82 clean_living_broker: true,
83 invoke_time: 1234567890,
84 };
85
86 let map = header.to_map().unwrap();
87 assert_eq!(
88 map.get(&CheetahString::from_static_str("clusterName")).unwrap(),
89 "test_cluster"
90 );
91 assert_eq!(
92 map.get(&CheetahString::from_static_str("brokerName")).unwrap(),
93 "test_broker"
94 );
95 assert_eq!(
96 map.get(&CheetahString::from_static_str("brokerControllerIdsToClean"))
97 .unwrap(),
98 "1;2"
99 );
100 assert_eq!(
101 map.get(&CheetahString::from_static_str("isCleanLivingBroker")).unwrap(),
102 "true"
103 );
104 }
105
106 #[test]
107 fn clean_broker_data_request_header_deserializes_correctly() {
108 let mut map = HashMap::new();
109 map.insert(
110 CheetahString::from_static_str("clusterName"),
111 CheetahString::from_static_str("test_cluster"),
112 );
113 map.insert(
114 CheetahString::from_static_str("brokerName"),
115 CheetahString::from_static_str("test_broker"),
116 );
117 map.insert(
118 CheetahString::from_static_str("brokerControllerIdsToClean"),
119 CheetahString::from_static_str("1;2"),
120 );
121 map.insert(
122 CheetahString::from_static_str("isCleanLivingBroker"),
123 CheetahString::from_static_str("false"),
124 );
125 map.insert(
126 CheetahString::from_static_str("invokeTime"),
127 CheetahString::from_static_str("1234567890"),
128 );
129
130 let header = <CleanBrokerDataRequestHeader as FromMap>::from(&map).unwrap();
131 assert_eq!(
132 header.cluster_name,
133 Some(CheetahString::from_static_str("test_cluster"))
134 );
135 assert_eq!(header.broker_name, CheetahString::from_static_str("test_broker"));
136 assert_eq!(
137 header.broker_controller_ids_to_clean,
138 Some(CheetahString::from_static_str("1;2"))
139 );
140 assert!(!header.clean_living_broker);
141 assert_eq!(header.invoke_time, 1234567890);
142 }
143
144 #[test]
145 fn missing_invoke_time_uses_the_java_dynamic_default() {
146 let before = rocketmq_model::time::current_millis();
147 let map = HashMap::from([(
148 CheetahString::from_static_str("brokerName"),
149 CheetahString::from_static_str("broker-a"),
150 )]);
151
152 let header = <CleanBrokerDataRequestHeader as FromMap>::from(&map).unwrap();
153 let after = rocketmq_model::time::current_millis();
154
155 assert!((before..=after).contains(&header.invoke_time));
156 assert!(!header.clean_living_broker);
157 }
158
159 #[test]
160 fn clean_broker_data_request_header_default() {
161 let before = rocketmq_model::time::current_millis();
162 let header = CleanBrokerDataRequestHeader::default();
163 let after = rocketmq_model::time::current_millis();
164
165 assert!(header.cluster_name.is_none());
166 assert_eq!(header.broker_name, "");
167 assert!(header.broker_controller_ids_to_clean.is_none());
168 assert!(!header.clean_living_broker);
169 assert!((before..=after).contains(&header.invoke_time));
170 }
171
172 #[test]
173 fn canonical_clean_living_key_wins_the_legacy_alias() {
174 let map = HashMap::from([
175 (
176 CheetahString::from_static_str("brokerName"),
177 CheetahString::from_static_str("broker-a"),
178 ),
179 (
180 CheetahString::from_static_str("isCleanLivingBroker"),
181 CheetahString::from_static_str("true"),
182 ),
183 (
184 CheetahString::from_static_str("cleanLivingBroker"),
185 CheetahString::from_static_str("false"),
186 ),
187 ]);
188
189 let header = <CleanBrokerDataRequestHeader as FromMap>::from(&map).unwrap();
190
191 assert!(header.clean_living_broker);
192 }
193}