feat: Phase 8.3 — Session Manager 注入 MessageRepository,AppendMessage 启用 Write-Through

This commit is contained in:
hhs
2026-06-14 17:54:33 +08:00
parent 96f4bc7abb
commit f4515ce5e4

View File

@@ -10,6 +10,7 @@ import (
"github.com/hhs/camtalk/internal/logger"
"github.com/hhs/camtalk/internal/models"
"github.com/hhs/camtalk/internal/store"
)
const (
@@ -33,11 +34,23 @@ type MemoryManager struct {
ttl time.Duration
maxHistory int
stopCleaner chan struct{}
msgRepo store.MessageRepository // 可选消息持久化Write-Through
}
// Option MemoryManager 的函数式选项。
type Option func(*MemoryManager)
// WithMessageRepository 注入消息持久化仓库,启用 Write-Through 模式。
func WithMessageRepository(repo store.MessageRepository) Option {
return func(m *MemoryManager) {
m.msgRepo = repo
}
}
// NewMemoryManager 创建内存版 SessionManager。
// ttl 为会话过期时间maxHistory 为对话历史上限0 表示使用默认值 20
func NewMemoryManager(ttl time.Duration, maxHistory int) *MemoryManager {
// opts 为可选配置,如 WithMessageRepository 启用消息持久化。
func NewMemoryManager(ttl time.Duration, maxHistory int, opts ...Option) *MemoryManager {
if ttl <= 0 {
ttl = defaultTTL
}
@@ -52,6 +65,10 @@ func NewMemoryManager(ttl time.Duration, maxHistory int) *MemoryManager {
stopCleaner: make(chan struct{}),
}
for _, opt := range opts {
opt(m)
}
// 启动后台清理 goroutine每分钟清除过期会话。
go m.cleanLoop()
@@ -242,12 +259,13 @@ func (m *MemoryManager) GetHistory(_ context.Context, sessionID string, limit in
}
// AppendMessage 追加一条对话消息,同时刷新 TTL。
// 若配置了 MessageRepository消息会异步写入 PostgreSQLWrite-Through
func (m *MemoryManager) AppendMessage(_ context.Context, sessionID string, msg models.Message) error {
m.mu.Lock()
defer m.mu.Unlock()
entry, ok := m.sessions[sessionID]
if !ok || m.isExpired(entry) {
m.mu.Unlock()
return ErrSessionNotFound
}
@@ -266,6 +284,17 @@ func (m *MemoryManager) AppendMessage(_ context.Context, sessionID string, msg m
now := time.Now()
entry.lastActive = now
entry.session.UpdatedAt = now
m.mu.Unlock()
// Write-Through异步写冷存储不阻塞调用方
if m.msgRepo != nil {
go func() {
if err := m.msgRepo.SaveMessage(context.Background(), sessionID, msg, 0); err != nil {
logger.Log.Warnw("persist message failed", "session", sessionID, "error", err)
}
}()
}
return nil
}