linstrom/storage-new/cleaners/manager.go

74 lines
1.6 KiB
Go

package cleaners
import (
"sync"
"time"
"github.com/rs/zerolog/log"
)
type CleanerManager struct {
activeCleaners map[string]bool
activeCleanerLock sync.Mutex
exitChans []chan any
}
var cleanerBuilders = []func() (onTick func(time.Time), name string, tickSpeed time.Duration){}
func NewManager() *CleanerManager {
activeCleaners := make(map[string]bool)
exitChans := []chan any{}
cm := &CleanerManager{
activeCleaners: activeCleaners,
exitChans: exitChans,
}
// Launch all cleaner tickers in a new goroutine each
for _, builder := range cleanerBuilders {
exitChan := make(chan any, 1)
onTick, name, tickSpeed := builder()
cm.exitChans = append(cm.exitChans, exitChan)
log.Info().Str("name", name).Msg("Starting ticker for cleaner")
go cm.tickOrExit(tickSpeed, name, exitChan, onTick)
}
return cm
}
func (m *CleanerManager) Stop() {
for _, exitChan := range m.exitChans {
exitChan <- 1
}
}
func (m *CleanerManager) tickOrExit(
tickSpeed time.Duration,
name string,
exitChan chan any,
onTick func(time.Time),
) {
ticker := time.Tick(tickSpeed)
for {
select {
case now := <-ticker:
go m.wrapOnTick(name, now, onTick)
case <-exitChan:
return
}
}
}
func (m *CleanerManager) wrapOnTick(name string, now time.Time, onTick func(time.Time)) {
m.activeCleanerLock.Lock()
if m.activeCleaners[name] {
m.activeCleanerLock.Unlock()
return
}
m.activeCleaners[name] = true
m.activeCleanerLock.Unlock()
log.Info().Str("cleaner", name).Msg("Ticking cleaner")
onTick(now)
m.activeCleanerLock.Lock()
m.activeCleaners[name] = false
m.activeCleanerLock.Unlock()
}