101 lines
2.3 KiB
Go
101 lines
2.3 KiB
Go
// Copyright 2018 Lars Hoogestraat
|
|
// Use of this source code is governed by a MIT-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package session
|
|
|
|
import (
|
|
"fmt"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
// Provider an interface for storing and accessing sessions
|
|
type Provider interface {
|
|
Create(sid string) *Session
|
|
Get(sid string) (*Session, error)
|
|
FindByValue(key string, value interface{}) []*Session
|
|
Remove(sid string)
|
|
Clean(ticker *time.Ticker, timeoutAfter time.Duration)
|
|
}
|
|
|
|
// InMemoryProvider implements a in memory storage for sessions
|
|
type InMemoryProvider struct {
|
|
sessions map[string]*Session
|
|
mutex sync.RWMutex
|
|
}
|
|
|
|
// NewInMemoryProvider creates a new in memory provider
|
|
func NewInMemoryProvider() *InMemoryProvider {
|
|
return &InMemoryProvider{
|
|
sessions: make(map[string]*Session),
|
|
}
|
|
}
|
|
|
|
// Create stores a session in the map
|
|
func (imp *InMemoryProvider) Create(sid string) *Session {
|
|
imp.mutex.Lock()
|
|
|
|
defer imp.mutex.Unlock()
|
|
|
|
imp.sessions[sid] = &Session{
|
|
sid: sid,
|
|
lastTouched: time.Now(),
|
|
values: make(map[string]interface{}),
|
|
}
|
|
|
|
return imp.sessions[sid]
|
|
}
|
|
|
|
// Get receives the session from the map by the session identifier
|
|
func (imp *InMemoryProvider) Get(sid string) (*Session, error) {
|
|
imp.mutex.RLock()
|
|
defer imp.mutex.RUnlock()
|
|
if sess, ok := imp.sessions[sid]; ok {
|
|
sess.lastTouched = time.Now()
|
|
return sess, nil
|
|
}
|
|
|
|
return nil, fmt.Errorf("no session with id %s found", sid)
|
|
}
|
|
|
|
// FindByValue finds all sessions from the map found by the key and value
|
|
func (imp *InMemoryProvider) FindByValue(key string, value interface{}) []*Session {
|
|
imp.mutex.RLock()
|
|
|
|
defer imp.mutex.RUnlock()
|
|
|
|
var sessions []*Session
|
|
|
|
for _, s := range imp.sessions {
|
|
if s.values[key] == value {
|
|
sessions = append(sessions, s)
|
|
}
|
|
}
|
|
|
|
return sessions
|
|
}
|
|
|
|
// Remove removes a session by the session identifier from the map
|
|
func (imp *InMemoryProvider) Remove(sid string) {
|
|
imp.mutex.Lock()
|
|
defer imp.mutex.Unlock()
|
|
|
|
delete(imp.sessions, sid)
|
|
}
|
|
|
|
// Clean clean sessions after the specified timeout
|
|
func (imp *InMemoryProvider) Clean(ticker *time.Ticker, timeoutAfter time.Duration) {
|
|
go func() {
|
|
for range ticker.C {
|
|
imp.mutex.Lock()
|
|
for key, value := range imp.sessions {
|
|
if time.Now().After(value.lastTouched.Add(timeoutAfter)) {
|
|
delete(imp.sessions, key)
|
|
}
|
|
}
|
|
imp.mutex.Unlock()
|
|
}
|
|
}()
|
|
}
|