Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Request: Describe the ratelimit for each operation #23

Open
danny-may opened this issue Aug 27, 2023 · 4 comments
Open

Request: Describe the ratelimit for each operation #23

danny-may opened this issue Aug 27, 2023 · 4 comments

Comments

@danny-may
Copy link

danny-may commented Aug 27, 2023

To avoid hitting ratelimits, a library needs to be able to guess, with some degree of confidence, which bucket a request will fall into before making the request. Most libraries do this by messing around with the URL+Method being requested to get a local bucket id, and using that to point to a real bucket id once the first request has been made. It would be useful if the method of getting that initial local bucket id would be something that can be worked out from the spec. Perhaps something like:

{
  "paths": {
    "/channels/{channel_id}/messages": {
      "get": {
        ...
        "x-discord-ratelimit": "GET /channels/{channel_id}/messages" // ratelimited by method and channel_id,
        "x-discord-ratelimit-global": true // falls under the global 50/s request limit
      },
      ...
    },
    ...
    "/channels/{channel_id}/messages/{message_id}": {
      "get": {
        ...
        "x-discord-ratelimit": "GET /channels/{channel_id}/messages/0", // ratelimited by method and channel_id, ignoring the message_id
        "x-discord-ratelimit-global": true // falls under the global 50/s request limit
      },
      ...
    },
    ...
    "/interactions/{interaction_id}/{interaction_token}/callback": {
      "post": {
        ...
        "x-discord-ratelimit": "POST /interactions/{interaction_id}/{interaction_token}/callback", // ratelimited by method, interaction_id and interaction_token
        "x-discord-ratelimit-global": false // Does not fall under the global 50/s request limit
      }
      ...
    },
    ...
  }
}

Some issues with this that I can see are:

  • Emoji ratelimits depend on the guild, but only the channel appears in the URL. From what I can see, most libraries rate limit these routes off of the channel and just end up having many local bucket ids pointing to the same real bucket id.
  • The message delete endpoint seems to be split into 3 buckets based on the age of the message. This can be computed from the message_id, but Im not sure how best to go about describing this in the spec. Perpaps something generic-ish would be nice? like "DELETE /channels/{channel_id}/messages/{message_id:age(10000,1209600000)}" (Split the age using 2 boundaries into 3 buckets - age < 10s, 10s <= age < 2 weeks, 2 weeks <= age). That could then be reused if discord ever adds a similar age-based ratelimit split for another endpoint in the future
@HunteRoi
Copy link

I agree!

@Zoddo
Copy link

Zoddo commented Aug 27, 2023

The message delete endpoint seems to be split into 2 buckets based on the age of the message.

AFAIK, there is actually 3 different buckets on this endpoint:

  • For messages created less than 10 seconds ago
  • For messages created between 10 seconds and 14 days ago
  • For messages created more than 14 days ago

This is a perfect example of why such exceptions should be documented somehow.

@danny-may
Copy link
Author

Ive updated the age based bucketing suggestion to support any number of categories. I figured that using nested ternaries would be hard to consume so I think just listing the boundaries of each range would be better

@erkinalp
Copy link

@Zoddo Just separate buckets, or does the window period also change?

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

No branches or pull requests

5 participants