144 lines
3.4 KiB
Go
144 lines
3.4 KiB
Go
// Package memory implements sessions saved into memory is gone when stop the server
|
|
package memory
|
|
|
|
import (
|
|
"container/list"
|
|
"sync"
|
|
"time"
|
|
|
|
"git.mtux.eu/darkgopher/session"
|
|
"git.mtux.eu/darkgopher/session/util"
|
|
)
|
|
|
|
var pder = &ProviderMemory{li: list.New()}
|
|
|
|
func init() {
|
|
pder.sessions = make(map[string]*list.Element, 0)
|
|
session.Register("memory", pder)
|
|
}
|
|
|
|
// ProviderMemory implement memory session provider
|
|
type ProviderMemory struct {
|
|
lock sync.Mutex
|
|
sessions map[string]*list.Element //save to RAM
|
|
li *list.List //for GC
|
|
}
|
|
|
|
func (pder *ProviderMemory) updateAtime(sid string) {
|
|
pder.lock.Lock()
|
|
defer pder.lock.Unlock()
|
|
if ssel, ok := pder.sessions[sid]; ok {
|
|
ssel.Value.(*SessionMemory).atime = time.Now()
|
|
pder.li.MoveToFront(ssel)
|
|
}
|
|
}
|
|
|
|
// SetParams for memory provider not possible
|
|
func (pder *ProviderMemory) SetParams(pr any) error {
|
|
return nil
|
|
}
|
|
|
|
// Init create new session store for sid
|
|
func (pder *ProviderMemory) Init(sid string) (ses session.Session, err error) {
|
|
pder.lock.Lock()
|
|
defer pder.lock.Unlock()
|
|
data := make(map[any]any, 0)
|
|
sess := &SessionMemory{sid, time.Now(), data}
|
|
sessel := pder.li.PushBack(sess)
|
|
pder.sessions[sid] = sessel
|
|
return sess, nil
|
|
}
|
|
|
|
// Load return existing unexpired session or create new
|
|
func (pder *ProviderMemory) Load(sid string) (ses session.Session, err error) {
|
|
pder.lock.Lock()
|
|
defer pder.lock.Unlock()
|
|
if pder.Exists(sid) {
|
|
return pder.sessions[sid].Value.(*SessionMemory), nil
|
|
}
|
|
return pder.Init(sid)
|
|
}
|
|
|
|
// Destroy delete session storage with sid
|
|
func (pder *ProviderMemory) Destroy(sid string) (err error) {
|
|
pder.lock.Lock()
|
|
defer pder.lock.Unlock()
|
|
if ssel, ok := pder.sessions[sid]; ok {
|
|
pder.li.Remove(ssel)
|
|
delete(pder.sessions, sid)
|
|
return nil
|
|
}
|
|
return
|
|
}
|
|
|
|
// ChangeID replace session ID to new one and preserve all data
|
|
func (pder *ProviderMemory) ChangeID(oldsid, newsid string) (err error) {
|
|
pder.lock.Lock()
|
|
defer pder.lock.Unlock()
|
|
if ssel, ok := pder.sessions[oldsid]; ok {
|
|
ssel.Value.(*SessionMemory).sid = newsid //set internal sid to new
|
|
delete(pder.sessions, oldsid) //remove old sid in map
|
|
pder.sessions[newsid] = ssel //add new sid into map
|
|
}
|
|
return
|
|
}
|
|
|
|
// Exists return true if session with sid exists
|
|
func (pder *ProviderMemory) Exists(sid string) (ex bool) {
|
|
if _, ex := pder.sessions[sid]; ex {
|
|
return ex
|
|
}
|
|
return
|
|
}
|
|
|
|
// GC iterate all sessions and delete expired
|
|
func (pder *ProviderMemory) GC(maxlifetime int64) {
|
|
pder.lock.Lock()
|
|
defer pder.lock.Unlock()
|
|
for {
|
|
ssel := pder.li.Back()
|
|
if ssel == nil {
|
|
break
|
|
}
|
|
if ssel.Value.(*SessionMemory).atime.UnixMilli()+(maxlifetime*session.MilisPerSec()) < time.Now().UnixMilli() {
|
|
pder.li.Remove(ssel)
|
|
delete(pder.sessions, ssel.Value.(*SessionMemory).sid)
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
// SessionMemory implement sessionma.Session interface only in memory
|
|
type SessionMemory struct {
|
|
sid string
|
|
atime time.Time
|
|
data map[any]any
|
|
}
|
|
|
|
// Set -
|
|
func (sm *SessionMemory) Set(k, v any) (err error) {
|
|
defer pder.updateAtime(sm.sid)
|
|
defer util.ResolvePanic(&err)
|
|
sm.data[k] = v
|
|
return
|
|
}
|
|
|
|
// Get -
|
|
func (sm *SessionMemory) Get(k any) (v any, err error) {
|
|
defer pder.updateAtime(sm.sid)
|
|
defer util.ResolvePanic(&err)
|
|
return sm.data[k], err
|
|
}
|
|
|
|
// Delete -
|
|
func (sm *SessionMemory) Delete(k any) (err error) {
|
|
defer pder.updateAtime(sm.sid)
|
|
delete(sm.data, k)
|
|
return
|
|
}
|
|
|
|
// SessionID -
|
|
func (sm *SessionMemory) SessionID() string {
|
|
return sm.sid
|
|
}
|