- Fix bandwidth limit error

- Add cooldowns for fair usage limit bug
- Fix repair bugs
This commit is contained in:
Mukhtar Akere
2025-04-09 20:00:06 +01:00
parent 92177b150b
commit a357897222
11 changed files with 205 additions and 156 deletions

View File

@@ -62,6 +62,23 @@ type Client struct {
retryableStatus map[int]bool
logger zerolog.Logger
proxy string
// cooldown
statusCooldowns map[int]time.Duration
statusCooldownsMu sync.RWMutex
lastStatusTime map[int]time.Time
lastStatusTimeMu sync.RWMutex
}
func WithStatusCooldown(statusCode int, cooldown time.Duration) ClientOption {
return func(c *Client) {
c.statusCooldownsMu.Lock()
if c.statusCooldowns == nil {
c.statusCooldowns = make(map[int]time.Duration)
}
c.statusCooldowns[statusCode] = cooldown
c.statusCooldownsMu.Unlock()
}
}
// WithMaxRetries sets the maximum number of retry attempts
@@ -177,7 +194,40 @@ func (c *Client) Do(req *http.Request) (*http.Response, error) {
}
c.headersMu.RUnlock()
if attempt > 0 && resp != nil {
c.statusCooldownsMu.RLock()
cooldown, exists := c.statusCooldowns[resp.StatusCode]
c.statusCooldownsMu.RUnlock()
if exists {
c.lastStatusTimeMu.RLock()
lastTime, timeExists := c.lastStatusTime[resp.StatusCode]
c.lastStatusTimeMu.RUnlock()
if timeExists {
elapsed := time.Since(lastTime)
if elapsed < cooldown {
// We need to wait longer for this status code
waitTime := cooldown - elapsed
select {
case <-req.Context().Done():
return nil, req.Context().Err()
case <-time.After(waitTime):
// Continue after waiting
}
}
}
}
}
resp, err = c.doRequest(req)
if err == nil {
c.lastStatusTimeMu.Lock()
c.lastStatusTime[resp.StatusCode] = time.Now()
c.lastStatusTimeMu.Unlock()
}
if err != nil {
// Check if this is a network error that might be worth retrying
if attempt < c.maxRetries {
@@ -271,10 +321,12 @@ func New(options ...ClientOption) *Client {
http.StatusServiceUnavailable: true,
http.StatusGatewayTimeout: true,
},
logger: logger.New("request"),
timeout: 60 * time.Second,
proxy: "",
headers: make(map[string]string), // Initialize headers map
logger: logger.New("request"),
timeout: 60 * time.Second,
proxy: "",
headers: make(map[string]string), // Initialize headers map
statusCooldowns: make(map[int]time.Duration),
lastStatusTime: make(map[int]time.Time),
}
// default http client