2017-08-04 08:20:59 +00:00
|
|
|
|
package hotime
|
|
|
|
|
|
|
2021-05-24 07:27:41 +08:00
|
|
|
|
import (
|
2026-01-30 17:51:43 +08:00
|
|
|
|
"encoding/json"
|
|
|
|
|
|
"os"
|
|
|
|
|
|
"sync"
|
|
|
|
|
|
"time"
|
|
|
|
|
|
|
2022-03-13 01:12:29 +08:00
|
|
|
|
. "code.hoteas.com/golang/hotime/cache"
|
|
|
|
|
|
. "code.hoteas.com/golang/hotime/common"
|
2021-05-24 07:27:41 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
2026-01-22 02:44:53 +08:00
|
|
|
|
// session对象
|
2017-08-04 08:20:59 +00:00
|
|
|
|
type SessionIns struct {
|
2021-05-28 22:52:22 +08:00
|
|
|
|
*HoTimeCache
|
|
|
|
|
|
SessionId string
|
2017-08-04 08:20:59 +00:00
|
|
|
|
Map
|
2021-05-24 07:27:41 +08:00
|
|
|
|
ContextBase
|
2026-01-22 04:36:52 +08:00
|
|
|
|
mutex sync.RWMutex
|
2017-08-04 08:20:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-22 04:36:52 +08:00
|
|
|
|
// set 保存 session 到缓存,必须在锁内调用或传入深拷贝的 map
|
|
|
|
|
|
func (that *SessionIns) setWithCopy() {
|
2026-01-30 17:51:43 +08:00
|
|
|
|
// #region agent log
|
|
|
|
|
|
logFile, _ := os.OpenFile(`d:\work\hotimev1.5\.cursor\debug.log`, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
|
|
|
|
|
if logFile != nil {
|
|
|
|
|
|
logEntry, _ := json.Marshal(map[string]interface{}{"sessionId": "debug-session", "runId": "run1", "hypothesisId": "A", "location": "session.go:setWithCopy", "message": "Session写入数据库触发", "data": map[string]interface{}{"session_id": that.SessionId, "map_size": len(that.Map)}, "timestamp": time.Now().UnixMilli()})
|
|
|
|
|
|
logFile.Write(append(logEntry, '\n'))
|
|
|
|
|
|
logFile.Close()
|
|
|
|
|
|
}
|
|
|
|
|
|
// #endregion
|
|
|
|
|
|
|
2026-01-22 04:36:52 +08:00
|
|
|
|
// 深拷贝 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)
|
2017-08-04 08:20:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2021-05-25 05:08:17 +08:00
|
|
|
|
func (that *SessionIns) Session(key string, data ...interface{}) *Obj {
|
2026-01-22 04:36:52 +08:00
|
|
|
|
that.mutex.Lock()
|
2021-05-25 05:08:17 +08:00
|
|
|
|
if that.Map == nil {
|
2026-01-22 04:36:52 +08:00
|
|
|
|
that.getWithoutLock()
|
2017-08-04 08:20:59 +00:00
|
|
|
|
}
|
2026-01-22 04:36:52 +08:00
|
|
|
|
that.mutex.Unlock()
|
2017-08-04 08:20:59 +00:00
|
|
|
|
|
2017-08-10 10:14:56 +00:00
|
|
|
|
if len(data) != 0 {
|
2026-01-30 17:51:43 +08:00
|
|
|
|
// #region agent log
|
|
|
|
|
|
logFile, _ := os.OpenFile(`d:\work\hotimev1.5\.cursor\debug.log`, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
|
|
|
|
|
if logFile != nil {
|
|
|
|
|
|
logEntry, _ := json.Marshal(map[string]interface{}{"sessionId": "debug-session", "runId": "run1", "hypothesisId": "B", "location": "session.go:Session", "message": "Session.Set调用", "data": map[string]interface{}{"key": key, "is_delete": data[0] == nil}, "timestamp": time.Now().UnixMilli()})
|
|
|
|
|
|
logFile.Write(append(logEntry, '\n'))
|
|
|
|
|
|
logFile.Close()
|
|
|
|
|
|
}
|
|
|
|
|
|
// #endregion
|
|
|
|
|
|
|
2026-01-22 04:36:52 +08:00
|
|
|
|
that.mutex.Lock()
|
2017-08-10 10:14:56 +00:00
|
|
|
|
if data[0] == nil {
|
2021-05-25 05:08:17 +08:00
|
|
|
|
delete(that.Map, key)
|
2017-08-10 10:14:56 +00:00
|
|
|
|
} else {
|
2021-05-25 05:08:17 +08:00
|
|
|
|
that.Map[key] = data[0]
|
2017-08-04 08:20:59 +00:00
|
|
|
|
}
|
2026-01-22 04:36:52 +08:00
|
|
|
|
that.mutex.Unlock()
|
|
|
|
|
|
|
|
|
|
|
|
// 使用深拷贝版本保存,避免并发问题
|
|
|
|
|
|
that.setWithCopy()
|
2017-08-10 10:14:56 +00:00
|
|
|
|
return &Obj{Data: nil}
|
2017-08-04 08:20:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-22 04:36:52 +08:00
|
|
|
|
that.mutex.RLock()
|
|
|
|
|
|
result := &Obj{Data: that.Map.Get(key)}
|
|
|
|
|
|
that.mutex.RUnlock()
|
|
|
|
|
|
return result
|
2017-08-04 08:20:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-30 17:51:43 +08:00
|
|
|
|
// SessionsSet 批量设置session字段,只触发一次数据库写入
|
|
|
|
|
|
// 用法:that.SessionsSet(Map{"key1": value1, "key2": value2, ...})
|
|
|
|
|
|
// 性能优化:设置N个字段只触发1次数据库写入(而非N次)
|
|
|
|
|
|
func (that *SessionIns) SessionsSet(data Map) {
|
|
|
|
|
|
if len(data) == 0 {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// #region agent log
|
|
|
|
|
|
logFile, _ := os.OpenFile(`d:\work\hotimev1.5\.cursor\debug.log`, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
|
|
|
|
|
if logFile != nil {
|
|
|
|
|
|
keys := make([]string, 0, len(data))
|
|
|
|
|
|
for k := range data {
|
|
|
|
|
|
keys = append(keys, k)
|
|
|
|
|
|
}
|
|
|
|
|
|
logEntry, _ := json.Marshal(map[string]interface{}{"sessionId": "debug-session", "runId": "run1", "hypothesisId": "C", "location": "session.go:SessionsSet", "message": "SessionsSet批量设置", "data": map[string]interface{}{"keys": keys, "count": len(data)}, "timestamp": time.Now().UnixMilli()})
|
|
|
|
|
|
logFile.Write(append(logEntry, '\n'))
|
|
|
|
|
|
logFile.Close()
|
|
|
|
|
|
}
|
|
|
|
|
|
// #endregion
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// #region agent log
|
|
|
|
|
|
logFile, _ := os.OpenFile(`d:\work\hotimev1.5\.cursor\debug.log`, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
|
|
|
|
|
if logFile != nil {
|
|
|
|
|
|
logEntry, _ := json.Marshal(map[string]interface{}{"sessionId": "debug-session", "runId": "run1", "hypothesisId": "C", "location": "session.go:SessionsDelete", "message": "SessionsDelete批量删除", "data": map[string]interface{}{"keys": keys, "count": len(keys)}, "timestamp": time.Now().UnixMilli()})
|
|
|
|
|
|
logFile.Write(append(logEntry, '\n'))
|
|
|
|
|
|
logFile.Close()
|
|
|
|
|
|
}
|
|
|
|
|
|
// #endregion
|
|
|
|
|
|
|
|
|
|
|
|
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", ...)
|
|
|
|
|
|
// 返回 Map,key 为字段名,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
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-22 04:36:52 +08:00
|
|
|
|
// getWithoutLock 内部使用,调用前需要已持有锁
|
|
|
|
|
|
func (that *SessionIns) getWithoutLock() {
|
2021-05-28 22:52:22 +08:00
|
|
|
|
that.Map = that.HoTimeCache.Session(HEAD_SESSION_ADD + that.SessionId).ToMap()
|
|
|
|
|
|
if that.Map != nil {
|
|
|
|
|
|
return
|
2017-08-04 08:20:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2021-05-25 05:08:17 +08:00
|
|
|
|
that.Map = Map{}
|
2026-01-22 04:36:52 +08:00
|
|
|
|
// 保存时也需要深拷贝
|
|
|
|
|
|
copyMap := make(Map, len(that.Map))
|
|
|
|
|
|
for k, v := range that.Map {
|
|
|
|
|
|
copyMap[k] = v
|
|
|
|
|
|
}
|
|
|
|
|
|
that.HoTimeCache.Session(HEAD_SESSION_ADD+that.SessionId, copyMap)
|
|
|
|
|
|
}
|
2017-08-04 08:20:59 +00:00
|
|
|
|
|
2026-01-22 04:36:52 +08:00
|
|
|
|
func (that *SessionIns) get() {
|
|
|
|
|
|
that.mutex.Lock()
|
|
|
|
|
|
defer that.mutex.Unlock()
|
|
|
|
|
|
that.getWithoutLock()
|
2017-08-04 08:20:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2021-05-28 22:52:22 +08:00
|
|
|
|
func (that *SessionIns) Init(cache *HoTimeCache) {
|
2026-01-22 04:36:52 +08:00
|
|
|
|
that.mutex = sync.RWMutex{}
|
2021-05-28 22:52:22 +08:00
|
|
|
|
that.HoTimeCache = cache
|
2017-08-10 10:14:56 +00:00
|
|
|
|
}
|