| package handler |
|
|
| import ( |
| "aurora/internal/chatgpt" |
| "log" |
| "sync" |
| "time" |
| ) |
|
|
| |
| |
| type SessionManager struct { |
| mu sync.RWMutex |
| sessions map[string]*sessionEntry |
| ttl time.Duration |
| } |
|
|
| type sessionEntry struct { |
| state *chatgpt.ChatClientState |
| lastUsed time.Time |
| } |
|
|
| const defaultSessionTTL = 30 * time.Minute |
|
|
| func NewSessionManager() *SessionManager { |
| sm := &SessionManager{ |
| sessions: make(map[string]*sessionEntry), |
| ttl: defaultSessionTTL, |
| } |
| go sm.cleanupLoop() |
| return sm |
| } |
|
|
| func (sm *SessionManager) Get(conversationID string) *chatgpt.ChatClientState { |
| if conversationID == "" { |
| return nil |
| } |
| sm.mu.RLock() |
| entry, ok := sm.sessions[conversationID] |
| sm.mu.RUnlock() |
| if !ok { |
| return nil |
| } |
| sm.mu.Lock() |
| entry.lastUsed = time.Now() |
| sm.mu.Unlock() |
| return entry.state |
| } |
|
|
| func (sm *SessionManager) Register(conversationID string, state *chatgpt.ChatClientState) { |
| if conversationID == "" || state == nil { |
| return |
| } |
| sm.mu.Lock() |
| defer sm.mu.Unlock() |
| sm.sessions[conversationID] = &sessionEntry{ |
| state: state, |
| lastUsed: time.Now(), |
| } |
| } |
|
|
| func (sm *SessionManager) cleanupLoop() { |
| ticker := time.NewTicker(10 * time.Minute) |
| defer ticker.Stop() |
| for range ticker.C { |
| sm.mu.Lock() |
| now := time.Now() |
| removed := 0 |
| for convID, entry := range sm.sessions { |
| if now.Sub(entry.lastUsed) > sm.ttl { |
| delete(sm.sessions, convID) |
| removed++ |
| } |
| } |
| if removed > 0 { |
| log.Printf("[session] 清理过期 session %d 个,当前活跃 %d 个", removed, len(sm.sessions)) |
| } |
| sm.mu.Unlock() |
| } |
| } |
|
|