feat(storage): 实现 Storage 主结构和初始化
This commit is contained in:
parent
c4c87aac95
commit
88f8a86b99
@ -3,3 +3,90 @@ pub mod session;
|
||||
pub mod message;
|
||||
|
||||
pub use error::StorageError;
|
||||
|
||||
use sqlx::{Pool, Sqlite, SqlitePool};
|
||||
use std::path::Path;
|
||||
|
||||
pub struct Storage {
|
||||
pool: Pool<Sqlite>,
|
||||
}
|
||||
|
||||
impl Storage {
|
||||
/// 打开或创建数据库
|
||||
pub async fn new(db_path: &Path) -> Result<Self, StorageError> {
|
||||
let database_url = format!("sqlite:{}?mode=rwc", db_path.display());
|
||||
let pool = SqlitePool::connect(&database_url).await?;
|
||||
|
||||
let storage = Self { pool };
|
||||
storage.init_schema().await?;
|
||||
Ok(storage)
|
||||
}
|
||||
|
||||
/// 初始化数据库 schema
|
||||
async fn init_schema(&self) -> Result<(), StorageError> {
|
||||
sqlx::query(
|
||||
r#"
|
||||
CREATE TABLE IF NOT EXISTS sessions (
|
||||
id TEXT PRIMARY KEY,
|
||||
channel TEXT NOT NULL,
|
||||
chat_id TEXT NOT NULL,
|
||||
dialog_id TEXT NOT NULL,
|
||||
title TEXT NOT NULL DEFAULT '新对话',
|
||||
created_at INTEGER NOT NULL,
|
||||
last_active_at INTEGER NOT NULL,
|
||||
message_count INTEGER DEFAULT 0,
|
||||
routing_info TEXT,
|
||||
deleted_at INTEGER,
|
||||
UNIQUE(channel, chat_id, dialog_id)
|
||||
)
|
||||
"#,
|
||||
)
|
||||
.execute(&self.pool)
|
||||
.await?;
|
||||
|
||||
sqlx::query(
|
||||
r#"
|
||||
CREATE INDEX IF NOT EXISTS idx_sessions_chat
|
||||
ON sessions(channel, chat_id, deleted_at)
|
||||
"#,
|
||||
)
|
||||
.execute(&self.pool)
|
||||
.await?;
|
||||
|
||||
sqlx::query(
|
||||
r#"
|
||||
CREATE TABLE IF NOT EXISTS messages (
|
||||
id TEXT PRIMARY KEY,
|
||||
session_id TEXT NOT NULL,
|
||||
seq INTEGER NOT NULL,
|
||||
role TEXT NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
media_refs TEXT,
|
||||
tool_call_id TEXT,
|
||||
tool_name TEXT,
|
||||
tool_calls TEXT,
|
||||
created_at INTEGER NOT NULL,
|
||||
FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE
|
||||
)
|
||||
"#,
|
||||
)
|
||||
.execute(&self.pool)
|
||||
.await?;
|
||||
|
||||
sqlx::query(
|
||||
r#"
|
||||
CREATE INDEX IF NOT EXISTS idx_messages_session_seq
|
||||
ON messages(session_id, seq)
|
||||
"#,
|
||||
)
|
||||
.execute(&self.pool)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 获取连接池引用(供内部 CRUD 使用)
|
||||
pub(crate) fn pool(&self) -> &Pool<Sqlite> {
|
||||
&self.pool
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user