Codebase list golang-github-go-kit-kit / 3752c99
Remove dependency on juju Nelz 6 years ago
2 changed file(s) with 0 addition(s) and 57 deletion(s). Raw diff Collapse all Expand all
22 import (
33 "context"
44 "errors"
5 "time"
6
7 "github.com/juju/ratelimit"
85
96 "github.com/go-kit/kit/endpoint"
107 )
129 // ErrLimited is returned in the request path when the rate limiter is
1310 // triggered and the request is rejected.
1411 var ErrLimited = errors.New("rate limit exceeded")
15
16 // NewTokenBucketLimiter returns an endpoint.Middleware that acts as a rate
17 // limiter based on a token-bucket algorithm. Requests that would exceed the
18 // maximum request rate are simply rejected with an error.
19 func NewTokenBucketLimiter(tb *ratelimit.Bucket) endpoint.Middleware {
20 return NewErroringLimiter(NewAllower(tb))
21 }
22
23 // NewTokenBucketThrottler returns an endpoint.Middleware that acts as a
24 // request throttler based on a token-bucket algorithm. Requests that would
25 // exceed the maximum request rate are delayed.
26 // The parameterized function "_" is kept for backwards-compatiblity of
27 // the API, but it is no longer used for anything. You may pass it nil.
28 func NewTokenBucketThrottler(tb *ratelimit.Bucket, _ func(time.Duration)) endpoint.Middleware {
29 return NewDelayingLimiter(NewWaiter(tb))
30 }
3112
3213 // Allower dictates whether or not a request is acceptable to run.
3314 // The Limiter from "golang.org/x/time/rate" already implements this interface,
8061 return f()
8162 }
8263
83 // NewAllower turns an existing ratelimit.Bucket into an API-compatible form
84 func NewAllower(tb *ratelimit.Bucket) Allower {
85 return AllowerFunc(func() bool {
86 return (tb.TakeAvailable(1) != 0)
87 })
88 }
89
9064 // WaiterFunc is an adapter that lets a function operate as if
9165 // it implements Waiter
9266 type WaiterFunc func(ctx context.Context) error
9569 func (f WaiterFunc) Wait(ctx context.Context) error {
9670 return f(ctx)
9771 }
98
99 // NewWaiter turns an existing ratelimit.Bucket into an API-compatible form
100 func NewWaiter(tb *ratelimit.Bucket) Waiter {
101 return WaiterFunc(func(ctx context.Context) error {
102 dur := tb.Take(1)
103 select {
104 case <-ctx.Done():
105 return ctx.Err()
106 case <-time.After(dur):
107 // happy path
108 }
109 return nil
110 })
111 }
55 "testing"
66 "time"
77
8 jujuratelimit "github.com/juju/ratelimit"
98 "golang.org/x/time/rate"
109
1110 "github.com/go-kit/kit/endpoint"
1312 )
1413
1514 var nopEndpoint = func(context.Context, interface{}) (interface{}, error) { return struct{}{}, nil }
16
17 func TestTokenBucketLimiter(t *testing.T) {
18 tb := jujuratelimit.NewBucket(time.Minute, 1)
19 testSuccessThenFailure(
20 t,
21 ratelimit.NewTokenBucketLimiter(tb)(nopEndpoint),
22 ratelimit.ErrLimited.Error())
23 }
24
25 func TestTokenBucketThrottler(t *testing.T) {
26 tb := jujuratelimit.NewBucket(time.Minute, 1)
27 testSuccessThenFailure(
28 t,
29 ratelimit.NewTokenBucketThrottler(tb, nil)(nopEndpoint),
30 "context deadline exceeded")
31 }
3215
3316 func TestXRateErroring(t *testing.T) {
3417 limit := rate.NewLimiter(rate.Every(time.Minute), 1)