Resetting a ticker in Go
Raft is the distributed consensus algorithm that I’m using for the database I’m building at the Recurse Center. The algorithm has two timeouts — a heartbeat timeout and an election timeout. When a server receives a heartbeat from the leader, it resets its election timeout. If it doesn’t receive a heartbeat before its election timeout runs out, it tries to elect itself as leader!
As a first step towards this, I need to write code that resets a timeout (say 2 seconds) every time another timeout (say 5 seconds) expires. I would expect to see output that looked like:
Elapsed: 0
Elapsed: 2 Ticker A
Elapsed: 4 Ticker A
Elapsed: 5 Ticker B - Going to reset Ticker A!
Elapsed: 7 Ticker A
Elapsed: 9 Ticker A
If I hadn’t reset the other ticker, of course, I would expect to see:
Elapsed: 0
Elapsed: 2 Ticker A
Elapsed: 4 Ticker A
Elapsed: 5 Ticker B
Elapsed: 6 Ticker A
Elapsed: 8 Ticker A
Here’s how I wrote this in Go, using ticking channels. I set up a goroutine that listens on two channels, tickerA and tickerB. Every time tickerB goes off, it resets tickerA.
type server struct {
doneChan chan bool
tickerA ticker
tickerB ticker
}func (s *server) listener() {
start := time.Now()
for {
select {
case <-s.tickerA.ticker.C:
elapsed := time.Since(start)
fmt.Println("Elapsed: ", elapsed, " Ticker A")
case <-s.tickerB.ticker.C:
s.tickerA.resetTicker()
elapsed := time.Since(start)
fmt.Println("Elapsed: ", elapsed, " Ticker B - Going to reset ticker A")
}
}
s.doneChan <- true
}func main() {
doneChan := make(chan bool)
tickerA := createTicker(2 * time.Second)
tickerB := createTicker(5 * time.Second)
s := &server{doneChan, *tickerA, *tickerB}
go s.listener()
<-doneChan
}
And my tickers and the methods to create and reset them look like:
type ticker struct {
period time.Duration
ticker time.Ticker
}func createTicker(period time.Duration) *ticker {
return &ticker{period, *time.NewTicker(period)}
}func (t *ticker) resetTicker() {
t.ticker = *time.NewTicker(t.period)
}
The actual output is:
$ go run tick.goElapsed: 2.00074535s Ticker AElapsed: 4.002086857s Ticker AElapsed: 5.004973744s Ticker B - Going to reset ticker AElapsed: 7.008515813s Ticker AElapsed: 9.009572001s Ticker A
That’s about it! Check it out!
Have a better way to do this? Just want to say hi? I’m on Twitter!