Do all session pruning in a single goroutine
This commit is contained in:
parent
e8f5809940
commit
c49bbc72d4
@ -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())
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
}()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user