providers/session: Fully-working session system

This commit is contained in:
Sasha Koshka 2024-12-14 01:06:43 -05:00
parent 9858fc4f17
commit 3cc005bece

View File

@ -64,8 +64,8 @@ func (this *Provider) FuncMapFor (document *step.Document) template.FuncMap {
sessions: &this.sessions,
}
return template.FuncMap {
"sessionHTTP": stat.funcSessionHTTP,
"session": stat.funcSession,
"sessionHTTP": stat.funcSessionHTTP,
"session": stat.funcSession,
}
}
@ -94,14 +94,17 @@ func (this *state) funcSessionHTTP (
} else {
expiration = time.Now().Add(this.lifetime)
}
var result *session
var result *Session
if session, ok := this.checkSession(id); ok {
if this.lifetime != 0 {
session.setExpiration(expiration)
}
result = session
} else {
session, err := this.startSession(expiration)
if id == (uuid.UUID { }) {
id = uuid.New()
}
session, err := this.newSession(id, expiration)
if err != nil { return nil, err }
result = session
}
@ -114,42 +117,33 @@ func (this *state) funcSessionHTTP (
return result, nil
}
func (this *state) funcSession (id uuid.UUID) (*session, error) {
func (this *state) funcSession (id uuid.UUID) (*Session, error) {
expires := time.Now().Add(this.lifetime)
if session, ok := this.checkSession(id); ok {
session.setExpiration(expires)
return session, nil
}
return this.startSession(expires)
return this.newSession(id, expires)
}
func (this *state) checkSession (id uuid.UUID) (*session, bool) {
func (this *state) checkSession (id uuid.UUID) (*Session, bool) {
sessions, done := this.sessions.RBorrow()
defer done()
session, ok := sessions[id]
log.Println(ok)
if !ok || session.Expired() { return nil, false }
return session, true
}
func (this *state) startSession (expires time.Time) (*session, error) {
sessions, done := this.sessions.Borrow()
defer done()
id := uuid.New()
// air defense
if _, exists := sessions[id]; exists { return nil, step.ErrPigsFlying }
session := &Session {
func (this *state) newSession (id uuid.UUID, expires time.Time) (*Session, error) {
return &Session {
parent: this,
id: id,
data: usync.NewRWLocker(make(map[string] any)),
expires: usync.NewRWLocker(expires),
}
sessions[id] = session
log.Println(id)
return session, nil
}, nil
}
type sessionMap = map[uuid.UUID] *Session
type sessionMap map[uuid.UUID] *Session
type Session struct {
parent *state // immutable
@ -172,6 +166,7 @@ func (this *Session) Set (name string, value any) string {
data, done := this.data.Borrow()
defer done()
data[name] = value
this.addSelf()
return ""
}
@ -186,17 +181,27 @@ func (this *Session) Clear () string {
data, done := this.data.Borrow()
defer done()
clear(data)
this.delSelf()
return ""
}
func (this *Session) Close () (string, error) {
func (this *Session) String () string {
return this.id.String()
}
func (this *Session) addSelf () (string, error) {
sessions, done := this.parent.sessions.Borrow()
defer done()
sessions[this.id] = this
log.Println("ADD", sessions)
return "", nil
}
func (this *Session) delSelf () (string, error) {
sessions, done := this.parent.sessions.Borrow()
defer done()
if _, ok := sessions[this.id]; ok {
return "", step.ErrDoubleClose
}
delete(sessions, this.id)
this.Clear()
log.Println("DEL", sessions)
return "", nil
}
@ -215,5 +220,5 @@ func (this *Session) setExpiration (expires time.Time) string {
}
func (this *Session) Expired () bool {
return this.Expiration().After(time.Now())
return this.Expiration().Before(time.Now())
}