rocketmq_protocol/protocol/header/
query_consumer_offset_request_header.rs1use cheetah_string::CheetahString;
16use rocketmq_macros::RequestHeaderCodec;
17use serde::Deserialize;
18use serde::Serialize;
19
20use crate::protocol::header::message_operation_header::TopicRequestHeaderTrait;
21use crate::protocol::header::namesrv::topic_operation_header::TopicRequestHeader;
22
23#[derive(Debug, Clone, Serialize, Deserialize, RequestHeaderCodec, Default)]
24#[header(
25 type_id = "rocketmq_protocol::protocol::header::query_consumer_offset_request_header::QueryConsumerOffsetRequestHeader",
26 java_class = "org.apache.rocketmq.remoting.protocol.header.QueryConsumerOffsetRequestHeader"
27)]
28#[serde(rename_all = "camelCase")]
29pub struct QueryConsumerOffsetRequestHeader {
30 #[header(required)]
31 pub consumer_group: CheetahString,
32
33 #[header(required)]
34 pub topic: CheetahString,
35
36 #[header(required)]
37 pub queue_id: i32,
38
39 pub set_zero_if_not_found: Option<bool>,
40
41 #[serde(flatten)]
42 #[header(flatten, presence = "always")]
43 pub topic_request_header: Option<TopicRequestHeader>,
44}
45
46impl QueryConsumerOffsetRequestHeader {
47 pub fn new(consumer_group: impl Into<CheetahString>, topic: impl Into<CheetahString>, queue_id: i32) -> Self {
48 Self {
49 consumer_group: consumer_group.into(),
50 topic: topic.into(),
51 queue_id,
52 set_zero_if_not_found: None,
53 topic_request_header: None,
54 }
55 }
56}
57
58impl TopicRequestHeaderTrait for QueryConsumerOffsetRequestHeader {
59 fn set_lo(&mut self, lo: Option<bool>) {
60 if let Some(header) = self.topic_request_header.as_mut() {
61 header.lo = lo;
62 }
63 }
64
65 fn lo(&self) -> Option<bool> {
66 self.topic_request_header.as_ref().and_then(|h| h.lo)
67 }
68
69 fn set_topic(&mut self, topic: CheetahString) {
70 self.topic = topic;
71 }
72
73 fn topic(&self) -> &CheetahString {
74 &self.topic
75 }
76
77 fn broker_name(&self) -> Option<&CheetahString> {
78 self.topic_request_header
79 .as_ref()
80 .and_then(|h| h.rpc.as_ref())
81 .and_then(|h| h.broker_name.as_ref())
82 }
83
84 fn set_broker_name(&mut self, broker_name: CheetahString) {
85 if let Some(header) = self.topic_request_header.as_mut() {
86 if let Some(rpc_header) = header.rpc.as_mut() {
87 rpc_header.broker_name = Some(broker_name);
88 }
89 }
90 }
91
92 fn namespace(&self) -> Option<&str> {
93 self.topic_request_header
94 .as_ref()
95 .and_then(|h| h.rpc.as_ref())
96 .and_then(|r| r.namespace.as_deref())
97 }
98
99 fn set_namespace(&mut self, namespace: CheetahString) {
100 if let Some(header) = self.topic_request_header.as_mut() {
101 if let Some(rpc_header) = header.rpc.as_mut() {
102 rpc_header.namespace = Some(namespace);
103 }
104 }
105 }
106
107 fn namespaced(&self) -> Option<bool> {
108 self.topic_request_header
109 .as_ref()
110 .and_then(|h| h.rpc.as_ref())
111 .and_then(|r| r.namespaced)
112 }
113
114 fn set_namespaced(&mut self, namespaced: bool) {
115 if let Some(header) = self.topic_request_header.as_mut() {
116 if let Some(rpc_header) = header.rpc.as_mut() {
117 rpc_header.namespaced = Some(namespaced);
118 }
119 }
120 }
121
122 fn oneway(&self) -> Option<bool> {
123 self.topic_request_header
124 .as_ref()
125 .and_then(|h| h.rpc.as_ref())
126 .and_then(|r| r.oneway)
127 }
128
129 fn set_oneway(&mut self, oneway: bool) {
130 if let Some(header) = self.topic_request_header.as_mut() {
131 if let Some(rpc_header) = header.rpc.as_mut() {
132 rpc_header.oneway = Some(oneway);
133 }
134 }
135 }
136
137 fn queue_id(&self) -> i32 {
138 self.queue_id
139 }
140
141 fn set_queue_id(&mut self, queue_id: i32) {
142 self.queue_id = queue_id;
143 }
144}
145
146#[cfg(test)]
147mod tests {
148 use std::collections::HashMap;
149
150 use super::*;
151 use crate::protocol::command_custom_header::FromMap;
152
153 #[test]
154 fn query_consumer_offset_request_header_serialization() {
155 let mut header = QueryConsumerOffsetRequestHeader::new("group", "topic", 1);
156 assert_eq!(header.consumer_group, "group");
157 assert_eq!(header.topic, "topic");
158 assert_eq!(header.queue_id, 1);
159 assert!(header.set_zero_if_not_found.is_none());
160 assert!(header.topic_request_header.is_none());
161
162 header.set_zero_if_not_found = Some(true);
163 header.topic_request_header = Some(TopicRequestHeader {
164 lo: Some(true),
165 ..Default::default()
166 });
167 let json = serde_json::to_string(&header).unwrap();
168 assert!(json.contains("\"consumerGroup\":\"group\""));
169 assert!(json.contains("\"topic\":\"topic\""));
170 assert!(json.contains("\"queueId\":1"));
171 assert!(json.contains("\"setZeroIfNotFound\":true"));
172 assert!(json.contains("\"lo\":true"));
173 }
174
175 #[test]
176 fn query_consumer_offset_request_header_deserialization() {
177 let json = r#"{"consumerGroup":"group","topic":"topic","queueId":1,"setZeroIfNotFound":true,"lo":true}"#;
178 let header: QueryConsumerOffsetRequestHeader = serde_json::from_str(json).unwrap();
179 assert_eq!(header.consumer_group, "group");
180 assert_eq!(header.topic, "topic");
181 assert_eq!(header.queue_id, 1);
182 assert_eq!(header.set_zero_if_not_found, Some(true));
183 assert_eq!(header.topic_request_header.unwrap().lo, Some(true));
184 }
185
186 #[test]
187 fn query_consumer_offset_request_header_from_map() {
188 let mut map = HashMap::new();
189 map.insert(CheetahString::from("consumerGroup"), CheetahString::from("group1"));
190 map.insert(CheetahString::from("topic"), CheetahString::from("topic1"));
191 map.insert(CheetahString::from("queueId"), CheetahString::from("2"));
192 map.insert(CheetahString::from("setZeroIfNotFound"), CheetahString::from("true"));
193 map.insert(CheetahString::from("lo"), CheetahString::from("true"));
194
195 let header = <QueryConsumerOffsetRequestHeader as FromMap>::from(&map).unwrap();
196 assert_eq!(header.consumer_group, "group1");
197 assert_eq!(header.topic, "topic1");
198 assert_eq!(header.queue_id, 2);
199 assert_eq!(header.set_zero_if_not_found, Some(true));
200 assert_eq!(header.topic_request_header.unwrap().lo, Some(true));
201 }
202}