use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Message {
pub id: Uuid,
pub msg_type: MessageType,
pub source: String,
pub target: Option<String>,
pub topic: Option<String>,
pub payload: Vec<u8>,
pub correlation_id: Option<Uuid>,
pub metadata: MessageMetadata,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum MessageType {
Request,
Response,
Event,
Subscribe,
Unsubscribe,
Heartbeat,
Error,
ServiceRegister,
ServiceUnregister,
ServiceQuery,
ServiceDirectory,
SubscriptionRequest,
SubscriptionAccept,
SubscriptionReject,
SubscriptionData,
SubscriptionCancel,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MessageMetadata {
pub timestamp: u64,
pub priority: Priority,
pub ttl: Option<u64>,
pub retain: bool,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Default)]
pub enum Priority {
Low,
#[default]
Normal,
High,
}
impl Message {
pub fn request(source: String, target: String, method: String, payload: Vec<u8>) -> Self {
let id = Uuid::new_v4();
Self {
id,
msg_type: MessageType::Request,
source,
target: Some(target),
topic: Some(method),
payload,
correlation_id: Some(id),
metadata: MessageMetadata::default(),
}
}
pub fn response(request: &Message, payload: Vec<u8>) -> Self {
Self {
id: Uuid::new_v4(),
msg_type: MessageType::Response,
source: "service".to_string(), target: Some(request.source.clone()),
topic: request.topic.clone(),
payload,
correlation_id: request.correlation_id,
metadata: MessageMetadata::default(),
}
}
pub fn event(source: String, topic: String, payload: Vec<u8>) -> Self {
Self {
id: Uuid::new_v4(),
msg_type: MessageType::Event,
source,
target: None,
topic: Some(topic),
payload,
correlation_id: None,
metadata: MessageMetadata::default(),
}
}
}
impl Default for MessageMetadata {
fn default() -> Self {
Self {
timestamp: std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_millis() as u64,
priority: Priority::Normal,
ttl: None,
retain: false,
}
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Request<T> {
pub method: String,
pub params: T,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Response<T> {
pub result: Result<T, String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ServiceInfo {
pub name: String,
pub methods: Vec<String>,
pub process_name: String,
pub registered_at: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ServiceDirectory {
pub services: Vec<ServiceInfo>,
}
impl Message {
pub fn service_register(source: String, service_info: ServiceInfo) -> Self {
let payload = bincode::serialize(&service_info).unwrap_or_default();
Self {
id: Uuid::new_v4(),
msg_type: MessageType::ServiceRegister,
source,
target: None, topic: Some("service.register".to_string()),
payload,
correlation_id: None,
metadata: MessageMetadata::default(),
}
}
pub fn service_query(source: String, service_name: Option<String>) -> Self {
let payload = bincode::serialize(&service_name).unwrap_or_default();
Self {
id: Uuid::new_v4(),
msg_type: MessageType::ServiceQuery,
source,
target: None, topic: Some("service.query".to_string()),
payload,
correlation_id: Some(Uuid::new_v4()),
metadata: MessageMetadata::default(),
}
}
pub fn service_directory(
source: String,
target: String,
directory: ServiceDirectory,
correlation_id: Option<Uuid>,
) -> Self {
let payload = bincode::serialize(&directory).unwrap_or_default();
Self {
id: Uuid::new_v4(),
msg_type: MessageType::ServiceDirectory,
source,
target: Some(target),
topic: Some("service.directory".to_string()),
payload,
correlation_id,
metadata: MessageMetadata::default(),
}
}
pub fn subscription_request(
source: String,
target: Option<String>,
method: String,
params: Vec<u8>,
) -> Self {
let subscription_msg = crate::subscription::SubscriptionMessage::Request {
id: Uuid::new_v4(),
method: method.clone(),
params: serde_json::from_slice(¶ms).unwrap_or(serde_json::Value::Null),
};
let payload = bincode::serialize(&subscription_msg).unwrap_or_default();
Self {
id: Uuid::new_v4(),
msg_type: MessageType::SubscriptionRequest,
source,
target,
topic: Some(format!("subscription.{method}")),
payload,
correlation_id: Some(subscription_msg.id()),
metadata: MessageMetadata::default(),
}
}
pub fn subscription_accept(source: String, target: String, subscription_id: Uuid) -> Self {
let subscription_msg = crate::subscription::SubscriptionMessage::Accept {
id: subscription_id,
};
let payload = bincode::serialize(&subscription_msg).unwrap_or_default();
Self {
id: Uuid::new_v4(),
msg_type: MessageType::SubscriptionAccept,
source,
target: Some(target),
topic: Some("subscription.accept".to_string()),
payload,
correlation_id: Some(subscription_id),
metadata: MessageMetadata::default(),
}
}
pub fn subscription_reject(
source: String,
target: String,
subscription_id: Uuid,
reason: String,
) -> Self {
let subscription_msg = crate::subscription::SubscriptionMessage::Reject {
id: subscription_id,
reason,
};
let payload = bincode::serialize(&subscription_msg).unwrap_or_default();
Self {
id: Uuid::new_v4(),
msg_type: MessageType::SubscriptionReject,
source,
target: Some(target),
topic: Some("subscription.reject".to_string()),
payload,
correlation_id: Some(subscription_id),
metadata: MessageMetadata::default(),
}
}
pub fn subscription_data(
source: String,
target: String,
subscription_id: Uuid,
data: serde_json::Value,
) -> Self {
let subscription_msg = crate::subscription::SubscriptionMessage::Data {
id: subscription_id,
data,
};
let payload = bincode::serialize(&subscription_msg).unwrap_or_default();
Self {
id: Uuid::new_v4(),
msg_type: MessageType::SubscriptionData,
source,
target: Some(target),
topic: Some("subscription.data".to_string()),
payload,
correlation_id: Some(subscription_id),
metadata: MessageMetadata::default(),
}
}
pub fn subscription_cancel(source: String, target: String, subscription_id: Uuid) -> Self {
let subscription_msg = crate::subscription::SubscriptionMessage::Cancel {
id: subscription_id,
};
let payload = bincode::serialize(&subscription_msg).unwrap_or_default();
Self {
id: Uuid::new_v4(),
msg_type: MessageType::SubscriptionCancel,
source,
target: Some(target),
topic: Some("subscription.cancel".to_string()),
payload,
correlation_id: Some(subscription_id),
metadata: MessageMetadata::default(),
}
}
}