1use serde::de::Error as _;
16use serde::Deserialize;
17use serde::Deserializer;
18use serde::Serialize;
19
20#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize)]
22#[serde(rename_all = "snake_case", tag = "kind")]
23pub enum ExpectedState {
24 Absent,
25 Present { version: u64 },
26}
27
28impl<'de> Deserialize<'de> for ExpectedState {
29 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
30 where
31 D: Deserializer<'de>,
32 {
33 #[derive(Deserialize)]
34 #[serde(deny_unknown_fields)]
35 struct RawExpectedState {
36 kind: String,
37 version: Option<u64>,
38 }
39 let raw = RawExpectedState::deserialize(deserializer)?;
40 match (raw.kind.as_str(), raw.version) {
41 ("absent", None) => Ok(Self::Absent),
42 ("present", Some(version)) => Ok(Self::Present { version }),
43 ("absent" | "present", _) => Err(D::Error::custom("expected state has invalid version presence")),
44 _ => Err(D::Error::custom("unknown expected state kind")),
45 }
46 }
47}
48
49#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
51#[serde(deny_unknown_fields, rename_all = "camelCase")]
52pub struct SupervisedTopicConfig {
53 pub read_queue_nums: u32,
54 pub write_queue_nums: u32,
55 pub perm: u32,
56 pub order: bool,
57 pub message_type: String,
58}
59
60#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
61#[serde(deny_unknown_fields, rename_all = "camelCase")]
62pub struct SupervisedTopicConfigCasRequestBody {
63 pub expected_state: ExpectedState,
64 pub replacement: SupervisedTopicConfig,
65}
66
67#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
69#[serde(deny_unknown_fields, rename_all = "camelCase")]
70pub struct SupervisedSubscriptionGroupConfig {
71 pub consume_enable: bool,
72 pub consume_from_min_enable: bool,
73 pub consume_broadcast_enable: bool,
74 pub consume_message_orderly: bool,
75 pub retry_queue_nums: i32,
76 pub retry_max_times: i32,
77 pub broker_id: u64,
78 pub which_broker_when_consume_slowly: u64,
79 pub notify_consumer_ids_changed_enable: bool,
80 pub group_sys_flag: i32,
81 pub consume_timeout_minute: i32,
82}
83
84#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
85#[serde(deny_unknown_fields, rename_all = "camelCase")]
86pub struct SupervisedSubscriptionGroupConfigCasRequestBody {
87 pub expected_state: ExpectedState,
88 pub replacement: SupervisedSubscriptionGroupConfig,
89}
90
91#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
93#[serde(deny_unknown_fields, rename_all = "camelCase")]
94pub struct BrokerMutationConfigState {
95 pub generation: u64,
96 pub auto_create_topic_enable: bool,
97 pub auto_create_subscription_group: bool,
98 pub broker_permission: u32,
99 pub default_topic_queue_nums: u32,
100 pub message_index_enable: bool,
101 pub trace_topic_enable: bool,
102}
103
104#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
106#[serde(deny_unknown_fields, rename_all = "camelCase")]
107pub struct SupervisedMessageRequestMode {
108 pub mode: String,
109 pub pop_share_queue_num: i32,
110}
111
112#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
113#[serde(rename_all = "snake_case", tag = "kind")]
114pub enum ExpectedMessageRequestMode {
115 Absent,
116 Present { mode: String, pop_share_queue_num: i32 },
117}
118
119impl<'de> Deserialize<'de> for ExpectedMessageRequestMode {
120 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
121 where
122 D: Deserializer<'de>,
123 {
124 #[derive(Deserialize)]
125 #[serde(deny_unknown_fields, rename_all = "snake_case")]
126 struct RawExpectedMode {
127 kind: String,
128 mode: Option<String>,
129 pop_share_queue_num: Option<i32>,
130 }
131 let raw = RawExpectedMode::deserialize(deserializer)?;
132 match (raw.kind.as_str(), raw.mode, raw.pop_share_queue_num) {
133 ("absent", None, None) => Ok(Self::Absent),
134 ("present", Some(mode), Some(pop_share_queue_num)) => Ok(Self::Present {
135 mode,
136 pop_share_queue_num,
137 }),
138 ("absent" | "present", _, _) => Err(D::Error::custom("expected request mode has invalid value presence")),
139 _ => Err(D::Error::custom("unknown expected request mode kind")),
140 }
141 }
142}
143
144#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
145#[serde(deny_unknown_fields, rename_all = "camelCase")]
146pub struct GetMessageRequestModeRequestBody {
147 pub topic: String,
148 pub consumer_group: String,
149}
150
151#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
152#[serde(deny_unknown_fields, rename_all = "camelCase")]
153pub struct MessageRequestModeStateBody {
154 pub current: Option<SupervisedMessageRequestMode>,
155}
156
157#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
159#[serde(rename_all = "snake_case")]
160pub enum MutationPersistenceState {
161 NotRequired,
162 Persisted,
163 Failed,
165 Unconfirmed,
168}
169
170#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
172#[serde(deny_unknown_fields, rename_all = "camelCase")]
173pub struct MessageRequestModeMutationResultBody {
174 pub applied: bool,
175 pub changed: bool,
176 pub current: Option<SupervisedMessageRequestMode>,
177 pub persistence: MutationPersistenceState,
178}
179
180#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
181#[serde(deny_unknown_fields, rename_all = "camelCase")]
182pub struct SetMessageRequestModeCasRequestBody {
183 pub topic: String,
184 pub consumer_group: String,
185 pub expected_state: ExpectedMessageRequestMode,
186 pub replacement: SupervisedMessageRequestMode,
187}
188
189#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
190#[serde(deny_unknown_fields, rename_all = "camelCase")]
191pub struct StateCasResultBody {
192 pub applied: bool,
193 pub changed: bool,
194 pub state: ExpectedState,
195 pub persistence: MutationPersistenceState,
196}
197
198#[cfg(test)]
199mod tests {
200 use super::*;
201
202 #[test]
203 fn expected_state_rejects_unknown_variants_and_fields() {
204 assert!(serde_json::from_str::<ExpectedState>(r#"{"kind":"missing"}"#).is_err());
205 assert!(serde_json::from_str::<ExpectedState>(r#"{"kind":"absent","version":1}"#).is_err());
206 assert_eq!(
207 serde_json::from_str::<ExpectedState>(r#"{"kind":"present","version":7}"#)
208 .expect("present state should decode"),
209 ExpectedState::Present { version: 7 }
210 );
211 }
212
213 #[test]
214 fn expected_message_request_mode_is_closed_and_requires_complete_present_state() {
215 for invalid in [
216 r#"{"kind":"absent","mode":"PULL","pop_share_queue_num":0}"#,
217 r#"{"kind":"present","mode":"PULL"}"#,
218 r#"{"kind":"present","pop_share_queue_num":0}"#,
219 r#"{"kind":"present","mode":"PULL","pop_share_queue_num":0,"extra":true}"#,
220 r#"{"kind":"unknown"}"#,
221 ] {
222 assert!(
223 serde_json::from_str::<ExpectedMessageRequestMode>(invalid).is_err(),
224 "{invalid} should be rejected"
225 );
226 }
227 assert_eq!(
228 serde_json::from_str::<ExpectedMessageRequestMode>(
229 r#"{"kind":"present","mode":"POP","pop_share_queue_num":4}"#
230 )
231 .expect("complete present state should decode"),
232 ExpectedMessageRequestMode::Present {
233 mode: "POP".to_owned(),
234 pop_share_queue_num: 4,
235 }
236 );
237 }
238}