| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 | package taskimport (	"sync"	"time")// Periodic is a task that runs periodically.type Periodic struct {	// Interval of the task being run	Interval time.Duration	// Execute is the task function	Execute func() error	access  sync.Mutex	timer   *time.Timer	running bool}func (t *Periodic) hasClosed() bool {	t.access.Lock()	defer t.access.Unlock()	return !t.running}func (t *Periodic) checkedExecute() error {	if t.hasClosed() {		return nil	}	if err := t.Execute(); err != nil {		t.access.Lock()		t.running = false		t.access.Unlock()		return err	}	t.access.Lock()	defer t.access.Unlock()	if !t.running {		return nil	}	t.timer = time.AfterFunc(t.Interval, func() {		t.checkedExecute() // nolint: errcheck	})	return nil}// Start implements common.Runnable.func (t *Periodic) Start() error {	t.access.Lock()	if t.running {		return nil	}	t.running = true	t.access.Unlock()	if err := t.checkedExecute(); err != nil {		t.access.Lock()		t.running = false		t.access.Unlock()		return err	}	return nil}// Close implements common.Closable.func (t *Periodic) Close() error {	t.access.Lock()	defer t.access.Unlock()	t.running = false	if t.timer != nil {		t.timer.Stop()		t.timer = nil	}	return nil}
 |