Skip to content

Respect retry_after in HTTP 429 response#470

Open
merlinfuchs wants to merge 1 commit into
diamondburned:v3from
merlinfuchs:ratelimiting
Open

Respect retry_after in HTTP 429 response#470
merlinfuchs wants to merge 1 commit into
diamondburned:v3from
merlinfuchs:ratelimiting

Conversation

@merlinfuchs

Copy link
Copy Markdown

Arikawa does prevent most 429's by respecting the headers returned by Discord but some rate limits aren't indicated by the headers.

Comment thread utils/httputil/client.go
if status = r.GetStatus(); status == StatusTooManyRequests || status >= 500 {
status = r.GetStatus()

if status == StatusNirnTimeout || status >= 500 {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the case of a 5xx response, I think we should do our own exponential backoff to prevent spamming Discord.

Comment thread utils/httputil/client.go
if status = r.GetStatus(); status == StatusTooManyRequests || status >= 500 {
status = r.GetStatus()

if status == StatusNirnTimeout || status >= 500 {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than adding a StatusNirnTimeout, I think we should just write status == http.StatusRequestTimeout.

Comment thread utils/httputil/client.go
err := json.Unmarshal(buf.Bytes(), &errBody)

if err == nil {
time.Sleep(time.Duration(errBody.RetryAfter) * time.Second)

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

time.Sleep is not context-aware. Prefer writing:

select {
case <-ctx.Done():
    doErr = ctx.Err()
    continue // or break out of the loop, but this will work too
case <-time.After(...):
    continue
}

Comment thread utils/httputil/client.go
RetryAfter float32 `json:"retry_after"`
}

err := json.Unmarshal(buf.Bytes(), &errBody)

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can shorten this to:

Suggested change
err := json.Unmarshal(buf.Bytes(), &errBody)
err := json.NewDecoder(body).Decode(&errBody)

Comment thread utils/httputil/client.go

err := json.Unmarshal(buf.Bytes(), &errBody)

if err == nil {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy path: put the if err != nil check first, then put the other case after the check.

@merlinfuchs

merlinfuchs commented Mar 21, 2025

Copy link
Copy Markdown
Author

I mainly made these changes so I can it in a project, I agree with your comments and can make the changes when I get around to it! Happy for you to also close this PR and make the changes :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants