You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
117 lines
2.8 KiB
Go
117 lines
2.8 KiB
Go
//////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Given is a SessionManager that stores session information in
|
|
// memory. The SessionManager itself is working, however, since we
|
|
// keep on adding new sessions to the manager our program will
|
|
// eventually run out of memory.
|
|
//
|
|
// Your task is to implement a session cleaner routine that runs
|
|
// concurrently in the background and cleans every session that
|
|
// hasn't been updated for more than 5 seconds (of course usually
|
|
// session times are much longer).
|
|
//
|
|
// Note that we expect the session to be removed anytime between 5 and
|
|
// 7 seconds after the last update. Also, note that you have to be
|
|
// very careful in order to prevent race conditions.
|
|
//
|
|
|
|
package main
|
|
|
|
import (
|
|
"errors"
|
|
"log"
|
|
)
|
|
|
|
// SessionManager keeps track of all sessions from creation, updating
|
|
// to destroying.
|
|
type SessionManager struct {
|
|
sessions map[string]Session
|
|
}
|
|
|
|
// Session stores the session's data
|
|
type Session struct {
|
|
Data map[string]interface{}
|
|
}
|
|
|
|
// NewSessionManager creates a new sessionManager
|
|
func NewSessionManager() *SessionManager {
|
|
m := &SessionManager{
|
|
sessions: make(map[string]Session),
|
|
}
|
|
|
|
return m
|
|
}
|
|
|
|
// CreateSession creates a new session and returns the sessionID
|
|
func (m *SessionManager) CreateSession() (string, error) {
|
|
sessionID, err := MakeSessionID()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
m.sessions[sessionID] = Session{
|
|
Data: make(map[string]interface{}),
|
|
}
|
|
|
|
return sessionID, nil
|
|
}
|
|
|
|
// ErrSessionNotFound returned when sessionID not listed in
|
|
// SessionManager
|
|
var ErrSessionNotFound = errors.New("SessionID does not exists")
|
|
|
|
// GetSessionData returns data related to session if sessionID is
|
|
// found, errors otherwise
|
|
func (m *SessionManager) GetSessionData(sessionID string) (map[string]interface{}, error) {
|
|
session, ok := m.sessions[sessionID]
|
|
if !ok {
|
|
return nil, ErrSessionNotFound
|
|
}
|
|
return session.Data, nil
|
|
}
|
|
|
|
// UpdateSessionData overwrites the old session data with the new one
|
|
func (m *SessionManager) UpdateSessionData(sessionID string, data map[string]interface{}) error {
|
|
_, ok := m.sessions[sessionID]
|
|
if !ok {
|
|
return ErrSessionNotFound
|
|
}
|
|
|
|
// Hint: you should renew expiry of the session here
|
|
m.sessions[sessionID] = Session{
|
|
Data: data,
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func main() {
|
|
// Create new sessionManager and new session
|
|
m := NewSessionManager()
|
|
sID, err := m.CreateSession()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
log.Println("Created new session with ID", sID)
|
|
|
|
// Update session data
|
|
data := make(map[string]interface{})
|
|
data["website"] = "longhoang.de"
|
|
|
|
err = m.UpdateSessionData(sID, data)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
log.Println("Update session data, set website to longhoang.de")
|
|
|
|
// Retrieve data from manager again
|
|
updatedData, err := m.GetSessionData(sID)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
log.Println("Get session data:", updatedData)
|
|
}
|