open-consul/consul/session_ttl.go

97 lines
2.4 KiB
Go

package consul
import (
"fmt"
"github.com/hashicorp/consul/consul/structs"
"time"
)
func (s *Server) initializeSessionTimers() error {
s.sessionTimersLock.Lock()
s.sessionTimers = make(map[string]*time.Timer)
s.sessionTimersLock.Unlock()
// walk the TTL index and resetSessionTimer for each non-zero TTL
state := s.fsm.State()
_, sessions, err := state.SessionListTTL()
if err != nil {
return err
}
for _, session := range sessions {
err := s.resetSessionTimer(session.ID, session)
if err != nil {
return err
}
}
return nil
}
func (s *Server) resetSessionTimer(id string, session *structs.Session) error {
if session == nil {
var err error
// find the session
state := s.fsm.State()
_, session, err = state.SessionGet(id)
if err != nil || session == nil {
return fmt.Errorf("Could not find session for '%s'\n", id)
}
}
if session.TTL != "" {
ttl, err := time.ParseDuration(session.TTL)
if err != nil {
return fmt.Errorf("Invalid Session TTL '%s': %v", session.TTL, err)
}
s.sessionTimersLock.Lock()
if s.sessionTimers == nil {
// should not happen . . .
panic(fmt.Sprintf("Invalid call to resetSessionTimer before creation of session timers in leaderLoop"))
}
defer s.sessionTimersLock.Unlock()
if t := s.sessionTimers[id]; t != nil {
// TBD may modify the session's active TTL based on load here
t.Reset(ttl * structs.SessionTTLMultiplier)
} else {
s.sessionTimers[session.ID] = time.AfterFunc(ttl*structs.SessionTTLMultiplier, func() {
s.sessionTimers[session.ID].Stop()
args := structs.SessionRequest{
Datacenter: s.config.Datacenter,
Op: structs.SessionDestroy,
}
args.Session.ID = session.ID
// Apply the update to destroy the session
_, err := s.raftApply(structs.SessionRequestType, args)
if err != nil {
s.logger.Printf("[ERR] consul.session: Apply failed: %v", err)
}
})
}
}
return nil
}
func (s *Server) clearSessionTimer(id string) error {
s.sessionTimersLock.Lock()
defer s.sessionTimersLock.Unlock()
if s.sessionTimers[id] != nil {
// stop the session timer and delete from the map
s.sessionTimers[id].Stop()
delete(s.sessionTimers, id)
}
return nil
}
func (s *Server) clearAllSessionTimers() error {
s.sessionTimersLock.Lock()
defer s.sessionTimersLock.Unlock()
// stop all timers and clear out the map
for id, t := range s.sessionTimers {
t.Stop()
delete(s.sessionTimers, id)
}
return nil
}