forked from go-kit/kit
-
Notifications
You must be signed in to change notification settings - Fork 0
/
token_bucket.go
72 lines (61 loc) · 2.15 KB
/
token_bucket.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
package ratelimit
import (
"context"
"errors"
"github.com/go-kit/kit/endpoint"
)
// ErrLimited is returned in the request path when the rate limiter is
// triggered and the request is rejected.
var ErrLimited = errors.New("rate limit exceeded")
// Allower dictates whether or not a request is acceptable to run.
// The Limiter from "golang.org/x/time/rate" already implements this interface,
// one is able to use that in NewErroringLimiter without any modifications.
type Allower interface {
Allow() bool
}
// NewErroringLimiter returns an endpoint.Middleware that acts as a rate
// limiter. Requests that would exceed the
// maximum request rate are simply rejected with an error.
func NewErroringLimiter(limit Allower) endpoint.Middleware {
return func(next endpoint.Endpoint) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
if !limit.Allow() {
return nil, ErrLimited
}
return next(ctx, request)
}
}
}
// Waiter dictates how long a request must be delayed.
// The Limiter from "golang.org/x/time/rate" already implements this interface,
// one is able to use that in NewDelayingLimiter without any modifications.
type Waiter interface {
Wait(ctx context.Context) error
}
// NewDelayingLimiter returns an endpoint.Middleware that acts as a
// request throttler. Requests that would
// exceed the maximum request rate are delayed via the Waiter function
func NewDelayingLimiter(limit Waiter) endpoint.Middleware {
return func(next endpoint.Endpoint) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
if err := limit.Wait(ctx); err != nil {
return nil, err
}
return next(ctx, request)
}
}
}
// AllowerFunc is an adapter that lets a function operate as if
// it implements Allower
type AllowerFunc func() bool
// Allow makes the adapter implement Allower
func (f AllowerFunc) Allow() bool {
return f()
}
// WaiterFunc is an adapter that lets a function operate as if
// it implements Waiter
type WaiterFunc func(ctx context.Context) error
// Wait makes the adapter implement Waiter
func (f WaiterFunc) Wait(ctx context.Context) error {
return f(ctx)
}