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)
|
d.states.deleteSession(key)
|
||||||
session.SetCookie(w, r)
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
d.states.setSession(session)
|
d.states.setSession(session)
|
||||||
go d.deleteSessionWhenExpired(session)
|
|
||||||
|
|
||||||
state := NewState(user, d)
|
state := NewState(user, d)
|
||||||
d.states.set(state)
|
d.states.set(state)
|
||||||
@ -86,12 +87,3 @@ func (d *Dispatch) newUser(w http.ResponseWriter, r *http.Request) (*State, erro
|
|||||||
|
|
||||||
return state, nil
|
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"
|
session.CookieName = "dispatch"
|
||||||
|
|
||||||
d.states = newStateStore(d.SessionStore)
|
d.states = newStateStore(d.SessionStore)
|
||||||
|
go d.states.run()
|
||||||
|
|
||||||
d.loadUsers()
|
d.loadUsers()
|
||||||
d.initFileServer()
|
d.initFileServer()
|
||||||
@ -57,7 +58,7 @@ func (d *Dispatch) loadUsers() {
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("Loading %d user(s)", len(users))
|
log.Printf("[Init] %d users", len(users))
|
||||||
|
|
||||||
for _, user := range users {
|
for _, user := range users {
|
||||||
go d.loadUser(user)
|
go d.loadUser(user)
|
||||||
|
@ -244,11 +244,12 @@ func newStateStore(sessionStore storage.SessionStore) *stateStore {
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Printf("[Init] %d sessions", len(sessions))
|
||||||
|
|
||||||
for _, session := range sessions {
|
for _, session := range sessions {
|
||||||
if !session.Expired() {
|
if !session.Expired() {
|
||||||
session.Init()
|
session.Init()
|
||||||
store.sessions[session.Key()] = session
|
store.sessions[session.Key()] = session
|
||||||
go deleteSessionWhenExpired(session, store)
|
|
||||||
} else {
|
} else {
|
||||||
go sessionStore.DeleteSession(session.Key())
|
go sessionStore.DeleteSession(session.Key())
|
||||||
}
|
}
|
||||||
@ -257,6 +258,22 @@ func newStateStore(sessionStore storage.SessionStore) *stateStore {
|
|||||||
return store
|
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 {
|
func (s *stateStore) get(id uint64) *State {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
state := s.states[id]
|
state := s.states[id]
|
||||||
@ -298,26 +315,34 @@ func (s *stateStore) setSession(session *session.Session) {
|
|||||||
|
|
||||||
func (s *stateStore) deleteSession(key string) {
|
func (s *stateStore) deleteSession(key string) {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
|
s.internalDeleteSession(key)
|
||||||
|
s.lock.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stateStore) internalDeleteSession(key string) {
|
||||||
id := s.sessions[key].UserID
|
id := s.sessions[key].UserID
|
||||||
delete(s.sessions, key)
|
delete(s.sessions, key)
|
||||||
|
|
||||||
n := 0
|
n := 0
|
||||||
for _, session := range s.sessions {
|
for _, session := range s.sessions {
|
||||||
if session.UserID == id {
|
if session.UserID == id {
|
||||||
n++
|
n++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state := s.states[id]
|
state := s.states[id]
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
delete(s.states, id)
|
delete(s.states, id)
|
||||||
}
|
}
|
||||||
s.lock.Unlock()
|
|
||||||
|
|
||||||
if n == 0 {
|
go func() {
|
||||||
// This anonymous user is not reachable anymore since all sessions have
|
if n == 0 {
|
||||||
// expired, so we clean it up
|
// This anonymous user is not reachable anymore since all sessions have
|
||||||
state.kill()
|
// expired, so we clean it up
|
||||||
state.user.Remove()
|
state.kill()
|
||||||
}
|
state.user.Remove()
|
||||||
|
}
|
||||||
|
|
||||||
go s.sessionStore.DeleteSession(key)
|
s.sessionStore.DeleteSession(key)
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user