Skip to content

Commit

Permalink
Simplify ticker.Stop(). Leverage ctx.cancel()
Browse files Browse the repository at this point in the history
  • Loading branch information
swift1337 committed Oct 3, 2024
1 parent 3f8f989 commit f5a4701
Showing 1 changed file with 15 additions and 10 deletions.
25 changes: 15 additions & 10 deletions pkg/ticker/ticker.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,18 @@ type Task func(ctx context.Context, t *Ticker) error
// Ticker represents a ticker that will run a function periodically.
// It also invokes BEFORE ticker starts.
type Ticker struct {
interval time.Duration
ticker *time.Ticker
task Task
internalStopChan chan struct{}
interval time.Duration
ticker *time.Ticker
task Task

// runnerMu is a mutex to prevent double run
runnerMu sync.Mutex

// stateMu is a mutex to prevent concurrent SetInterval calls
stateMu sync.Mutex

stopped bool
stopped bool
ctxCancel context.CancelFunc

externalStopChan <-chan struct{}
logger zerolog.Logger
Expand Down Expand Up @@ -120,8 +120,8 @@ func (t *Ticker) Run(ctx context.Context) (err error) {
defer t.runnerMu.Unlock()

// setup
ctx, t.ctxCancel = context.WithCancel(ctx)
t.ticker = time.NewTicker(t.interval)
t.internalStopChan = make(chan struct{})
t.stopped = false

// initial run
Expand All @@ -133,16 +133,21 @@ func (t *Ticker) Run(ctx context.Context) (err error) {
for {
select {
case <-ctx.Done():
// if task is finished (i.e. last tick completed BEFORE ticker.Stop(),
// then we need to return nil)
if t.stopped {
return nil
}
return ctx.Err()
case <-t.ticker.C:
// If another goroutine calls ticker.Stop() while the current tick is running,
// Then it's okay to return ctx error
if err := t.task(ctx, t); err != nil {
return fmt.Errorf("ticker task failed: %w", err)
}
case <-t.externalStopChan:
t.Stop()
return nil
case <-t.internalStopChan:
return nil
}
}
}
Expand All @@ -167,11 +172,11 @@ func (t *Ticker) Stop() {
defer t.stateMu.Unlock()

// noop
if t.stopped || t.internalStopChan == nil {
if t.stopped {
return
}

close(t.internalStopChan)
t.ctxCancel()
t.stopped = true
t.ticker.Stop()

Expand Down

0 comments on commit f5a4701

Please sign in to comment.