go-full-stack/app/session/memprovider.go

122 lines
2.3 KiB
Go

package session
import (
"container/list"
"sync"
"time"
)
var prov = &Provider{list: list.New()}
type MemSessionStore struct {
timeAccessed time.Time
value map[interface{}]interface{}
sid string
}
func (m *MemSessionStore) Set(key interface{}, value interface{}) error {
m.value[key] = value
err := prov.SessionUpdate(m.sid)
if err != nil {
return err
}
return nil
}
func (m *MemSessionStore) Get(key interface{}) interface{} {
err := prov.SessionUpdate(m.sid)
if err != nil {
return nil
}
if v, ok := m.value[key]; ok {
return v
}
return nil
}
func (m *MemSessionStore) Delete(key interface{}) error {
delete(m.value, key)
err := prov.SessionUpdate(m.sid)
if err != nil {
return err
}
return nil
}
func (m *MemSessionStore) SessionID() string {
return m.sid
}
type Provider struct {
sessions map[string]*list.Element
list *list.List
lock sync.Mutex
}
func (p *Provider) SessionInit(sid string) (ISession, error) {
prov.lock.Lock()
defer prov.lock.Unlock()
v := make(map[interface{}]interface{}, 0)
newSess := &MemSessionStore{sid: sid, timeAccessed: time.Now(), value: v}
elem := prov.list.PushBack(newSess)
prov.sessions[sid] = elem
return newSess, nil
}
func (p *Provider) SessionRead(sid string) (ISession, error) {
if element, ok := prov.sessions[sid]; ok {
return element.Value.(*MemSessionStore), nil
}
sess, err := prov.SessionInit(sid)
return sess, err
}
func (p *Provider) SessionDestroy(sid string) error {
if element, ok := prov.sessions[sid]; ok {
delete(prov.sessions, sid)
prov.list.Remove(element)
}
return nil
}
func (p *Provider) SessionGC(maxLifeTime int64) {
prov.lock.Lock()
defer prov.lock.Unlock()
for {
element := prov.list.Back()
if element == nil {
break
}
if (element.Value.(*MemSessionStore).timeAccessed.Unix() + maxLifeTime) < time.Now().Unix() {
prov.list.Remove(element)
delete(prov.sessions, element.Value.(*MemSessionStore).sid)
} else {
break
}
}
}
func (p *Provider) SessionUpdate(sid string) error {
p.lock.Lock()
defer p.lock.Unlock()
if elem, ok := p.sessions[sid]; ok {
elem.Value.(*MemSessionStore).timeAccessed = time.Now()
p.list.MoveToFront(elem)
return nil
}
return nil
}
func init() {
prov.sessions = make(map[string]*list.Element, 0)
Register("memory", prov)
}