Documentation
¶
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type FixedWindow ¶
FixedWindow acts as a counter for a given time period.
Example ¶
package main import ( "fmt" "log" "os" "text/tabwriter" "time" "github.com/sneakycursor/core/sync/ratelimit" ) func main() { now := time.Now() rl := ratelimit.NewFixedWindow(5, time.Second) w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', tabwriter.AlignRight|tabwriter.Debug) fmt.Fprintf(w, "%s\t%s\t\n", "t", "allow") call := func(duration time.Duration, allow bool) { rl.Now = func() time.Time { return now.Add(duration) } allowed := rl.Allow() if allow != allowed { log.Fatalf("unexpected allow at %v", duration) } fmt.Fprintf(w, "%s\t%t\t\n", duration, allowed) } call(0, true) call(1*time.Millisecond, true) call(2*time.Millisecond, true) call(3*time.Millisecond, true) call(4*time.Millisecond, true) call(99*time.Millisecond, false) call(100*time.Millisecond, false) call(101*time.Millisecond, false) call(999*time.Millisecond, false) call(1000*time.Millisecond, true) call(1100*time.Millisecond, true) call(1200*time.Millisecond, true) call(1300*time.Millisecond, true) call(1400*time.Millisecond, true) call(1500*time.Millisecond, false) call(1999*time.Millisecond, false) fmt.Println("fixed window") w.Flush() }
Output: fixed window t| allow| 0s| true| 1ms| true| 2ms| true| 3ms| true| 4ms| true| 99ms| false| 100ms| false| 101ms| false| 999ms| false| 1s| true| 1.1s| true| 1.2s| true| 1.3s| true| 1.4s| true| 1.5s| false| 1.999s| false|
func NewFixedWindow ¶
func NewFixedWindow(limit int, period time.Duration) *FixedWindow
func (*FixedWindow) Allow ¶
func (r *FixedWindow) Allow() bool
Allow checks if a request is allowed. Special case of AllowN that consumes only 1 token.
func (*FixedWindow) AllowN ¶
func (r *FixedWindow) AllowN(n int) bool
AllowN checks if a request is allowed. Consumes n token if allowed.
func (*FixedWindow) Remaining ¶
func (r *FixedWindow) Remaining() int
func (*FixedWindow) RetryAt ¶
func (r *FixedWindow) RetryAt() time.Time
type GCRA ¶
Example ¶
package main import ( "fmt" "log" "os" "text/tabwriter" "time" "github.com/sneakycursor/core/sync/ratelimit" ) func main() { // We need to truncate the time to the nearest second, as the sliding window // is based on the window. now := time.Now().Truncate(time.Second) rl := ratelimit.NewGCRA(5, time.Second, 1) w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', tabwriter.AlignRight|tabwriter.Debug) fmt.Fprintf(w, "%s\t%s\t\n", "t", "allow") call := func(duration time.Duration, allow bool) { rl.Now = func() time.Time { return now.Add(duration) } allowed := rl.Allow() if allow != allowed { log.Fatalf("unexpected allow at %v", duration) } fmt.Fprintf(w, "%s\t%t\t\n", duration, allowed) } call(0, true) call(1*time.Millisecond, true) call(2*time.Millisecond, false) call(3*time.Millisecond, false) call(4*time.Millisecond, false) call(99*time.Millisecond, false) call(100*time.Millisecond, false) call(101*time.Millisecond, false) call(999*time.Millisecond, true) call(1000*time.Millisecond, true) call(1100*time.Millisecond, false) call(1200*time.Millisecond, true) call(1300*time.Millisecond, false) call(1400*time.Millisecond, true) call(1500*time.Millisecond, false) call(1999*time.Millisecond, true) fmt.Println("gcra") w.Flush() }
Output: gcra t| allow| 0s| true| 1ms| true| 2ms| false| 3ms| false| 4ms| false| 99ms| false| 100ms| false| 101ms| false| 999ms| true| 1s| true| 1.1s| false| 1.2s| true| 1.3s| false| 1.4s| true| 1.5s| false| 1.999s| true|
type MultiFixedWindow ¶
MultiFixedWindow acts as a counter for a given time period.
Example ¶
package main import ( "fmt" "log" "os" "text/tabwriter" "time" "github.com/sneakycursor/core/sync/ratelimit" ) func main() { now := time.Now() rl := ratelimit.NewMultiFixedWindow(5, time.Second) w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', tabwriter.AlignRight|tabwriter.Debug) fmt.Fprintf(w, "%s\t%s\t\n", "t", "allow") call := func(duration time.Duration, allow bool) { rl.Now = func() time.Time { return now.Add(duration) } allowed := rl.Allow("key") if allow != allowed { log.Fatalf("unexpected allow at %v", duration) } fmt.Fprintf(w, "%s\t%t\t\n", duration, allowed) } call(0, true) call(1*time.Millisecond, true) call(2*time.Millisecond, true) call(3*time.Millisecond, true) call(4*time.Millisecond, true) call(99*time.Millisecond, false) call(100*time.Millisecond, false) call(101*time.Millisecond, false) call(999*time.Millisecond, false) call(1000*time.Millisecond, true) call(1100*time.Millisecond, true) call(1200*time.Millisecond, true) call(1300*time.Millisecond, true) call(1400*time.Millisecond, true) call(1500*time.Millisecond, false) call(1999*time.Millisecond, false) fmt.Println("multi fixed window") w.Flush() }
Output: multi fixed window t| allow| 0s| true| 1ms| true| 2ms| true| 3ms| true| 4ms| true| 99ms| false| 100ms| false| 101ms| false| 999ms| false| 1s| true| 1.1s| true| 1.2s| true| 1.3s| true| 1.4s| true| 1.5s| false| 1.999s| false|
func NewMultiFixedWindow ¶
func NewMultiFixedWindow(limit int, period time.Duration) *MultiFixedWindow
func (*MultiFixedWindow) Allow ¶
func (r *MultiFixedWindow) Allow(key string) bool
Allow checks if a request is allowed. Special case of AllowN that consumes only 1 token.
func (*MultiFixedWindow) AllowN ¶
func (r *MultiFixedWindow) AllowN(key string, n int) bool
AllowN checks if a request is allowed. Consumes n token if allowed.
func (*MultiFixedWindow) Clear ¶
func (r *MultiFixedWindow) Clear()
func (*MultiFixedWindow) Remaining ¶
func (r *MultiFixedWindow) Remaining(key string) int
func (*MultiFixedWindow) Size ¶
func (r *MultiFixedWindow) Size() int
type MultiGCRA ¶
Example ¶
package main import ( "fmt" "log" "os" "text/tabwriter" "time" "github.com/sneakycursor/core/sync/ratelimit" ) func main() { // We need to truncate the time to the nearest second, as the sliding window // is based on the window. now := time.Now().Truncate(time.Second) rl := ratelimit.NewMultiGCRA(5, time.Second, 1) w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', tabwriter.AlignRight|tabwriter.Debug) fmt.Fprintf(w, "%s\t%s\t\n", "t", "allow") call := func(duration time.Duration, allow bool) { rl.Now = func() time.Time { return now.Add(duration) } allowed := rl.Allow("key") if allow != allowed { log.Fatalf("unexpected allow at %v", duration) } fmt.Fprintf(w, "%s\t%t\t\n", duration, allowed) } call(0, true) call(1*time.Millisecond, true) call(2*time.Millisecond, false) call(3*time.Millisecond, false) call(4*time.Millisecond, false) call(99*time.Millisecond, false) call(100*time.Millisecond, false) call(101*time.Millisecond, false) call(999*time.Millisecond, true) call(1000*time.Millisecond, true) call(1100*time.Millisecond, false) call(1200*time.Millisecond, true) call(1300*time.Millisecond, false) call(1400*time.Millisecond, true) call(1500*time.Millisecond, false) call(1999*time.Millisecond, true) fmt.Println("multi gcra") w.Flush() }
Output: multi gcra t| allow| 0s| true| 1ms| true| 2ms| false| 3ms| false| 4ms| false| 99ms| false| 100ms| false| 101ms| false| 999ms| true| 1s| true| 1.1s| false| 1.2s| true| 1.3s| false| 1.4s| true| 1.5s| false| 1.999s| true|
type MultiSlidingWindow ¶
Example ¶
package main import ( "fmt" "log" "os" "text/tabwriter" "time" "github.com/sneakycursor/core/sync/ratelimit" ) func main() { now := time.Now() rl := ratelimit.NewMultiSlidingWindow(5, time.Second) w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', tabwriter.AlignRight|tabwriter.Debug) fmt.Fprintf(w, "%s\t%s\t\n", "t", "allow") call := func(duration time.Duration, allow bool) { rl.Now = func() time.Time { return now.Add(duration) } allowed := rl.Allow("key") if allow != allowed { log.Fatalf("unexpected allow at %v", duration) } fmt.Fprintf(w, "%s\t%t\t\n", duration, allowed) } call(0, true) call(1*time.Millisecond, true) call(2*time.Millisecond, true) call(3*time.Millisecond, true) call(4*time.Millisecond, true) call(99*time.Millisecond, false) call(100*time.Millisecond, false) call(101*time.Millisecond, false) call(999*time.Millisecond, false) call(1000*time.Millisecond, false) call(1100*time.Millisecond, false) call(1200*time.Millisecond, true) call(1300*time.Millisecond, false) call(1400*time.Millisecond, true) call(1500*time.Millisecond, false) call(1999*time.Millisecond, true) fmt.Println("multi sliding window") w.Flush() }
Output: multi sliding window t| allow| 0s| true| 1ms| true| 2ms| true| 3ms| true| 4ms| true| 99ms| false| 100ms| false| 101ms| false| 999ms| false| 1s| false| 1.1s| false| 1.2s| true| 1.3s| false| 1.4s| true| 1.5s| false| 1.999s| true|
func NewMultiSlidingWindow ¶
func NewMultiSlidingWindow(limit int, period time.Duration) *MultiSlidingWindow
func (*MultiSlidingWindow) Allow ¶
func (r *MultiSlidingWindow) Allow(key string) bool
func (*MultiSlidingWindow) Clear ¶
func (r *MultiSlidingWindow) Clear()
func (*MultiSlidingWindow) Remaining ¶
func (r *MultiSlidingWindow) Remaining(key string) int
func (*MultiSlidingWindow) Size ¶
func (r *MultiSlidingWindow) Size() int
type RateLimiter ¶
type RateLimiter struct {
// contains filtered or unexported fields
}
func New ¶
func New(rls ...ratelimiter) *RateLimiter
func (*RateLimiter) Allow ¶
func (r *RateLimiter) Allow() bool
func (*RateLimiter) AllowN ¶
func (r *RateLimiter) AllowN(n int) bool
type SlidingWindow ¶
Example ¶
package main import ( "fmt" "log" "os" "text/tabwriter" "time" "github.com/sneakycursor/core/sync/ratelimit" ) func main() { // We need to truncate the time to the nearest second, as the sliding window // is based on the window. now := time.Now() rl := ratelimit.NewSlidingWindow(5, time.Second) w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', tabwriter.AlignRight|tabwriter.Debug) fmt.Fprintf(w, "%s\t%s\t\n", "t", "allow") call := func(duration time.Duration, allow bool) { rl.Now = func() time.Time { return now.Add(duration) } allowed := rl.Allow() if allow != allowed { log.Fatalf("unexpected allow at %v", duration) } fmt.Fprintf(w, "%s\t%t\t\n", duration, allowed) } call(0, true) call(1*time.Millisecond, true) call(2*time.Millisecond, true) call(3*time.Millisecond, true) call(4*time.Millisecond, true) call(99*time.Millisecond, false) call(100*time.Millisecond, false) call(101*time.Millisecond, false) call(999*time.Millisecond, false) call(1000*time.Millisecond, false) call(1100*time.Millisecond, false) call(1200*time.Millisecond, true) call(1300*time.Millisecond, false) call(1400*time.Millisecond, true) call(1500*time.Millisecond, false) call(1999*time.Millisecond, true) fmt.Println("sliding window") w.Flush() }
Output: sliding window t| allow| 0s| true| 1ms| true| 2ms| true| 3ms| true| 4ms| true| 99ms| false| 100ms| false| 101ms| false| 999ms| false| 1s| false| 1.1s| false| 1.2s| true| 1.3s| false| 1.4s| true| 1.5s| false| 1.999s| true|
func NewSlidingWindow ¶
func NewSlidingWindow(limit int, period time.Duration) *SlidingWindow
func (*SlidingWindow) Allow ¶
func (r *SlidingWindow) Allow() bool
func (*SlidingWindow) AllowN ¶
func (r *SlidingWindow) AllowN(n int) bool
func (*SlidingWindow) Remaining ¶
func (r *SlidingWindow) Remaining() int
Click to show internal directories.
Click to hide internal directories.