use rocketmq_model::common::message::message_ext::MessageExt; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] #[serde(default)] pub struct EventProperties { pub user_id: Option, pub org_id: Option, pub request_id: Option, pub repo_id: Option, pub repo_name: Option, pub room_id: Option, pub message_id: Option, pub thread_id: Option, pub issue_id: Option, pub pull_id: Option, pub timestamp: Option, } impl EventProperties { pub fn normalize(&mut self) -> Result<(), String> { for id in [ &mut self.org_id, &mut self.repo_id, &mut self.room_id, &mut self.message_id, &mut self.thread_id, &mut self.issue_id, &mut self.pull_id, ] .into_iter() .flatten() { *id = uuid::Uuid::parse_str(id) .map_err(|_| "resource IDs must be UUIDs")? .to_string(); } if let Some(user) = &mut self.user_id { let id = user.parse::().map_err(|_| "invalid user id")?; if id <= 0 { return Err("user id must be positive".to_string()); } *user = id.to_string(); } Ok(()) } pub(super) fn from_message(message: &MessageExt) -> Self { let properties = message.properties(); Self { user_id: properties.get("user").map(ToString::to_string), org_id: properties.get("org").map(ToString::to_string), request_id: properties.get("request_id").map(ToString::to_string), repo_id: properties.get("repo_id").map(ToString::to_string), repo_name: properties.get("repo_name").map(ToString::to_string), room_id: properties.get("room_id").map(ToString::to_string), message_id: properties.get("message_id").map(ToString::to_string), thread_id: properties.get("thread_id").map(ToString::to_string), issue_id: properties.get("issue_id").map(ToString::to_string), pull_id: properties.get("pull_id").map(ToString::to_string), timestamp: properties .get("timestamp") .and_then(|value| value.as_str().parse().ok()), } } pub fn is_empty(&self) -> bool { self.user_id.is_none() && self.org_id.is_none() && self.request_id.is_none() && self.repo_id.is_none() && self.repo_name.is_none() && self.room_id.is_none() && self.message_id.is_none() && self.thread_id.is_none() && self.issue_id.is_none() && self.pull_id.is_none() && self.timestamp.is_none() } pub fn matches(&self, event: &Self) -> bool { if self.is_empty() { return false; } matches_field(&self.user_id, &event.user_id) && matches_field(&self.org_id, &event.org_id) && matches_field(&self.request_id, &event.request_id) && matches_field(&self.repo_id, &event.repo_id) && matches_field(&self.repo_name, &event.repo_name) && matches_field(&self.room_id, &event.room_id) && matches_field(&self.message_id, &event.message_id) && matches_field(&self.thread_id, &event.thread_id) && matches_field(&self.issue_id, &event.issue_id) && matches_field(&self.pull_id, &event.pull_id) && matches_field(&self.timestamp, &event.timestamp) } } fn matches_field(filter: &Option, value: &Option) -> bool { match filter { Some(expected) => value.as_ref() == Some(expected), None => true, } }