diff --git a/backend/internal/session/memory.go b/backend/internal/session/memory.go index be8da3c..bc300a3 100644 --- a/backend/internal/session/memory.go +++ b/backend/internal/session/memory.go @@ -307,6 +307,48 @@ func generateTitle(firstMessage string) string { return firstMessage } +// LoadSession 从外部存储加载会话到内存热存储。 +// 用于 conversation_id 恢复场景:WS 连接时会话不在内存中,从 PostgreSQL 加载。 +// 若会话已在内存中,返回 nil(幂等)。 +func (m *MemoryManager) LoadSession(sess *models.Session, messages []models.Message) error { + m.mu.Lock() + defer m.mu.Unlock() + + if _, ok := m.sessions[sess.ID]; ok { + return nil // 已在内存中,无需重复加载 + } + + m.sessions[sess.ID] = &sessionEntry{ + session: *sess, + history: messages, + lastActive: time.Now(), + } + + logger.Log.Debugw("session loaded from DB", "session", sess.ID, "messages", len(messages)) + return nil +} + +// LoadSessionFromRepo 从 MessageRepository 加载会话消息并注册到内存。 +// 适用于已注入 MessageRepository 的场景,调用方只需传入 session 元数据。 +func (m *MemoryManager) LoadSessionFromRepo(ctx context.Context, sess *models.Session) error { + if m.msgRepo == nil { + return m.LoadSession(sess, nil) + } + + // 从冷存储加载全部消息(limit=0 表示全量) + stored, err := m.msgRepo.GetMessages(ctx, sess.ID, 0, 0) + if err != nil { + return err + } + + messages := make([]models.Message, len(stored)) + for i, s := range stored { + messages[i] = models.Message{Role: s.Role, Content: s.Content} + } + + return m.LoadSession(sess, messages) +} + // SetActiveRequest 标记当前正在处理的请求 ID。 func (m *MemoryManager) SetActiveRequest(_ context.Context, sessionID string, requestID string) error { m.mu.Lock()