//! Thread metadata — maps to `message_thread` table. //! //! A thread is anchored by a root message. Reply messages in the same thread //! set `message.thread_id = message_thread.id`. use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use uuid::Uuid; /// A message thread anchored by a root message. /// /// Maps to the `message_thread` table. Reply messages set /// `message.thread_id = message_thread.id` to join the thread. #[derive(Debug, Clone, Serialize, Deserialize, sqlx::FromRow)] pub struct MessageThread { pub id: Uuid, pub channel_id: Uuid, /// The first message that started this thread. pub root_message_id: Uuid, pub created_by: Uuid, pub replies_count: i64, pub participants_count: i64, pub last_reply_message_id: Option, pub last_reply_at: Option>, /// Forum-style: mark thread as resolved / answered. pub resolved: bool, pub resolved_by: Option, pub resolved_at: Option>, pub created_at: DateTime, pub updated_at: DateTime, } #[cfg(test)] mod tests { use super::*; #[test] fn test_thread_serialize() { let thread = MessageThread { id: Uuid::now_v7(), channel_id: Uuid::now_v7(), root_message_id: Uuid::now_v7(), created_by: Uuid::now_v7(), replies_count: 5, participants_count: 3, last_reply_message_id: None, last_reply_at: None, resolved: false, resolved_by: None, resolved_at: None, created_at: Utc::now(), updated_at: Utc::now(), }; let json = serde_json::to_value(&thread).unwrap(); assert_eq!(json["replies_count"], 5); assert_eq!(json["resolved"], false); assert!(json["id"].is_string()); } }