Skip to main content

rocketmq_protocol/protocol/header/
update_subscription_group_config_cas_request_header.rs

1// Copyright 2026 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 cheetah_string::CheetahString;
16use rocketmq_macros::RequestHeaderCodec;
17use serde::Deserialize;
18use serde::Serialize;
19
20/// Closed, version-checked Subscription Group configuration patch.
21///
22/// Only retry limits and consume timeout are accepted. The Broker preserves
23/// permissions, subscription policy, attributes, and every other field from
24/// the current group configuration.
25#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, RequestHeaderCodec)]
26#[header(
27    type_id = "rocketmq_protocol::protocol::header::update_subscription_group_config_cas_request_header::UpdateSubscriptionGroupConfigCasRequestHeader"
28)]
29#[serde(rename_all = "camelCase")]
30pub struct UpdateSubscriptionGroupConfigCasRequestHeader {
31    #[header(required)]
32    pub group: CheetahString,
33    #[header(required)]
34    pub expected_version: u64,
35    pub retry_max_times: Option<i32>,
36    pub retry_queue_nums: Option<i32>,
37    pub consume_timeout_minutes: Option<i32>,
38}
39
40#[cfg(test)]
41mod tests {
42    use std::collections::HashMap;
43
44    use cheetah_string::CheetahString;
45
46    use super::UpdateSubscriptionGroupConfigCasRequestHeader;
47    use crate::protocol::command_custom_header::CommandCustomHeader;
48    use crate::protocol::command_custom_header::FromMap;
49
50    #[test]
51    fn allowlisted_patch_round_trips_through_wire_map() {
52        let header = UpdateSubscriptionGroupConfigCasRequestHeader {
53            group: "orders-consumer".into(),
54            expected_version: 42,
55            retry_max_times: Some(8),
56            retry_queue_nums: Some(4),
57            consume_timeout_minutes: Some(30),
58        };
59        let map = header.to_map().expect("header should encode");
60
61        assert_eq!(map.get("group").map(CheetahString::as_str), Some("orders-consumer"));
62        assert_eq!(map.get("expectedVersion").map(CheetahString::as_str), Some("42"));
63        assert_eq!(map.get("retryMaxTimes").map(CheetahString::as_str), Some("8"));
64        assert_eq!(map.get("retryQueueNums").map(CheetahString::as_str), Some("4"));
65        assert_eq!(map.get("consumeTimeoutMinutes").map(CheetahString::as_str), Some("30"));
66
67        let decoded =
68            <UpdateSubscriptionGroupConfigCasRequestHeader as FromMap>::from(&map).expect("header should decode");
69        assert_eq!(decoded, header);
70    }
71
72    #[test]
73    fn omitted_patch_fields_remain_absent() {
74        let header = UpdateSubscriptionGroupConfigCasRequestHeader {
75            group: "orders-consumer".into(),
76            expected_version: 0,
77            ..Default::default()
78        };
79        let map = header.to_map().expect("header should encode");
80
81        assert!(!map.contains_key("retryMaxTimes"));
82        assert!(!map.contains_key("retryQueueNums"));
83        assert!(!map.contains_key("consumeTimeoutMinutes"));
84        assert_eq!(
85            <UpdateSubscriptionGroupConfigCasRequestHeader as FromMap>::from(&map).expect("header should decode"),
86            header
87        );
88    }
89
90    #[test]
91    fn missing_version_is_rejected_instead_of_becoming_zero() {
92        let mut map = HashMap::new();
93        map.insert(
94            CheetahString::from_static_str("group"),
95            CheetahString::from_static_str("orders-consumer"),
96        );
97
98        assert!(<UpdateSubscriptionGroupConfigCasRequestHeader as FromMap>::from(&map).is_err());
99    }
100}