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:
@@ -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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user