Rich Enhanced Shell History - Contextual shell history for zsh and bash
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
resh/internal/sesswatch/sesswatch.go

96 lines
2.5 KiB

package sesswatch
import (
"sync"
"time"
"github.com/curusarn/resh/internal/records"
"github.com/mitchellh/go-ps"
"go.uber.org/zap"
)
type sesswatch struct {
sugar *zap.SugaredLogger
sessionsToDrop []chan string
sleepSeconds uint
watchedSessions map[string]bool
mutex sync.Mutex
}
// Go runs the session watcher - watches sessions and sends
func Go(sugar *zap.SugaredLogger,
sessionsToWatch chan records.Record, sessionsToWatchRecords chan records.Record,
sessionsToDrop []chan string, sleepSeconds uint) {
sw := sesswatch{
sugar: sugar.With("module", "sesswatch"),
sessionsToDrop: sessionsToDrop,
sleepSeconds: sleepSeconds,
watchedSessions: map[string]bool{},
}
go sw.waiter(sessionsToWatch, sessionsToWatchRecords)
}
func (s *sesswatch) waiter(sessionsToWatch chan records.Record, sessionsToWatchRecords chan records.Record) {
for {
func() {
select {
case record := <-sessionsToWatch:
// normal way to start watching a session
id := record.SessionID
pid := record.SessionPID
sugar := s.sugar.With(
"sessionID", record.SessionID,
"sessionPID", record.SessionPID,
)
s.mutex.Lock()
defer s.mutex.Unlock()
if s.watchedSessions[id] == false {
sugar.Infow("Starting watching new session")
s.watchedSessions[id] = true
go s.watcher(sugar, id, pid)
}
case record := <-sessionsToWatchRecords:
// additional safety - watch sessions that were never properly initialized
id := record.SessionID
pid := record.SessionPID
sugar := s.sugar.With(
"sessionID", record.SessionID,
"sessionPID", record.SessionPID,
)
s.mutex.Lock()
defer s.mutex.Unlock()
if s.watchedSessions[id] == false {
sugar.Warnw("Starting watching new session based on '/record'")
s.watchedSessions[id] = true
go s.watcher(sugar, id, pid)
}
}
}()
}
}
func (s *sesswatch) watcher(sugar *zap.SugaredLogger, sessionID string, sessionPID int) {
for {
time.Sleep(time.Duration(s.sleepSeconds) * time.Second)
proc, err := ps.FindProcess(sessionPID)
if err != nil {
sugar.Errorw("Error while finding process", "error", err)
} else if proc == nil {
sugar.Infow("Dropping session")
func() {
s.mutex.Lock()
defer s.mutex.Unlock()
s.watchedSessions[sessionID] = false
}()
for _, ch := range s.sessionsToDrop {
sugar.Debugw("Sending 'drop session' message ...")
ch <- sessionID
sugar.Debugw("Sending 'drop session' message DONE")
}
break
}
}
}