package janitor import ( "context" "sync" "time" ) // Janitor for collecting expired items and cleaning them. type Janitor struct { ctx context.Context interval time.Duration done chan struct{} once sync.Once } func NewJanitor(ctx context.Context, interval time.Duration) *Janitor { j := &Janitor{ ctx: ctx, interval: interval, done: make(chan struct{}), } return j } // stop to stop the janitor. func (j *Janitor) stop() { j.once.Do(func() { close(j.done) }) } // Run with the given cleanup callback function. func (j *Janitor) Run(fn func()) { go func() { ticker := time.NewTicker(j.interval) defer ticker.Stop() for { select { case <-ticker.C: fn() case <-j.done: fn() // last call return case <-j.ctx.Done(): j.stop() } } }() }