@@ -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
1618const (
1719 defaultUserAgent = "sp-yduck/proxmox-go"
20+ defaultQPS = 20
1821)
1922
2023type 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
2937type TicketRequest struct {
@@ -41,8 +49,9 @@ type ClientOption func(*RESTClient)
4149
4250func 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+
101120func (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
0 commit comments