From 4edffe94f3e5041ce67c01fddb713530564665c6 Mon Sep 17 00:00:00 2001 From: surdeus Date: Fri, 31 May 2024 15:39:34 +0500 Subject: [PATCH] feat: added limitting to the request rate. --- amocrm.go | 1 + api/api.go | 48 +++++++++++++++++++++++++++++++++++++++++++ api/request.go | 4 ++++ cmd/amocli/getlead.go | 2 +- 4 files changed, 54 insertions(+), 1 deletion(-) diff --git a/amocrm.go b/amocrm.go index e081944..a6bcf2d 100644 --- a/amocrm.go +++ b/amocrm.go @@ -26,3 +26,4 @@ func NewClient(secretPath string) (*Client, error) { }, nil } + diff --git a/api/api.go b/api/api.go index 905ba81..3ed30e7 100644 --- a/api/api.go +++ b/api/api.go @@ -11,6 +11,7 @@ const ( DefaultContentType = "application/json" DefaultAccept = DefaultContentType DefaultCacheControl = "no-cache" + MaxEntitiesPerRequest = 250 ) type ClientOptions struct { @@ -34,6 +35,14 @@ type Client struct { BaseURL *url.URL secretStoreFilePath string Debug bool + + availableRequests int + mrps int + + ticker *time.Ticker + req chan struct{} + + requestsMade int64 } type OAuthTokenResponse struct { @@ -112,3 +121,42 @@ func NewAPI(secretPath string) (*Client, error) { return client, nil } +// Set maximum requests per second. +func (client *Client) SetMRPS(rps int) *Client { + client.mrps = rps + client.req = make(chan struct{}) + client.ticker = time.NewTicker(time.Second) + go func() { + for { + for _ = range make( + []struct{}, + client.mrps - client.availableRequests, + ) { + client.req <- struct{}{} + } + client.availableRequests = client.mrps + <-client.ticker.C + } + }() + return client +} + +func (client *Client) waitInQueue() bool { + // Just leaving if MRPS is not set. + if client.mrps == 0 { + return false + } + + <- client.req + client.availableRequests-- + + return true +} + +func (client *Client) finishRequest() { +} + +func (client *Client) RequestsMade() int64 { + return client.requestsMade +} + diff --git a/api/request.go b/api/request.go index f17096f..4f65c0b 100644 --- a/api/request.go +++ b/api/request.go @@ -22,6 +22,7 @@ func (client *Client) doRawRequest( var ( err error ) + client.requestsMade++ reqBody := new(bytes.Buffer) if params.Body != nil { @@ -113,6 +114,9 @@ func (client *Client) doRequest( err error parsedURL *url.URL ) + if client.waitInQueue() { + defer client.finishRequest() + } parsedURL, err = url.Parse(u) if err != nil { diff --git a/cmd/amocli/getlead.go b/cmd/amocli/getlead.go index 7507263..0aba4c8 100644 --- a/cmd/amocli/getlead.go +++ b/cmd/amocli/getlead.go @@ -7,7 +7,6 @@ import "encoding/json" import "strconv" import "log" import "fmt" -//import "os" var getLead = mtool.T("get-leads").Func(func(flags *mtool.Flags){ var ( @@ -36,6 +35,7 @@ var getLead = mtool.T("get-leads").Func(func(flags *mtool.Flags){ if err != nil { log.Fatalf("NewAmoClient(...): %s\n", err) } + c.API.SetMRPS(8) leads, err := c.GetLeads( urlenc.Array[int]{