Documentation
¶
Index ¶
- type Interval
- type Ticker
- func (t *Ticker) Start() error
- func (t *Ticker) Stop()
- func (t *Ticker) WithContext(ctx context.Context) *Ticker
- func (t *Ticker) WithFunc(f func()) *Ticker
- func (t *Ticker) WithJitter(fraction float64) *Ticker
- func (t *Ticker) WithMaxDuration(d time.Duration) *Ticker
- func (t *Ticker) WithMaxInterval(d time.Duration) *Ticker
- func (t *Ticker) WithMinInterval(d time.Duration) *Ticker
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Interval ¶ added in v1.1.0
type Interval interface { // The [*Ticker.Start] method will call Next to determine how long to wait // until firing the next ticker. Next() time.Duration }
Interval provides the interval that the next ticker should fire after.
type Ticker ¶
Ticker holds a channel that delivers `ticks` of a clock at intervals (just like the standard library time.Ticker).
func NewConstant ¶
NewConstant returns a constant ticker, functionally equivalent to the standard library time.Ticker.
Example ¶
package main import ( "fmt" "time" "github.com/tkennon/ticker" ) func runFiveTimes(t *ticker.Ticker) bool { for i := 0; i < 5; i++ { then := time.Now() now, ok := <-t.C if !ok { return false } fmt.Println(now.Sub(then).Round(time.Millisecond)) } return true } func main() { con := ticker.NewConstant(time.Millisecond) if err := con.Start(); err != nil { panic(err) } defer con.Stop() if ok := runFiveTimes(con); !ok { panic("ticker stopped unexpectedly") } }
Output: 1ms 1ms 1ms 1ms 1ms
func NewExponential ¶
NewExponential returns an exponential backoff ticker.
Example ¶
package main import ( "fmt" "time" "github.com/tkennon/ticker" ) func runFiveTimes(t *ticker.Ticker) bool { for i := 0; i < 5; i++ { then := time.Now() now, ok := <-t.C if !ok { return false } fmt.Println(now.Sub(then).Round(time.Millisecond)) } return true } func main() { exp := ticker.NewExponential(time.Millisecond, 2.0) if err := exp.Start(); err != nil { panic(err) } defer exp.Stop() if ok := runFiveTimes(exp); !ok { panic("ticker stopped unexpectedly") } }
Output: 1ms 2ms 4ms 8ms 16ms
func NewLinear ¶
NewLinear returns a linear backoff ticker.
Example ¶
package main import ( "fmt" "time" "github.com/tkennon/ticker" ) func runFiveTimes(t *ticker.Ticker) bool { for i := 0; i < 5; i++ { then := time.Now() now, ok := <-t.C if !ok { return false } fmt.Println(now.Sub(then).Round(time.Millisecond)) } return true } func main() { lin := ticker.NewLinear(time.Millisecond, time.Millisecond) if err := lin.Start(); err != nil { panic(err) } defer lin.Stop() if ok := runFiveTimes(lin); !ok { panic("ticker stopped unexpectedly") } }
Output: 1ms 2ms 3ms 4ms 5ms
func NewTicker ¶ added in v1.1.0
NewTicker creates a new generic ticker with the given interval. This package provides NewConstant, NewLinear, and NewExponential as convenience initialisers for constant, linear, and exponential backoff tickers, but NewTicker allows the caller to specify any custom interval.
func (*Ticker) Start ¶
Start starts the ticker. The ticker's channel will send the current time after an interval has elapsed. Start returns an error if the ticker could not be started due to restrictions imposed in the ticker config (e.g. minimum allowed interval is greater than the maximum allowed interval). The ticker's channel will fire at different intervals determined by the type of ticker (e.g. constant, linear, or exponential) and by the ticker modifiers (WithJitter, WithMaximum etc). The ticker must be stopped (either explicitly via Stop, or through a context expiring or a maximum duration being reached) to release all associated resources. The ticker's channel will be closed when the ticker is stopped . As such, callers must always check the ticker's channel is still open when receiving "ticks". The ticker will not fire again until its channel has been read.
Note that once started, tickers must not be modified (through the WithXxx modifiers).
func (*Ticker) Stop ¶
func (t *Ticker) Stop()
Stop turns off a ticker. Unlike the standard library, Stop does close the ticker's channel. As such, callers must always check the ticker's channel is still open when receiving "ticks". The ticker may continue to return valid ticks for a brief period after Stop is called.
Once stopped, a ticker will panic if (re)started. Stop will panic if called more than once. It is safe to stop a ticker via different methods (e.g. calling Stop explicitly, canceling a context, or capping the total maximum duration the ticker has ticked for).
Example ¶
package main import ( "fmt" "time" "github.com/tkennon/ticker" ) func main() { con := ticker.NewConstant(time.Millisecond) con.Stop() if err := con.Start(); err != nil { panic(err) } now, ok := <-con.C fmt.Println("ticker ok:", ok) fmt.Println("ticker time is zero:", now.IsZero()) }
Output: ticker ok: false ticker time is zero: true
func (*Ticker) WithContext ¶
WithContext adds a context.Context to the ticker. If the context expires then the ticker's channel will be closed.
Example ¶
package main import ( "context" "fmt" "time" "github.com/tkennon/ticker" ) func main() { ctx, cancel := context.WithCancel(context.Background()) con := ticker.NewConstant(time.Millisecond).WithContext(ctx) then := time.Now() if err := con.Start(); err != nil { panic(err) } now, ok := <-con.C fmt.Println("ticker ok:", ok) fmt.Println(now.Sub(then).Round(time.Millisecond)) cancel() now, ok = <-con.C fmt.Println("ticker ok:", ok) fmt.Println("ticker time is zero:", now.IsZero()) }
Output: ticker ok: true 1ms ticker ok: false ticker time is zero: true
func (*Ticker) WithFunc ¶
WithFunc will execute f in its own goroutine each time the ticker fires. The ticker must be stopped to prevent running f.
Example ¶
package main import ( "fmt" "time" "github.com/tkennon/ticker" ) func runFiveTimes(t *ticker.Ticker) bool { for i := 0; i < 5; i++ { then := time.Now() now, ok := <-t.C if !ok { return false } fmt.Println(now.Sub(then).Round(time.Millisecond)) } return true } func main() { str := make(chan string) con := ticker.NewConstant(time.Millisecond).WithFunc(func() { str <- "hello" }) if err := con.Start(); err != nil { panic(err) } if ok := runFiveTimes(con); !ok { panic("ticker stopped unexpectedly") } for i := 0; i < 5; i++ { fmt.Println(<-str) } }
Output: 1ms 1ms 1ms 1ms 1ms hello hello hello hello hello
func (*Ticker) WithJitter ¶
WithJitter adds a uniformly random jitter to the time the ticker next fires. The jitter will be within `fraction` of the next interval. For example, WithJitter(0.1) applies a 10% jitter, so a linear ticker that would otherwise fire after 1, 2, 3, 4, ... seconds would now fire between 0.9-1.1 seconds on the first tick, and 1.8-2.2 seconds on the second tick, and so forth. The jitter fraction may be greater than one, allowing the possiblity for jittered tickers to fire immediately if the calculated interval with the jitter is less than zero. Note that jitter is symmetric; a negative `fraction` is treated the same as the corresponding positive value.
func (*Ticker) WithMaxDuration ¶
WithMaxDuration sets the maxiumum total duration over all ticks that the ticker will run for. Once the maximum duration is reached, the ticker's channel will be closed.
Example ¶
package main import ( "fmt" "time" "github.com/tkennon/ticker" ) func runFiveTimes(t *ticker.Ticker) bool { for i := 0; i < 5; i++ { then := time.Now() now, ok := <-t.C if !ok { return false } fmt.Println(now.Sub(then).Round(time.Millisecond)) } return true } func main() { exp := ticker.NewExponential(time.Millisecond, 2.0).WithMaxDuration(10 * time.Millisecond) if err := exp.Start(); err != nil { panic(err) } ok := runFiveTimes(exp) fmt.Println("ticker channel closed:", !ok) }
Output: 1ms 2ms 4ms ticker channel closed: true
func (*Ticker) WithMaxInterval ¶
WithMaxInterval sets the maximum interval between times the ticker fires. This is applied after jitter is applied.
Example ¶
package main import ( "fmt" "time" "github.com/tkennon/ticker" ) func runFiveTimes(t *ticker.Ticker) bool { for i := 0; i < 5; i++ { then := time.Now() now, ok := <-t.C if !ok { return false } fmt.Println(now.Sub(then).Round(time.Millisecond)) } return true } func main() { lin := ticker.NewLinear(time.Millisecond, time.Millisecond).WithMaxInterval(3 * time.Millisecond) if err := lin.Start(); err != nil { panic(err) } defer lin.Stop() if ok := runFiveTimes(lin); !ok { panic("ticker stopped unexpectedly") } }
Output: 1ms 2ms 3ms 3ms 3ms
func (*Ticker) WithMinInterval ¶
WithMinInterval sets the minimum interval between times the ticker fires. This is applied after jitter is applied.
Example ¶
package main import ( "fmt" "time" "github.com/tkennon/ticker" ) func runFiveTimes(t *ticker.Ticker) bool { for i := 0; i < 5; i++ { then := time.Now() now, ok := <-t.C if !ok { return false } fmt.Println(now.Sub(then).Round(time.Millisecond)) } return true } func main() { lin := ticker.NewLinear(5*time.Millisecond, -time.Millisecond).WithMinInterval(3 * time.Millisecond) if err := lin.Start(); err != nil { panic(err) } defer lin.Stop() if ok := runFiveTimes(lin); !ok { panic("ticker stopped unexpectedly") } }
Output: 5ms 4ms 3ms 3ms 3ms