main
mod common;
mod gitdata;
mod kenshell;
mod platform_events;
mod properties;
pub use common::{EventContext, action};
pub use properties::EventProperties;
use serde_json::Value;
use crate::EventKind;
use crate::gateway::Subscription;
/// 网关支持订阅的 (项目前缀, area, tag) 全集:本仓库事件来自 `EventKind`,
/// kenshell 事件由对端仓库产生,这里是唯一的外来清单。
const KENSHELL: &[(&str, &str)] = &[
("repo", "create"),
("repo", "update"),
("repo", "delete"),
("repo", "placement-change"),
("repo", "language-update"),
("ref", "create-branch"),
("ref", "update-branch"),
("ref", "delete-branch"),
("ref", "rename-branch"),
("ref", "set-default-branch"),
("ref", "create-tag"),
("ref", "delete-tag"),
("ref", "create-protection"),
("ref", "delete-protection"),
("commit", "sync"),
("commit", "set-status"),
("commit", "comment-create"),
("commit", "comment-update"),
("commit", "comment-delete"),
("lfs", "upload"),
("lfs", "unreference"),
("lfs", "purge"),
("archive", "create"),
("job", "enqueue"),
("job", "claim"),
("job", "progress"),
("job", "heartbeat"),
("job", "cancel"),
("job", "retry"),
("job", "finish"),
("node", "create"),
("node", "update"),
("node", "delete"),
("node", "probe"),
("volume", "create"),
("volume", "update"),
("volume", "delete"),
("volume", "mount"),
("volume", "unmount"),
("volume", "probe"),
];
pub(crate) fn catalog() -> impl Iterator<Item = (&'static str, &'static str, &'static str)> {
EventKind::ALL
.iter()
.flat_map(|kind| {
kind.tags()
.iter()
.map(move |tag| ("gitdata", kind.topic(), *tag))
})
.chain(KENSHELL.iter().map(|(area, tag)| ("kenshell", *area, *tag)))
}
pub(crate) fn split_topic(topic: &str) -> Option<(&str, &str)> {
config::event::consumer::DEFAULT_TOPIC_PREFIXES
.iter()
.find_map(|prefix| {
topic
.strip_prefix(prefix)
.and_then(|rest| rest.strip_prefix('-'))
.map(|area| (*prefix, area))
})
}
pub(crate) fn identity_area(area: &str) -> bool {
EventKind::ALL
.iter()
.any(|kind| kind.topic() == area && kind.identity())
}
pub(crate) fn personal(area: &str, tag: &str) -> bool {
EventKind::ALL
.iter()
.any(|kind| kind.topic() == area && kind.personal() && kind.tags().contains(&tag))
}
/// 与 MQ 扇出一致的下行 payload 形状(可选附带命中的订阅列表)。
pub fn common_payload(
topic: &str,
tag: &str,
event_user_id: Option<i64>,
recipient_user_id: i64,
properties: &EventProperties,
body: &Value,
destinations: Option<Vec<Subscription>>,
) -> Value {
let mut value = serde_json::json!({
"topic": topic,
"tag": tag,
"user_id": event_user_id,
"recipient_user_id": recipient_user_id,
"properties": properties,
"body": body,
});
if let Some(destinations) = destinations {
if let Ok(value_destinations) = serde_json::to_value(destinations) {
value["destinations"] = value_destinations;
}
}
value
}
/// topic/tag 是否属于本网关支持的事件族(平台定向投递与订阅校验共用)。
pub fn is_supported(topic: &str, tag: &str) -> bool {
gitdata::is_supported(topic, tag)
|| kenshell::is_supported(topic, tag)
|| platform_events::is_supported(topic, tag)
}
pub fn is_personal_topic(topic: &str, tag: &str) -> bool {
crate::gateway::is_personal(topic, tag)
}