fix(session): 消息持久化和恢复

问题:消息只写内存,重启后丢失。from_storage 恢复了 meta 但没加载消息。

修复:
- add_message 改为 async,同时写内存和 Storage
- compact 场景用 persist=false 避免重复持久化
- clear_session_history 同时清内存和 Storage 消息
- 所有调用点添加 .await 和错误转换
This commit is contained in:
xiaoxixi 2026-04-28 23:10:53 +08:00
parent c48ed83a23
commit e2fd836794

View File

@ -163,27 +163,9 @@ impl Session {
self.id.to_string() self.id.to_string()
} }
/// 添加消息到历史仅内存Phase 3 会扩展为持久化) /// 添加消息到历史并持久化到 Storage
pub fn add_message(&mut self, message: ChatMessage) { /// 如果 `persist` 为 false只更新内存用于 compaction 场景)
let is_user = message.role == "user"; pub async fn add_message(&mut self, message: ChatMessage, persist: bool) -> Result<(), StorageError> {
let now = chrono::Utc::now().timestamp_millis();
// Assign seq (in-memory only, persistence in Phase 3)
let _seq = self.seq_counter;
self.seq_counter += 1;
// Update in-memory state
self.messages.push(message);
self.total_message_count += 1;
if is_user {
self.message_count += 1;
}
self.last_active_at = now;
}
/// 添加消息到历史并持久化到 StoragePhase 3 使用)
/// 目前 storage 为 None此方法退化为 add_message
pub async fn add_message_and_persist(&mut self, message: ChatMessage) -> Result<(), StorageError> {
let is_user = message.role == "user"; let is_user = message.role == "user";
let now = chrono::Utc::now().timestamp_millis(); let now = chrono::Utc::now().timestamp_millis();
@ -191,7 +173,8 @@ impl Session {
let seq = self.seq_counter; let seq = self.seq_counter;
self.seq_counter += 1; self.seq_counter += 1;
// Persist to Storage (currently None, wired up in Phase 3) // Persist to Storage
if persist {
if let Some(ref storage) = self.storage { if let Some(ref storage) = self.storage {
let msg_meta = crate::storage::message::MessageMeta { let msg_meta = crate::storage::message::MessageMeta {
id: message.id.clone(), id: message.id.clone(),
@ -211,6 +194,7 @@ impl Session {
}; };
storage.append_message_with_retry(&self.id.to_string(), &msg_meta).await?; storage.append_message_with_retry(&self.id.to_string(), &msg_meta).await?;
} }
}
// Update in-memory state // Update in-memory state
self.messages.push(message); self.messages.push(message);
@ -757,7 +741,8 @@ impl SessionManager {
let compressed_count = compressed.len(); let compressed_count = compressed.len();
session_guard.clear_history(); session_guard.clear_history();
for msg in compressed { for msg in compressed {
session_guard.add_message(msg); session_guard.add_message(msg, false).await
.map_err(|e| AgentError::Other(format!("persist error: {}", e)))?;
} }
Ok((None, format!( Ok((None, format!(
"Context compressed: {} → {} messages.", "Context compressed: {} → {} messages.",
@ -1125,7 +1110,8 @@ impl SessionManager {
} }
let user_message = session_guard.create_user_message(content, media_refs); let user_message = session_guard.create_user_message(content, media_refs);
session_guard.add_message(user_message); session_guard.add_message(user_message, true).await
.map_err(|e| AgentError::Other(format!("persist error: {}", e)))?;
let mut history = session_guard.get_history().to_vec(); let mut history = session_guard.get_history().to_vec();
@ -1145,7 +1131,8 @@ impl SessionManager {
let result = agent.process(history).await?; let result = agent.process(history).await?;
for msg in result.emitted_messages { for msg in result.emitted_messages {
session_guard.add_message(msg); session_guard.add_message(msg, true).await
.map_err(|e| AgentError::Other(format!("persist error: {}", e)))?;
} }
result.final_response.content result.final_response.content
@ -1165,7 +1152,16 @@ impl SessionManager {
pub async fn clear_session_history(&self, unified_id: &UnifiedSessionId) -> Result<(), AgentError> { pub async fn clear_session_history(&self, unified_id: &UnifiedSessionId) -> Result<(), AgentError> {
let session = self.get_or_create_session(unified_id).await?; let session = self.get_or_create_session(unified_id).await?;
let mut session_guard = session.lock().await; let mut session_guard = session.lock().await;
session_guard.clear_history(); // Clear in-memory
session_guard.messages.clear();
session_guard.seq_counter = 1;
session_guard.total_message_count = 0;
session_guard.message_count = 0;
// Clear Storage
if let Some(ref storage) = session_guard.storage {
storage.clear_messages(&session_guard.id.to_string()).await
.map_err(|e| AgentError::Other(format!("failed to clear messages: {}", e)))?;
}
Ok(()) Ok(())
} }
} }