Files
hotime/session.go
T
hoteas 87098a9180 refactor(db): 增强测试事务和缓存管理
- 在 HoTimeDB 中新增 testMu 互斥锁,确保 testTx 的串行访问,解决并发冲突问题
- 在 BeginTestTx 中初始化 testMu,确保测试事务的安全性
- 在 HoTimeCache 中新增 DisableDbCache 方法,测试模式下禁用 DB 和 Redis 缓存,避免锁等待超时
- 更新 Select 方法,确保在 testTx 激活时跳过缓存逻辑,提升测试稳定性
- 优化 Swagger 生成逻辑,支持模块化输出和导航页生成
- 移除冗余的调试日志代码,提升代码整洁性
2026-03-14 13:06:32 +08:00

160 lines
3.3 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 hotime
import (
"sync"
. "code.hoteas.com/golang/hotime/cache"
. "code.hoteas.com/golang/hotime/common"
)
// session对象
type SessionIns struct {
*HoTimeCache
SessionId string
Map
ContextBase
mutex sync.RWMutex
}
// set 保存 session 到缓存,必须在锁内调用或传入深拷贝的 map
func (that *SessionIns) setWithCopy() {
// 深拷贝 Map 防止并发修改
that.mutex.RLock()
copyMap := make(Map, len(that.Map))
for k, v := range that.Map {
copyMap[k] = v
}
that.mutex.RUnlock()
that.HoTimeCache.Session(HEAD_SESSION_ADD+that.SessionId, copyMap)
}
func (that *SessionIns) Session(key string, data ...interface{}) *Obj {
that.mutex.Lock()
if that.Map == nil {
that.getWithoutLock()
}
that.mutex.Unlock()
if len(data) != 0 {
that.mutex.Lock()
if data[0] == nil {
delete(that.Map, key)
} else {
that.Map[key] = data[0]
}
that.mutex.Unlock()
// 使用深拷贝版本保存,避免并发问题
that.setWithCopy()
return &Obj{Data: nil}
}
that.mutex.RLock()
result := &Obj{Data: that.Map.Get(key)}
that.mutex.RUnlock()
return result
}
// SessionsSet 批量设置session字段,只触发一次数据库写入
// 用法:that.SessionsSet(Map{"key1": value1, "key2": value2, ...})
// 性能优化:设置N个字段只触发1次数据库写入(而非N次)
func (that *SessionIns) SessionsSet(data Map) {
if len(data) == 0 {
return
}
that.mutex.Lock()
if that.Map == nil {
that.getWithoutLock()
}
// 批量设置所有字段
for key, value := range data {
if value == nil {
delete(that.Map, key)
} else {
that.Map[key] = value
}
}
that.mutex.Unlock()
// 只触发一次数据库写入
that.setWithCopy()
}
// SessionsDelete 批量删除session字段,只触发一次数据库写入
// 用法:that.SessionsDelete("key1", "key2", ...)
func (that *SessionIns) SessionsDelete(keys ...string) {
if len(keys) == 0 {
return
}
that.mutex.Lock()
if that.Map == nil {
that.getWithoutLock()
}
// 批量删除所有字段
for _, key := range keys {
delete(that.Map, key)
}
that.mutex.Unlock()
// 只触发一次数据库写入
that.setWithCopy()
}
// SessionsGet 批量获取session字段
// 用法:result := that.SessionsGet("key1", "key2", ...)
// 返回 Mapkey 为字段名,value 为字段值(不存在的 key 不包含在结果中)
func (that *SessionIns) SessionsGet(keys ...string) Map {
if len(keys) == 0 {
return Map{}
}
that.mutex.Lock()
if that.Map == nil {
that.getWithoutLock()
}
that.mutex.Unlock()
result := make(Map, len(keys))
that.mutex.RLock()
for _, key := range keys {
if value, exists := that.Map[key]; exists {
result[key] = value
}
}
that.mutex.RUnlock()
return result
}
// getWithoutLock 内部使用,调用前需要已持有锁
func (that *SessionIns) getWithoutLock() {
that.Map = that.HoTimeCache.Session(HEAD_SESSION_ADD + that.SessionId).ToMap()
if that.Map != nil {
return
}
that.Map = Map{}
// 保存时也需要深拷贝
copyMap := make(Map, len(that.Map))
for k, v := range that.Map {
copyMap[k] = v
}
that.HoTimeCache.Session(HEAD_SESSION_ADD+that.SessionId, copyMap)
}
func (that *SessionIns) get() {
that.mutex.Lock()
defer that.mutex.Unlock()
that.getWithoutLock()
}
func (that *SessionIns) Init(cache *HoTimeCache) {
that.mutex = sync.RWMutex{}
that.HoTimeCache = cache
}