Files
urldb/services/search_session.go
2025-10-31 23:32:57 +08:00

231 lines
5.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package services
import (
"sync"
"time"
"github.com/ctwj/urldb/db/entity"
)
// SearchSession 搜索会话
type SearchSession struct {
UserID string // 用户ID
Keyword string // 搜索关键字
Resources []entity.Resource // 搜索结果
PageSize int // 每页数量
CurrentPage int // 当前页码
TotalPages int // 总页数
LastAccess time.Time // 最后访问时间
}
// SearchSessionManager 搜索会话管理器
type SearchSessionManager struct {
sessions map[string]*SearchSession // 用户ID -> 搜索会话
mutex sync.RWMutex
}
// NewSearchSessionManager 创建搜索会话管理器
func NewSearchSessionManager() *SearchSessionManager {
manager := &SearchSessionManager{
sessions: make(map[string]*SearchSession),
}
// 启动清理过期会话的goroutine
go manager.cleanupExpiredSessions()
return manager
}
// CreateSession 创建或更新搜索会话
func (m *SearchSessionManager) CreateSession(userID, keyword string, resources []entity.Resource, pageSize int) *SearchSession {
m.mutex.Lock()
defer m.mutex.Unlock()
session := &SearchSession{
UserID: userID,
Keyword: keyword,
Resources: resources,
PageSize: pageSize,
CurrentPage: 1,
TotalPages: (len(resources) + pageSize - 1) / pageSize,
LastAccess: time.Now(),
}
m.sessions[userID] = session
return session
}
// GetSession 获取搜索会话
func (m *SearchSessionManager) GetSession(userID string) *SearchSession {
m.mutex.RLock()
defer m.mutex.RUnlock()
session, exists := m.sessions[userID]
if !exists {
return nil
}
// 更新最后访问时间
m.mutex.RUnlock()
m.mutex.Lock()
session.LastAccess = time.Now()
m.mutex.Unlock()
m.mutex.RLock()
return session
}
// SetCurrentPage 设置当前页
func (m *SearchSessionManager) SetCurrentPage(userID string, page int) bool {
m.mutex.Lock()
defer m.mutex.Unlock()
session, exists := m.sessions[userID]
if !exists {
return false
}
if page < 1 || page > session.TotalPages {
return false
}
session.CurrentPage = page
session.LastAccess = time.Now()
return true
}
// GetPageResources 获取指定页的资源
func (m *SearchSessionManager) GetPageResources(userID string, page int) []entity.Resource {
m.mutex.RLock()
session, exists := m.sessions[userID]
m.mutex.RUnlock()
if !exists {
return nil
}
if page < 1 || page > session.TotalPages {
return nil
}
start := (page - 1) * session.PageSize
end := start + session.PageSize
if end > len(session.Resources) {
end = len(session.Resources)
}
// 更新当前页和最后访问时间
m.mutex.Lock()
session.CurrentPage = page
session.LastAccess = time.Now()
m.mutex.Unlock()
return session.Resources[start:end]
}
// GetCurrentPageResources 获取当前页的资源
func (m *SearchSessionManager) GetCurrentPageResources(userID string) []entity.Resource {
m.mutex.RLock()
session, exists := m.sessions[userID]
m.mutex.RUnlock()
if !exists {
return nil
}
return m.GetPageResources(userID, session.CurrentPage)
}
// HasNextPage 是否有下一页
func (m *SearchSessionManager) HasNextPage(userID string) bool {
m.mutex.RLock()
defer m.mutex.RUnlock()
session, exists := m.sessions[userID]
if !exists {
return false
}
return session.CurrentPage < session.TotalPages
}
// HasPrevPage 是否有上一页
func (m *SearchSessionManager) HasPrevPage(userID string) bool {
m.mutex.RLock()
defer m.mutex.RUnlock()
session, exists := m.sessions[userID]
if !exists {
return false
}
return session.CurrentPage > 1
}
// NextPage 下一页
func (m *SearchSessionManager) NextPage(userID string) []entity.Resource {
m.mutex.Lock()
session, exists := m.sessions[userID]
m.mutex.Unlock()
if !exists {
return nil
}
if session.CurrentPage >= session.TotalPages {
return nil
}
return m.GetPageResources(userID, session.CurrentPage+1)
}
// PrevPage 上一页
func (m *SearchSessionManager) PrevPage(userID string) []entity.Resource {
m.mutex.Lock()
session, exists := m.sessions[userID]
m.mutex.Unlock()
if !exists {
return nil
}
if session.CurrentPage <= 1 {
return nil
}
return m.GetPageResources(userID, session.CurrentPage-1)
}
// GetPageInfo 获取分页信息
func (m *SearchSessionManager) GetPageInfo(userID string) (currentPage, totalPages int, hasPrev, hasNext bool) {
m.mutex.RLock()
defer m.mutex.RUnlock()
session, exists := m.sessions[userID]
if !exists {
return 0, 0, false, false
}
return session.CurrentPage, session.TotalPages, session.CurrentPage > 1, session.CurrentPage < session.TotalPages
}
// cleanupExpiredSessions 清理过期会话超过1小时未访问
func (m *SearchSessionManager) cleanupExpiredSessions() {
ticker := time.NewTicker(10 * time.Minute)
defer ticker.Stop()
for range ticker.C {
m.mutex.Lock()
now := time.Now()
for userID, session := range m.sessions {
// 如果超过1小时未访问清理该会话
if now.Sub(session.LastAccess) > time.Hour {
delete(m.sessions, userID)
}
}
m.mutex.Unlock()
}
}
// GlobalSearchSessionManager 全局搜索会话管理器
var GlobalSearchSessionManager = NewSearchSessionManager()