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
This commit is contained in:
zhenyi
2026-06-11 12:11:05 +08:00
parent 06e8ee96a5
commit 821537186e
111 changed files with 10458 additions and 385 deletions
+110
View File
@@ -0,0 +1,110 @@
//! Pin CRUD operations on `MessageRepo`.
//!
//! One row per pinned message. Channels can have multiple pinned messages.
//! `position` auto-calculated as `MAX(position) + 1` within the channel.
use chrono::Utc;
use sqlx::Row;
use uuid::Uuid;
use crate::ImksResult;
use crate::models::message_pin::{MessagePin, PinDetail};
use super::message_repo::MessageRepo;
impl MessageRepo {
/// Pin a message in a channel. Computes the next position automatically.
pub async fn pin_message(
&self,
channel_id: Uuid,
message_id: Uuid,
pinned_by: Uuid,
) -> ImksResult<MessagePin> {
let id = Uuid::now_v7();
let now = Utc::now();
let mut tx = self.pool().begin().await?;
sqlx::query("SELECT pg_advisory_xact_lock(hashtextextended($1, 0))")
.bind(channel_id.to_string())
.execute(&mut *tx)
.await?;
let max_pos: Option<i32> = sqlx::query_scalar(
"SELECT COALESCE(MAX(position), -1) FROM message_pin WHERE channel_id = $1",
)
.bind(channel_id)
.fetch_one(&mut *tx)
.await?;
let position = max_pos.unwrap_or(-1) + 1;
let pin = sqlx::query_as::<_, MessagePin>(
r#"
INSERT INTO message_pin (id, channel_id, message_id, pinned_by, position, created_at)
VALUES ($1, $2, $3, $4, $5, $6)
ON CONFLICT (channel_id, message_id) DO NOTHING
RETURNING *
"#,
)
.bind(id)
.bind(channel_id)
.bind(message_id)
.bind(pinned_by)
.bind(position)
.bind(now)
.fetch_optional(&mut *tx)
.await?
.ok_or_else(|| crate::ImksError::InvalidInput("Message already pinned".into()))?;
tx.commit().await?;
Ok(pin)
}
/// Unpin a message from a channel.
pub async fn unpin_message(&self, channel_id: Uuid, message_id: Uuid) -> ImksResult<bool> {
let result =
sqlx::query("DELETE FROM message_pin WHERE channel_id = $1 AND message_id = $2")
.bind(channel_id)
.bind(message_id)
.execute(self.pool())
.await?;
Ok(result.rows_affected() > 0)
}
/// List all pinned messages in a channel, newest first, joined with message content.
pub async fn list_pins(&self, channel_id: Uuid) -> ImksResult<Vec<PinDetail>> {
let rows = sqlx::query(
r#"
SELECT p.*, m.body AS message_body, m.author_id AS message_author_id,
m.created_at AS message_created_at
FROM message_pin p
JOIN message m ON m.id = p.message_id
WHERE p.channel_id = $1 AND m.deleted_at IS NULL
ORDER BY p.position ASC
"#,
)
.bind(channel_id)
.fetch_all(self.pool())
.await?;
let result = rows
.into_iter()
.map(|row| PinDetail {
pin: MessagePin {
id: row.get("id"),
channel_id: row.get("channel_id"),
message_id: row.get("message_id"),
pinned_by: row.get("pinned_by"),
position: row.get("position"),
created_at: row.get("created_at"),
},
message_body: row.get("message_body"),
message_author_id: row.get("message_author_id"),
message_created_at: row.get("message_created_at"),
})
.collect();
Ok(result)
}
}