Files
imks/repo/message_edit.rs
zhenyi 821537186e refactor(tests): reformat code and update dependency management
- Reorganized import statements in adapter tests for better readability
- Replaced or_insert_with(Vec::new) with or_default() in test closures
- Updated Cargo.lock with new dependency versions and checksums
- Added TLS features to tonic dependency configuration
- Included sqlx, chrono, and uuid dependencies with specific features
- Added jsonwebtoken and arc-swap as project dependencies
- Reformatted assertion statements to comply with line length limits
- Adjusted base64 import order in engine codec module
- Updated protobuf include statement formatting
2026-06-11 12:11:05 +08:00

78 lines
2.2 KiB
Rust

//! Edit history CRUD operations on `MessageRepo`.
//!
//! Immutable append-only log. Every message body edit creates one row.
use chrono::Utc;
use sqlx::Row;
use uuid::Uuid;
use crate::ImksResult;
use crate::models::message_edit::{EditSummary, MessageEdit};
use super::message_repo::MessageRepo;
impl MessageRepo {
/// Record an edit to a message's body.
pub async fn record_edit(
&self,
message_id: Uuid,
edited_by: Uuid,
old_body: &str,
new_body: &str,
) -> ImksResult<MessageEdit> {
let id = Uuid::now_v7();
let now = Utc::now();
sqlx::query_as::<_, MessageEdit>(
r#"
INSERT INTO message_edit (id, message_id, edited_by, old_body, new_body, edited_at)
VALUES ($1, $2, $3, $4, $5, $6)
RETURNING *
"#,
)
.bind(id)
.bind(message_id)
.bind(edited_by)
.bind(old_body)
.bind(new_body)
.bind(now)
.fetch_one(self.pool())
.await
.map_err(Into::into)
}
/// Get the full edit history for a message, oldest first.
pub async fn get_edit_history(&self, message_id: Uuid) -> ImksResult<Vec<MessageEdit>> {
sqlx::query_as::<_, MessageEdit>(
"SELECT * FROM message_edit WHERE message_id = $1 ORDER BY edited_at ASC",
)
.bind(message_id)
.fetch_all(self.pool())
.await
.map_err(Into::into)
}
/// Get a summary of edits for a message (count + last editor).
pub async fn get_edit_summary(&self, message_id: Uuid) -> ImksResult<EditSummary> {
let row = sqlx::query(
r#"
SELECT
COUNT(*)::BIGINT AS edit_count,
MAX(edited_at) AS last_edited_at,
(ARRAY_AGG(edited_by ORDER BY edited_at DESC))[1] AS last_edited_by
FROM message_edit
WHERE message_id = $1
"#,
)
.bind(message_id)
.fetch_one(self.pool())
.await?;
Ok(EditSummary {
edit_count: row.get("edit_count"),
last_edited_at: row.get("last_edited_at"),
last_edited_by: row.get("last_edited_by"),
})
}
}