Skip to main content

rocketmq_common/common/message/
message_queue_assignment.rs

1// Copyright 2023 The RocketMQ Rust Authors
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::collections::HashMap;
16use std::hash::Hash;
17use std::hash::Hasher;
18
19use cheetah_string::CheetahString;
20use serde::Deserialize;
21use serde::Serialize;
22
23use crate::common::message::message_enum::MessageRequestMode;
24use crate::common::message::message_queue::MessageQueue;
25
26#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
27#[serde(rename_all = "camelCase")]
28pub struct MessageQueueAssignment {
29    pub message_queue: Option<MessageQueue>,
30    pub mode: MessageRequestMode,
31    pub attachments: Option<HashMap<CheetahString, CheetahString>>,
32}
33
34impl Hash for MessageQueueAssignment {
35    fn hash<H: Hasher>(&self, state: &mut H) {
36        self.message_queue.hash(state);
37        self.mode.hash(state);
38        if let Some(ref attachments) = self.attachments {
39            let mut sorted_attachments: Vec<_> = attachments.iter().collect();
40            sorted_attachments.sort_by_key(|(k, _)| k.as_str());
41            for (key, value) in sorted_attachments {
42                key.hash(state);
43                value.hash(state);
44            }
45        }
46    }
47}
48
49impl Default for MessageQueueAssignment {
50    fn default() -> Self {
51        MessageQueueAssignment {
52            message_queue: None,
53            mode: MessageRequestMode::Pull,
54            attachments: None,
55        }
56    }
57}
58
59#[cfg(test)]
60mod tests {
61    use super::*;
62
63    #[test]
64    fn test_message_queue_assignment() {
65        let msg_queue_assignment = MessageQueueAssignment::default();
66
67        assert_eq!(msg_queue_assignment.message_queue, None);
68        assert_eq!(msg_queue_assignment.mode, MessageRequestMode::Pull);
69        assert_eq!(msg_queue_assignment.attachments, None);
70    }
71
72    #[test]
73    fn test_message_queue_assignment_hash() {
74        let mut first_msg_queue = MessageQueue::default();
75        first_msg_queue.set_broker_name(CheetahString::from("defaultBroker"));
76        first_msg_queue.set_queue_id(123);
77        first_msg_queue.set_topic(CheetahString::from("testTopic"));
78        let mut first_props = HashMap::new();
79        first_props.insert(CheetahString::from("rocketmqHome"), CheetahString::from("/new/path"));
80        first_props.insert(
81            CheetahString::from("kvConfigPath"),
82            CheetahString::from("/new/kvConfigPath"),
83        );
84        let first = MessageQueueAssignment {
85            message_queue: Some(first_msg_queue),
86            mode: MessageRequestMode::Pull,
87            attachments: Some(first_props),
88        };
89
90        let mut second_msg_queue = MessageQueue::default();
91        second_msg_queue.set_broker_name(CheetahString::from("defaultBroker"));
92        second_msg_queue.set_queue_id(123);
93        second_msg_queue.set_topic(CheetahString::from("testTopic"));
94        let mut second_props = HashMap::new();
95        second_props.insert(CheetahString::from("rocketmqHome"), CheetahString::from("/new/path"));
96        second_props.insert(
97            CheetahString::from("kvConfigPath"),
98            CheetahString::from("/new/kvConfigPath"),
99        );
100        let second = MessageQueueAssignment {
101            message_queue: Some(second_msg_queue),
102            mode: MessageRequestMode::Pull,
103            attachments: Some(second_props),
104        };
105
106        let mut first_hasher = std::collections::hash_map::DefaultHasher::new();
107        let mut second_hasher = std::collections::hash_map::DefaultHasher::new();
108
109        first.hash(&mut first_hasher);
110        let hash_first = first_hasher.finish();
111        second.hash(&mut second_hasher);
112        let hash_second = second_hasher.finish();
113
114        assert_eq!(hash_first, hash_second);
115    }
116
117    #[test]
118    fn test_message_queue_assignment_hash_differences() {
119        let mut first_props = HashMap::new();
120        first_props.insert(CheetahString::from("rocketmqHome"), CheetahString::from("/new/path"));
121        let mut second_props = HashMap::new();
122        second_props.insert(
123            CheetahString::from("rocketmqHome"),
124            CheetahString::from("/some/other/path"),
125        );
126
127        let first = MessageQueueAssignment {
128            message_queue: None,
129            mode: MessageRequestMode::Pull,
130            attachments: Some(first_props),
131        };
132
133        let second = MessageQueueAssignment {
134            message_queue: None,
135            mode: MessageRequestMode::Pull,
136            attachments: Some(second_props),
137        };
138
139        let mut first_hasher = std::collections::hash_map::DefaultHasher::new();
140        let mut second_hasher = std::collections::hash_map::DefaultHasher::new();
141
142        first.hash(&mut first_hasher);
143        let hash_first = first_hasher.finish();
144        second.hash(&mut second_hasher);
145        let hash_second = second_hasher.finish();
146
147        assert_ne!(hash_first, hash_second);
148
149        let mut first_msg_queue = MessageQueue::default();
150        first_msg_queue.set_broker_name(CheetahString::from("defaultBroker"));
151        let mut second_msg_queue = MessageQueue::default();
152        second_msg_queue.set_broker_name(CheetahString::from("nonDefaultBroker"));
153
154        let first = MessageQueueAssignment {
155            message_queue: Some(first_msg_queue),
156            mode: MessageRequestMode::Pull,
157            attachments: None,
158        };
159        let second = MessageQueueAssignment {
160            message_queue: Some(second_msg_queue),
161            mode: MessageRequestMode::Pull,
162            attachments: None,
163        };
164
165        let mut first_hasher = std::collections::hash_map::DefaultHasher::new();
166        let mut second_hasher = std::collections::hash_map::DefaultHasher::new();
167
168        first.hash(&mut first_hasher);
169        let hash_first = first_hasher.finish();
170        second.hash(&mut second_hasher);
171        let hash_second = second_hasher.finish();
172
173        assert_ne!(hash_first, hash_second);
174
175        let first = MessageQueueAssignment {
176            message_queue: None,
177            mode: MessageRequestMode::Pop,
178            attachments: None,
179        };
180        let second = MessageQueueAssignment {
181            message_queue: None,
182            mode: MessageRequestMode::Pull,
183            attachments: None,
184        };
185
186        let mut first_hasher = std::collections::hash_map::DefaultHasher::new();
187        let mut second_hasher = std::collections::hash_map::DefaultHasher::new();
188
189        first.hash(&mut first_hasher);
190        let hash_first = first_hasher.finish();
191        second.hash(&mut second_hasher);
192        let hash_second = second_hasher.finish();
193
194        assert_ne!(hash_first, hash_second);
195    }
196}