Skip to content

Commit 7fc1a08

Browse files
committed
support rate limit
1 parent 157926a commit 7fc1a08

File tree

4 files changed

+46
-4
lines changed

4 files changed

+46
-4
lines changed

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ require (
66
github.com/gorilla/websocket v1.5.0
77
github.com/pkg/errors v0.9.1
88
github.com/stretchr/testify v1.8.4
9+
golang.org/x/time v0.3.0
910
)
1011

1112
require (

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
88
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
99
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
1010
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
11+
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
12+
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
1113
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
1214
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
1315
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

rest/client.go

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,28 @@ import (
1010
"strings"
1111
"time"
1212

13+
"golang.org/x/time/rate"
14+
1315
"github.com/sp-yduck/proxmox-go/api"
1416
)
1517

1618
const (
1719
defaultUserAgent = "sp-yduck/proxmox-go"
20+
defaultQPS = 20
1821
)
1922

2023
type RESTClient struct {
21-
endpoint string
22-
httpClient *http.Client
24+
// proxmox rest api endpoint
25+
endpoint string
26+
27+
httpClient *http.Client
28+
2329
tokenid string
2430
token string
2531
session *api.Session
2632
credentials *TicketRequest
33+
34+
rateLimiter *rate.Limiter
2735
}
2836

2937
type TicketRequest struct {
@@ -41,8 +49,9 @@ type ClientOption func(*RESTClient)
4149

4250
func NewRESTClient(baseUrl string, opts ...ClientOption) (*RESTClient, error) {
4351
client := &RESTClient{
44-
endpoint: complementURL(baseUrl),
45-
httpClient: &http.Client{},
52+
endpoint: complementURL(baseUrl),
53+
httpClient: &http.Client{},
54+
rateLimiter: rate.NewLimiter(rate.Every(1*time.Second), defaultQPS),
4655
}
4756

4857
for _, option := range opts {
@@ -98,6 +107,16 @@ func WithAPIToken(tokenid, secret string) ClientOption {
98107
}
99108
}
100109

110+
func WithQPS(qps int) ClientOption {
111+
return func(c *RESTClient) {
112+
c.rateLimiter = rate.NewLimiter(rate.Every(1*time.Second), qps)
113+
}
114+
}
115+
116+
func (c *RESTClient) SetMaxQPS(qps int) {
117+
c.rateLimiter = rate.NewLimiter(rate.Every(1*time.Second), qps)
118+
}
119+
101120
func (c *RESTClient) Do(ctx context.Context, httpMethod, urlPath string, req, v interface{}) error {
102121
endpoint := c.endpoint + urlPath
103122

@@ -117,6 +136,9 @@ func (c *RESTClient) Do(ctx context.Context, httpMethod, urlPath string, req, v
117136
httpReq.Header = c.makeAuthHeaders()
118137
httpReq.Header.Add("Content-Type", "application/json")
119138

139+
if err := c.rateLimiter.Wait(ctx); err != nil {
140+
return err
141+
}
120142
httpRsp, err := c.httpClient.Do(httpReq)
121143
if err != nil {
122144
return err

rest/client_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package rest
2+
3+
import (
4+
"context"
5+
"fmt"
6+
)
7+
8+
func (s *TestSuite) TestRateLimit() {
9+
s.restclient.SetMaxQPS(10)
10+
for i := 0; i < 13; i++ {
11+
_, err := s.restclient.GetVersion(context.TODO())
12+
if err != nil {
13+
s.T().Errorf("failed to ger version: %v", err)
14+
}
15+
fmt.Println(i)
16+
}
17+
}

0 commit comments

Comments
 (0)