138 lines
3.2 KiB
Go
138 lines
3.2 KiB
Go
|
package service
|
||
|
|
||
|
import (
|
||
|
"reflect"
|
||
|
"sync"
|
||
|
"time"
|
||
|
|
||
|
"apigo.cc/gojs"
|
||
|
"apigo.cc/gojs/goja"
|
||
|
"github.com/ssgo/log"
|
||
|
"github.com/ssgo/redis"
|
||
|
)
|
||
|
|
||
|
type Session struct {
|
||
|
id string
|
||
|
conn *redis.Redis
|
||
|
data map[string]any
|
||
|
}
|
||
|
|
||
|
var sessionRedis *redis.Redis
|
||
|
var sessionTimeout = int64(3600)
|
||
|
var memorySessionData = map[string]map[string]any{}
|
||
|
var memorySessionDataLock = sync.RWMutex{}
|
||
|
var lastSessionClearTime int64
|
||
|
|
||
|
func NewSession(id string, logger *log.Logger) *Session {
|
||
|
data := map[string]any{}
|
||
|
conn := sessionRedis
|
||
|
if sessionRedis == nil {
|
||
|
memorySessionDataLock.RLock()
|
||
|
if data1, ok1 := memorySessionData[id]; ok1 && data1 != nil {
|
||
|
data = data1
|
||
|
}
|
||
|
memorySessionDataLock.RUnlock()
|
||
|
} else {
|
||
|
conn = sessionRedis.CopyByLogger(logger)
|
||
|
err := conn.GET("SESS_" + id).To(&data)
|
||
|
if err == nil {
|
||
|
conn.EXPIRE("SESS_"+id, int(sessionTimeout))
|
||
|
}
|
||
|
}
|
||
|
return &Session{
|
||
|
id: id,
|
||
|
conn: conn,
|
||
|
data: data,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (session *Session) Set(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
|
||
|
args := gojs.MakeArgs(&argsIn, vm).Check(1)
|
||
|
if args.Arguments[0].ExportType().Kind() == reflect.Map {
|
||
|
for key, value := range args.Map(0) {
|
||
|
session.data[key] = value
|
||
|
}
|
||
|
} else {
|
||
|
args.Check(2)
|
||
|
session.data[args.Str(0)] = args.Any(1)
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (session *Session) Get(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
|
||
|
args := gojs.MakeArgs(&argsIn, vm).Check(1)
|
||
|
if len(args.Arguments) == 1 {
|
||
|
if args.Arguments[0].ExportType().Kind() == reflect.Slice {
|
||
|
out := make(map[string]any)
|
||
|
for _, key := range args.Arr(0).StrArray(0) {
|
||
|
out[key] = session.data[key]
|
||
|
}
|
||
|
return vm.ToValue(out)
|
||
|
} else {
|
||
|
return vm.ToValue(session.data[args.Str(0)])
|
||
|
}
|
||
|
} else {
|
||
|
out := make(map[string]any)
|
||
|
for _, key := range args.StrArray(0) {
|
||
|
out[key] = session.data[key]
|
||
|
}
|
||
|
return vm.ToValue(out)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (session *Session) Remove(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
|
||
|
args := gojs.MakeArgs(&argsIn, vm).Check(1)
|
||
|
if args.Arguments[0].ExportType().Kind() == reflect.Slice {
|
||
|
out := make(map[string]any)
|
||
|
for _, key := range args.Arr(0).StrArray(0) {
|
||
|
delete(session.data, key)
|
||
|
}
|
||
|
return vm.ToValue(out)
|
||
|
} else {
|
||
|
for _, key := range args.StrArray(0) {
|
||
|
delete(session.data, key)
|
||
|
}
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (session *Session) SetAuthLevel(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
|
||
|
args := gojs.MakeArgs(&argsIn, vm).Check(1)
|
||
|
session.data["_authLevel"] = args.Int(0)
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (session *Session) Save(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
|
||
|
if session.conn == nil {
|
||
|
now := time.Now().Unix()
|
||
|
session.data["_time"] = now
|
||
|
memorySessionDataLock.Lock()
|
||
|
memorySessionData[session.id] = session.data
|
||
|
clearTimeDiff := now - lastSessionClearTime
|
||
|
if clearTimeDiff > 60 {
|
||
|
lastSessionClearTime = now
|
||
|
}
|
||
|
memorySessionDataLock.Unlock()
|
||
|
|
||
|
if clearTimeDiff > 60 {
|
||
|
go clearMemorySession()
|
||
|
}
|
||
|
} else {
|
||
|
session.conn.SETEX("SESS_"+session.id, int(sessionTimeout), session.data)
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func clearMemorySession() {
|
||
|
memorySessionDataLock.Lock()
|
||
|
now := time.Now().Unix()
|
||
|
for id, data := range memorySessionData {
|
||
|
if data["_time"] != nil {
|
||
|
if now-data["_time"].(int64) > sessionTimeout {
|
||
|
delete(memorySessionData, id)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
memorySessionDataLock.Unlock()
|
||
|
}
|