Do all session pruning in a single goroutine

This commit is contained in:
Ken-Håvard Lieng 2018-06-01 05:40:12 +02:00
parent e8f5809940
commit c49bbc72d4
3 changed files with 38 additions and 20 deletions

View File

@ -35,6 +35,8 @@ func (d *Dispatch) handleAuth(w http.ResponseWriter, r *http.Request, createUser
d.states.deleteSession(key)
session.SetCookie(w, r)
}
} else {
d.states.deleteSession(key)
}
}
@ -76,7 +78,6 @@ func (d *Dispatch) newUser(w http.ResponseWriter, r *http.Request) (*State, erro
return nil, err
}
d.states.setSession(session)
go d.deleteSessionWhenExpired(session)
state := NewState(user, d)
d.states.set(state)
@ -86,12 +87,3 @@ func (d *Dispatch) newUser(w http.ResponseWriter, r *http.Request) (*State, erro
return state, nil
}
func (d *Dispatch) deleteSessionWhenExpired(session *session.Session) {
deleteSessionWhenExpired(session, d.states)
}
func deleteSessionWhenExpired(session *session.Session, stateStore *stateStore) {
session.WaitUntilExpiration()
stateStore.deleteSession(session.Key())
}

View File

@ -45,6 +45,7 @@ func (d *Dispatch) Run() {
session.CookieName = "dispatch"
d.states = newStateStore(d.SessionStore)
go d.states.run()
d.loadUsers()
d.initFileServer()
@ -57,7 +58,7 @@ func (d *Dispatch) loadUsers() {
log.Fatal(err)
}
log.Printf("Loading %d user(s)", len(users))
log.Printf("[Init] %d users", len(users))
for _, user := range users {
go d.loadUser(user)

View File

@ -244,11 +244,12 @@ func newStateStore(sessionStore storage.SessionStore) *stateStore {
log.Fatal(err)
}
log.Printf("[Init] %d sessions", len(sessions))
for _, session := range sessions {
if !session.Expired() {
session.Init()
store.sessions[session.Key()] = session
go deleteSessionWhenExpired(session, store)
} else {
go sessionStore.DeleteSession(session.Key())
}
@ -257,6 +258,22 @@ func newStateStore(sessionStore storage.SessionStore) *stateStore {
return store
}
func (s *stateStore) run() {
pruneSessions := time.Tick(time.Minute * 5)
for {
select {
case <-pruneSessions:
s.lock.Lock()
for key, session := range s.sessions {
if session.Expired() {
s.internalDeleteSession(key)
}
}
s.lock.Unlock()
}
}
}
func (s *stateStore) get(id uint64) *State {
s.lock.Lock()
state := s.states[id]
@ -298,20 +315,27 @@ func (s *stateStore) setSession(session *session.Session) {
func (s *stateStore) deleteSession(key string) {
s.lock.Lock()
s.internalDeleteSession(key)
s.lock.Unlock()
}
func (s *stateStore) internalDeleteSession(key string) {
id := s.sessions[key].UserID
delete(s.sessions, key)
n := 0
for _, session := range s.sessions {
if session.UserID == id {
n++
}
}
state := s.states[id]
if n == 0 {
delete(s.states, id)
}
s.lock.Unlock()
go func() {
if n == 0 {
// This anonymous user is not reachable anymore since all sessions have
// expired, so we clean it up
@ -319,5 +343,6 @@ func (s *stateStore) deleteSession(key string) {
state.user.Remove()
}
go s.sessionStore.DeleteSession(key)
s.sessionStore.DeleteSession(key)
}()
}