Skip to content

Instantly share code, notes, and snippets.

@shatil
Last active July 23, 2019 07:29
Show Gist options
  • Save shatil/0ca9fd3cf93827c65ba6378324f72c75 to your computer and use it in GitHub Desktop.
Save shatil/0ca9fd3cf93827c65ba6378324f72c75 to your computer and use it in GitHub Desktop.
time.Tick with burst capability
package main
import "time"
// TickBurst creates a time.Tick()-like throttle with an initial burst.
//
// The created channel is replenished using time.Tick() every given interval,
// making it useful to limit concurrency. You can have an initial burst of 10
// requests, for example, and permit one additional request every millisecond.
//
// See time.Tick() for caveats (like GC can't touch this, for example).
func TickBurst(interval time.Duration, size int) <-chan time.Time {
c := make(chan time.Time, size)
for i := 0; i < size; i++ {
c <- time.Now()
}
go func() {
t := time.Tick(interval)
for {
c <- <-t
}
}()
return c
}
package main
import (
"testing"
"time"
)
// TestTickBurst ensures correctness of burst and ticks.
func TestTickBurst(t *testing.T) {
interval := 100 * time.Microsecond // Large enough for race conditions?
size := 4 // Burst size; also useful for slice size.
ticker := TickBurst(interval, size)
ticks := []time.Time{}
for i := 0; i < size+1; i++ {
ticks = append(ticks, <-ticker)
}
// Test burst elements.
for j := 1; j < size; j++ {
if diff := ticks[j].Sub(ticks[j-1]); diff > interval {
t.Errorf("expected %q to be smaller interval than %q", diff, interval)
}
}
// Test tick _after_ burst.
if diff := ticks[size].Sub(ticks[size-1]); diff < interval {
t.Errorf("expected %q to be greater than interval %q", diff, interval)
}
}
@shatil
Copy link
Author

shatil commented Jul 23, 2019

Please run go mod init if you encounter:

$ go test
go: cannot find main module; see 'go help modules'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment