feat(storage): 实现 Session CRUD 操作
This commit is contained in:
parent
c51ba900fa
commit
eeb8a77ac8
@ -4,7 +4,7 @@ pub mod message;
|
|||||||
|
|
||||||
pub use error::StorageError;
|
pub use error::StorageError;
|
||||||
|
|
||||||
use sqlx::{Pool, Sqlite, SqlitePool};
|
use sqlx::{Pool, Row, Sqlite, SqlitePool};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
pub struct Storage {
|
pub struct Storage {
|
||||||
@ -89,4 +89,170 @@ impl Storage {
|
|||||||
pub(crate) fn pool(&self) -> &Pool<Sqlite> {
|
pub(crate) fn pool(&self) -> &Pool<Sqlite> {
|
||||||
&self.pool
|
&self.pool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn upsert_session(&self, meta: &crate::storage::session::SessionMeta) -> Result<(), StorageError> {
|
||||||
|
sqlx::query(
|
||||||
|
r#"
|
||||||
|
INSERT INTO sessions (id, channel, chat_id, dialog_id, title, created_at, last_active_at, message_count, routing_info, deleted_at)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
|
ON CONFLICT(id) DO UPDATE SET
|
||||||
|
title = excluded.title,
|
||||||
|
last_active_at = excluded.last_active_at,
|
||||||
|
message_count = excluded.message_count,
|
||||||
|
routing_info = excluded.routing_info,
|
||||||
|
deleted_at = excluded.deleted_at
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.bind(&meta.id)
|
||||||
|
.bind(&meta.channel)
|
||||||
|
.bind(&meta.chat_id)
|
||||||
|
.bind(&meta.dialog_id)
|
||||||
|
.bind(&meta.title)
|
||||||
|
.bind(meta.created_at)
|
||||||
|
.bind(meta.last_active_at)
|
||||||
|
.bind(meta.message_count)
|
||||||
|
.bind(&meta.routing_info)
|
||||||
|
.bind(meta.deleted_at)
|
||||||
|
.execute(self.pool())
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_session(&self, id: &str) -> Result<crate::storage::session::SessionMeta, StorageError> {
|
||||||
|
let row = sqlx::query(
|
||||||
|
r#"
|
||||||
|
SELECT id, channel, chat_id, dialog_id, title, created_at, last_active_at, message_count, routing_info, deleted_at
|
||||||
|
FROM sessions WHERE id = ? AND deleted_at IS NULL
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.bind(id)
|
||||||
|
.fetch_optional(self.pool())
|
||||||
|
.await?
|
||||||
|
.ok_or_else(|| StorageError::NotFound(id.to_string()))?;
|
||||||
|
|
||||||
|
Ok(crate::storage::session::SessionMeta {
|
||||||
|
id: row.get("id"),
|
||||||
|
channel: row.get("channel"),
|
||||||
|
chat_id: row.get("chat_id"),
|
||||||
|
dialog_id: row.get("dialog_id"),
|
||||||
|
title: row.get("title"),
|
||||||
|
created_at: row.get("created_at"),
|
||||||
|
last_active_at: row.get("last_active_at"),
|
||||||
|
message_count: row.get("message_count"),
|
||||||
|
routing_info: row.get("routing_info"),
|
||||||
|
deleted_at: row.get("deleted_at"),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn list_sessions(
|
||||||
|
&self,
|
||||||
|
channel: &str,
|
||||||
|
chat_id: &str,
|
||||||
|
limit: i64,
|
||||||
|
) -> Result<Vec<crate::storage::session::SessionMeta>, StorageError> {
|
||||||
|
let rows = sqlx::query(
|
||||||
|
r#"
|
||||||
|
SELECT id, channel, chat_id, dialog_id, title, created_at, last_active_at, message_count, routing_info, deleted_at
|
||||||
|
FROM sessions
|
||||||
|
WHERE channel = ? AND chat_id = ? AND deleted_at IS NULL
|
||||||
|
ORDER BY last_active_at DESC
|
||||||
|
LIMIT ?
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.bind(channel)
|
||||||
|
.bind(chat_id)
|
||||||
|
.bind(limit)
|
||||||
|
.fetch_all(self.pool())
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(rows
|
||||||
|
.into_iter()
|
||||||
|
.map(|row| crate::storage::session::SessionMeta {
|
||||||
|
id: row.get("id"),
|
||||||
|
channel: row.get("channel"),
|
||||||
|
chat_id: row.get("chat_id"),
|
||||||
|
dialog_id: row.get("dialog_id"),
|
||||||
|
title: row.get("title"),
|
||||||
|
created_at: row.get("created_at"),
|
||||||
|
last_active_at: row.get("last_active_at"),
|
||||||
|
message_count: row.get("message_count"),
|
||||||
|
routing_info: row.get("routing_info"),
|
||||||
|
deleted_at: row.get("deleted_at"),
|
||||||
|
})
|
||||||
|
.collect())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn touch_session(
|
||||||
|
&self,
|
||||||
|
id: &str,
|
||||||
|
message_count: i64,
|
||||||
|
last_active_at: i64,
|
||||||
|
) -> Result<(), StorageError> {
|
||||||
|
sqlx::query(
|
||||||
|
r#"
|
||||||
|
UPDATE sessions SET message_count = ?, last_active_at = ?
|
||||||
|
WHERE id = ?
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.bind(message_count)
|
||||||
|
.bind(last_active_at)
|
||||||
|
.bind(id)
|
||||||
|
.execute(self.pool())
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn soft_delete_session(&self, id: &str) -> Result<(), StorageError> {
|
||||||
|
let now = chrono::Utc::now().timestamp_millis();
|
||||||
|
sqlx::query(
|
||||||
|
r#"UPDATE sessions SET deleted_at = ? WHERE id = ?"#,
|
||||||
|
)
|
||||||
|
.bind(now)
|
||||||
|
.bind(id)
|
||||||
|
.execute(self.pool())
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn find_active_session(
|
||||||
|
&self,
|
||||||
|
channel: &str,
|
||||||
|
chat_id: &str,
|
||||||
|
ttl_millis: i64,
|
||||||
|
) -> Result<Option<crate::storage::session::SessionMeta>, StorageError> {
|
||||||
|
let cutoff = chrono::Utc::now().timestamp_millis() - ttl_millis;
|
||||||
|
let row = sqlx::query(
|
||||||
|
r#"
|
||||||
|
SELECT id, channel, chat_id, dialog_id, title, created_at, last_active_at, message_count, routing_info, deleted_at
|
||||||
|
FROM sessions
|
||||||
|
WHERE channel = ? AND chat_id = ? AND deleted_at IS NULL AND last_active_at > ?
|
||||||
|
ORDER BY last_active_at DESC
|
||||||
|
LIMIT 1
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.bind(channel)
|
||||||
|
.bind(chat_id)
|
||||||
|
.bind(cutoff)
|
||||||
|
.fetch_optional(self.pool())
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
match row {
|
||||||
|
Some(row) => Ok(Some(crate::storage::session::SessionMeta {
|
||||||
|
id: row.get("id"),
|
||||||
|
channel: row.get("channel"),
|
||||||
|
chat_id: row.get("chat_id"),
|
||||||
|
dialog_id: row.get("dialog_id"),
|
||||||
|
title: row.get("title"),
|
||||||
|
created_at: row.get("created_at"),
|
||||||
|
last_active_at: row.get("last_active_at"),
|
||||||
|
message_count: row.get("message_count"),
|
||||||
|
routing_info: row.get("routing_info"),
|
||||||
|
deleted_at: row.get("deleted_at"),
|
||||||
|
})),
|
||||||
|
None => Ok(None),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user