rocketmq_client_rust/hook/
consume_message_context.rs1use std::any::Any;
16use std::collections::HashMap;
17use std::fmt;
18use std::sync::Arc;
19
20use cheetah_string::CheetahString;
21use rocketmq_common::common::message::message_ext::MessageExt;
22use rocketmq_common::common::message::message_queue::MessageQueue;
23use rocketmq_rust::ArcMut;
24
25use crate::base::access_channel::AccessChannel;
26
27#[derive(Default)]
46pub struct ConsumeMessageContext<'a> {
47 pub consumer_group: CheetahString,
49 pub msg_list: &'a [ArcMut<MessageExt>],
51 pub mq: Option<MessageQueue>,
53 pub success: bool,
55 pub status: CheetahString,
57 pub mq_trace_context: Option<Arc<dyn Any + Send + Sync>>,
59 pub props: HashMap<CheetahString, CheetahString>,
61 pub namespace: CheetahString,
63 pub access_channel: Option<AccessChannel>,
65}
66
67impl<'a> ConsumeMessageContext<'a> {
68 #[inline]
70 pub fn new(consumer_group: CheetahString, msg_list: &'a [ArcMut<MessageExt>]) -> Self {
71 Self {
72 consumer_group,
73 msg_list,
74 ..Default::default()
75 }
76 }
77
78 #[inline]
80 pub fn with_mq(mut self, mq: MessageQueue) -> Self {
81 self.mq = Some(mq);
82 self
83 }
84
85 #[inline]
87 pub fn with_success(mut self, success: bool) -> Self {
88 self.success = success;
89 self
90 }
91
92 #[inline]
94 pub fn with_status(mut self, status: impl Into<CheetahString>) -> Self {
95 self.status = status.into();
96 self
97 }
98
99 #[inline]
101 pub fn with_trace_context(mut self, context: Arc<dyn Any + Send + Sync>) -> Self {
102 self.mq_trace_context = Some(context);
103 self
104 }
105
106 #[inline]
108 pub fn with_namespace(mut self, namespace: impl Into<CheetahString>) -> Self {
109 self.namespace = namespace.into();
110 self
111 }
112
113 #[inline]
115 pub fn with_access_channel(mut self, channel: AccessChannel) -> Self {
116 self.access_channel = Some(channel);
117 self
118 }
119
120 #[inline]
122 pub fn add_prop(&mut self, key: impl Into<CheetahString>, value: impl Into<CheetahString>) {
123 self.props.insert(key.into(), value.into());
124 }
125
126 #[inline]
128 pub fn message_count(&self) -> usize {
129 self.msg_list.len()
130 }
131}
132
133impl<'a> fmt::Display for ConsumeMessageContext<'a> {
134 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
135 write!(
136 f,
137 "ConsumeMessageContext {{ consumer_group: {}, msg_count: {}, ",
138 self.consumer_group,
139 self.msg_list.len()
140 )?;
141
142 if let Some(ref mq) = self.mq {
143 write!(f, "mq: {}, ", mq)?;
144 }
145
146 write!(f, "success: {}, status: {}", self.success, self.status)?;
147
148 if !self.namespace.is_empty() {
149 write!(f, ", namespace: {}", self.namespace)?;
150 }
151
152 if let Some(ref channel) = self.access_channel {
153 write!(f, ", access_channel: {:?}", channel)?;
154 }
155
156 write!(f, " }}")
157 }
158}
159
160impl<'a> fmt::Debug for ConsumeMessageContext<'a> {
161 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
162 f.debug_struct("ConsumeMessageContext")
163 .field("consumer_group", &self.consumer_group)
164 .field("msg_list_len", &self.msg_list.len())
165 .field("mq", &self.mq)
166 .field("success", &self.success)
167 .field("status", &self.status)
168 .field("mq_trace_context", &self.mq_trace_context.as_ref().map(|_| "Some(_)"))
169 .field("props_count", &self.props.len())
170 .field("namespace", &self.namespace)
171 .field("access_channel", &self.access_channel)
172 .finish()
173 }
174}
175
176#[cfg(test)]
177mod tests {
178 use super::*;
179
180 #[test]
181 fn consume_message_context_new() {
182 let group = CheetahString::from("test_group");
183 let msg_list = vec![ArcMut::new(MessageExt::default())];
184 let context = ConsumeMessageContext::new(group.clone(), &msg_list);
185
186 assert_eq!(context.consumer_group, group);
187 assert_eq!(context.message_count(), 1);
188 assert!(context.mq.is_none());
189 assert!(!context.success);
190 }
191
192 #[test]
193 fn consume_message_context_builder_methods() {
194 let group = CheetahString::from("test_group");
195 let msg_list = vec![];
196 let mq = MessageQueue::from_parts("topic", "broker", 1);
197
198 let context = ConsumeMessageContext::new(group, &msg_list)
199 .with_mq(mq.clone())
200 .with_success(true)
201 .with_status("SUCCESS")
202 .with_namespace("test_ns")
203 .with_access_channel(AccessChannel::Cloud);
204
205 assert_eq!(context.mq.unwrap(), mq);
206 assert!(context.success);
207 assert_eq!(context.status, "SUCCESS");
208 assert_eq!(context.namespace, "test_ns");
209 assert_eq!(context.access_channel.unwrap(), AccessChannel::Cloud);
210 }
211
212 #[test]
213 fn consume_message_context_add_prop() {
214 let mut context = ConsumeMessageContext::<'static>::default();
215 context.add_prop("key1", "value1");
216 assert_eq!(context.props.get(&CheetahString::from("key1")).unwrap(), "value1");
217 }
218
219 #[test]
220 fn consume_message_context_display() {
221 let group = CheetahString::from("test_group");
222 let msg_list = vec![];
223 let context = ConsumeMessageContext::new(group, &msg_list)
224 .with_success(true)
225 .with_status("OK");
226
227 let display = format!("{}", context);
228 assert!(display.contains("consumer_group: test_group"));
229 assert!(display.contains("msg_count: 0"));
230 assert!(display.contains("success: true"));
231 assert!(display.contains("status: OK"));
232 }
233
234 #[test]
235 fn consume_message_context_debug() {
236 let context = ConsumeMessageContext::<'static>::default();
237 let debug = format!("{:?}", context);
238 assert!(debug.contains("ConsumeMessageContext"));
239 assert!(debug.contains("consumer_group"));
240 }
241
242 #[test]
243 fn consume_message_context_with_trace_context() {
244 let context =
245 ConsumeMessageContext::<'static>::default().with_trace_context(Arc::new("trace_data".to_string()));
246 assert!(context.mq_trace_context.is_some());
247 }
248}