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

fix: Different ratelimits for the same route (implement discord buckets) #1546

Merged
merged 9 commits into from
Aug 6, 2020

Conversation

SubZero0
Copy link
Member

@SubZero0 SubZero0 commented May 23, 2020

Summary

The same route can have different ratelimits depending on the http method (post, patch, get, ...) and different endpoints can share the same limit on their route.

An example would be GetMessageAsync and IUserMessage.ModifyAsync that are GET channels/{channel.id}/messages and PATCH channels/{channel.id}/messages that would previously have the same bucket, channels/{channel.id}/messages, but GET has no specific limit, while PATCH does.

The issue happening was:

  1. GetMessageAsync is called, it's GET
  2. No ratelimit header is returned, so the semaphore is disabled
  3. ModifyAsync is called, it's PATCH, but the endpoint is the same so it gets the same bucket as GET
  4. The semaphore is disabled so it won't update the limits or try to delay

An easy way to repro it without this fix:

var c = Context.Client.GetChannel(/*channelId*/) as SocketTextChannel;
var m = await c.GetMessageAsync(/*messageId*/) as IUserMessage; //This will disable the semaphore
for (int i = 0; i < 20; i++)
    _ = m.ModifyAsync(x => x.Content = "test"); //This will trigger the ratelimit (not the preemptive)

Fixes #1535

Changes

  • Add HttpMethod when generating the bucket id.
  • Add X-RateLimit-Bucket to RateLimitInfo
  • Add WebhookId as a major parameter into BucketIds
  • Changed the bucket list to fit two kinds of KVPs, Hash and Endpoint Buckets (Hash are shared limits by one or more endpoints, so the list will redirect them to it)
  • Add BucketId as it's own class
  • Change all places that used the bucket id as a string to the BucketId class

References

discord/discord-api-docs#981
discord/discord-api-docs#1551
https://discord.com/developers/docs/topics/rate-limits#header-format

Sometimes Discord won't send any ratelimit headers, disabling the semaphore for endpoints that should have them.
@AraHaan
Copy link

AraHaan commented May 26, 2020

Is this ready to merge?

@SubZero0
Copy link
Member Author

Is this ready to merge?

In my tests it was working fine, but more would be better, specially by people that were having this issue (like who created the issue).

@SubZero0
Copy link
Member Author

SubZero0 commented May 26, 2020

Did a few more tests and notice _semaphore can be negative, so I will need to change that compare to <= instead of ==.

But it still seems something is weird atm, the buckets are being disabled instead of updated with the correct ratelimit. From what I saw, it's working because it's solely relying on the headers that for some reason seem to not being passed correctly.

I'll need some more time to see what's going on.

@SubZero0
Copy link
Member Author

SubZero0 commented May 26, 2020

Ok, I believe I understood the real issue going on, just need some time to find where.

@SubZero0 SubZero0 changed the title fix: Ratelimiter getting disabled when it's needed fix: HttpMethods have different limits for the same endpoint May 26, 2020
@SubZero0
Copy link
Member Author

SubZero0 commented May 27, 2020

Think I got the real reason that was happening and why I reached the wrong conclusion the first time.

The issue was that methods with different http methods but the same endpoint were sharing the same bucket for ratelimits, so while one wouldn't have specific limits, the other would.

Example: GET Message and PATCH Message. So getting a message would disable the bucket, then, when trying to PATCH, it wouldn't be able to update the limits, making possible to reach the actual ratelimit.

I still need to check and test if different http methods might share the same bucket, like PATCH/POST.

@SubZero0 SubZero0 marked this pull request as draft May 27, 2020 00:29
@SubZero0 SubZero0 changed the title fix: HttpMethods have different limits for the same endpoint fix: Different limits for the same endpoint May 27, 2020
@SubZero0
Copy link
Member Author

Added X-RateLimit-Bucket that will join buckets based on the value provided by that header and the endpoint, excluding the http method in these cases.

Now I believe there's two tests needed to be done:

  1. What happens when there's two requests being processed in different buckets but that would be actually the same.
  2. Since I didn't look extensively how the bucket ids are generated, it would probably be better to check if they are only the major parameters

Reference
discord/discord-api-docs#981
discord/discord-api-docs#1551
https://discord.com/developers/docs/topics/rate-limits#header-format

@SubZero0 SubZero0 changed the title fix: Different limits for the same endpoint fix: Different limits for the same route May 27, 2020
- BucketId is it's own class now
- Add WebhookId as a major parameter
- Add shared buckets using the hash and major parameters
@SubZero0
Copy link
Member Author

SubZero0 commented May 27, 2020

The last commit was to change the BucketId to keep track of the major parameters of the route to easily create a shared bucket between different endpoints since the previous one only used the endpoint. It's all related to the 2nd point I made on my previous comment.

I still need to check the 1st and do the necessary changes (+ add some missing documentation).

@SubZero0
Copy link
Member Author

SubZero0 commented May 28, 2020

Added a way to redirect requests to another bucket when it's discovered it should be a hash one. This will deal with the 1st point I made on my previous comment.

Now I just need to do some tests to see how it's behaving and check for possible issues.

@SubZero0
Copy link
Member Author

I think I reached a stable ground. I'll open it for review, but probably would be better testing it on a real bot, since test ones can only achieve so much trying to "spam" the API with random requests.

@SubZero0 SubZero0 marked this pull request as ready for review May 31, 2020 00:33
@SubZero0 SubZero0 changed the title fix: Different limits for the same route fix: Different ratelimits for the same route (implement discord buckets) May 31, 2020
@BrammyS
Copy link
Contributor

BrammyS commented Jun 3, 2020

@SubZero0 I can try to test it on one of my nodes. Any good ways on how i could install it? :P

@SubZero0
Copy link
Member Author

SubZero0 commented Jun 3, 2020

@SubZero0 I can try to test it on one of my nodes. Any good ways on how i could install it? :P

@BramEsendam You will need to clone the repo and compile this branch (or reference it from your project).

I have been running this for almost 3 days on my bot (2 shards, 1.6k servers) and so far so good. Didn't reach any true ratelimit or got deadlocked afaik (at least there was no report of the bot not responding, so can't say 100% for sure).

@AraHaan
Copy link

AraHaan commented Jun 3, 2020

I sadly cant say either because I only ever reached the role "ratelimit" once on 1 of the myget preview packages (And I do call a lot onto roles for patreon related stuff based on tiers of people returned from their API as well in an webhook on ask.net core 3.1). Although I do check if the users already got the roles (and list them out for AddRoles) and if they do have them already I have it bail out to try to prevent ratelimit (why request if it wont do any changes am I right?). And it basically has 1 command to basically re-cache everything it caches.

@AraHaan
Copy link

AraHaan commented Jun 6, 2020

I have actually manged to ratelimit a lot more because of patreon themselves seeming to request my locally hosted api all at once which then causes a race condition which then causes ratelimits...
So this is making me want to start ratelimiting them now.

18:10:49 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:49 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:49 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:49 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:49 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:49 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:49 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:49 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:49 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:49 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:49 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:49 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:51 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:51 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:51 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:51 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:51 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:51 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:51 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:51 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:51 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:51 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:51 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:51 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:51 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:51 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:51 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:51 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:51 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:51 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:51 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:51 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:51 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:51 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:51 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:51 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:51 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:51 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:51 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:52 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:52 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:52 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:52 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:52 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:52 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:52 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:52 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:52 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:52 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:52 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:52 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:52 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:52 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:52 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:52 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:52 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:53 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:53 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:53 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:53 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:53 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:53 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:53 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:53 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:54 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:54 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:54 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:54 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:54 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:54 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:54 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:54 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:54 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:54 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:54 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:54 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:54 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:54 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:54 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:54 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:54 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:54 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:54 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:54 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:54 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:54 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:54 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:54 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:54 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:54 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:54 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:54 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:54 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:54 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:54 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:54 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:54 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:54 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:54 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:54 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:54 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:54 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:54 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:56 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:58 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:58 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:58 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:58 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:58 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:58 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:58 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:58 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:58 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:58 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:58 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:58 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:58 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:58 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:58 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:58 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:58 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:58 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:58 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:58 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:58 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:58 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:59 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:59 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:59 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:59 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:59 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:59 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:59 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:59 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:59 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:59 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:59 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:59 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:59 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:59 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:59 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:59 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:59 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:59 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:59 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:59 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:59 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:59 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:59 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:59 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:59 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:59 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:59 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:59 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:59 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:59 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:59 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:59 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:59 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:59 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:59 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:59 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:59 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:59 Rest        Rate limit triggered: channels/710558365192945676/messages
18:10:59 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:00 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:01 Rest        Rate limit triggered: channels/710558365192945676/messages
18:11:02 Rest        Rate limit triggered: channels/710558365192945676/messages

@SubZero0
Copy link
Member Author

SubZero0 commented Jun 6, 2020

I have actually manged to ratelimit a lot more because of patreon themselves seeming to request my locally hosted api all at once which then causes a race condition which then causes ratelimits...
So this is making me want to start ratelimiting them now.

@AraHaan Not sure if I follow what you are saying, but I believe you aren't running Discord.Net with this patch since I changed the way how it'll display the bucket.

Your message is Rate limit triggered: channels/710558365192945676/messages and with this patch it should be either:

  • Rate limit triggered: POST channels/710558365192945676/messages, as it'll include the HttpMethod, unless it's gateway that isn't in yet and has different names.
  • Rate limit triggered: 80c17d2f203122d936070c88c8d10f33:710558365192945676, so it'll be the hash then major parameters, separated by a colon.

@AraHaan
Copy link

AraHaan commented Jun 6, 2020

Ye, I am using the latest myget package version of d.net on it currently. Also it seems after a while since that ratelimit triggers that it also seems to look offline all the time after that.

Alright so I have decided to clone this to make slight edits to where the reconnection logic is to actually make logs from within it on every line (would contain line numbers) to try to find where in the code that me and others actually experience the deadlock at.

@AraHaan
Copy link

AraHaan commented Jun 10, 2020

good news it looks like this branch works for now (have not tested it long enough to get my issue yet though) I also posted 1 idea though in an open issue for ConnectionManager.cs that might be an issue however not clear yet if it really is though. It might be an issue from within ApiClient or the event that is registered for that class inside of DiscordSocketClient or in the event itself somewhere.

I would have to do more digging and more logging to find out what is really going on.

Starting up Patreon Pledges server...
Booting up discord bot.
04:30:37 Discord     Discord.Net v2.3.0-dev-dev (API v6)
04:30:43 Rest        GET voice/regions: 3695.76 ms
04:30:47 Rest        GET users/@me: 84.79 ms
04:30:52 Rest        GET gateway: 26.43 ms
mybot#1567 is connected!
04:31:09 Rest        POST channels/710558365192945676/messages: 221.88 ms
04:31:16 Rest        POST channels/710558365192945676/messages: 143.32 ms
04:31:20 Rest        POST channels/710558365192945676/messages: 227.21 ms
04:31:24 Rest        POST channels/710558365192945676/messages: 144.98 ms
04:31:27 Rest        POST channels/710558365192945676/messages: 138.69 ms
04:31:30 Rest        POST channels/710558365192945676/messages: 116.2 ms
04:31:33 Rest        POST channels/710558365192945676/messages: 121.96 ms
04:31:36 Rest        POST channels/710558365192945676/messages: 139.29 ms
04:31:36 Rest        Preemptive Rate limit triggered: 80c17d2f203122d936070c88c8d10f33:710558365192945676
04:31:40 Rest        POST channels/710558365192945676/messages: 1050.8 ms
04:31:46 Rest        POST channels/710558365192945676/messages: 182.37 ms
04:31:49 Rest        POST channels/710558365192945676/messages: 123.98 ms
04:31:49 Rest        POST channels/710558365192945676/messages: 140.27 ms
04:31:51 Rest        POST channels/710558365192945676/messages: 127.16 ms
04:31:52 Rest        POST channels/710558365192945676/messages: 94.22 ms
04:31:53 Rest        POST channels/710558365192945676/messages: 101.44 ms

@SubZero0
Copy link
Member Author

SubZero0 commented Jun 10, 2020

@AraHaan I believe your post should be in that issue, because this PR has nothing to do with the connection deadlock (or shouldn't have). It's about fixing the ratelimiter that doesn't work properly by not accounting shared buckets between endpoints.

I would also recommend uploading those logs as a file, as you can see, it's huge and makes reading other comments really hard.

@AraHaan
Copy link

AraHaan commented Jun 10, 2020

Alright I think that this is stable enough for me on my bot. Not sure about others but I think this is safe to merge.

@BrammyS
Copy link
Contributor

BrammyS commented Jul 8, 2020

Is this still getting added. :?
Because i need it.

@AraHaan
Copy link

AraHaan commented Jul 8, 2020

I think I found what can cause deadlocks in the code and narrowed it down to the usage of SemaphoreSlims that also causes my code to deadlock as well when I try to have my code also wait until the invoke is completed on an async timer which is related in the actual semaphore on the Wait or WaitAsync calls in that class waiting indefinitely even when there are nothing executing on the semaphore. I have currently no idea what to do to fix the semaphore issue both in my code and in discord.net. It just makes me feel like the usage of SemaphoreSlims could be a major contributing factor to the connection deadlocks.

@SubZero0
Copy link
Member Author

SubZero0 commented Jul 8, 2020

I think I found what can cause deadlocks in the code and narrowed it down to the usage of SemaphoreSlims that also causes my code to deadlock as well when I try to have my code also wait until the invoke is completed on an async timer which is related in the actual semaphore on the Wait or WaitAsync calls in that class waiting indefinitely even when there are nothing executing on the semaphore. I have currently no idea what to do to fix the semaphore issue both in my code and in discord.net. It just makes me feel like the usage of SemaphoreSlims could be a major contributing factor to the connection deadlocks.

I have no idea what you are talking about since this PR and the classes it modifies don't use SemaphoreSlim.

@AraHaan
Copy link

AraHaan commented Jul 14, 2020

ok so @SubZero0 I have fixed my issues on my end in combination to what was at fault on the lib's side of things in #1580. After fixing those I have realized that this is stable enough and can be merged without issues. My bot might only have 1 command but it is a large bot too because of it being ran in an ASP.NET Core webapi process and as such having an web interface and a lot of other integrations like calls to the patreon api to verify patrons and stuff as well as oauth providers to login to it's web interface using discord and patreon. It was a whole mother to set up and get working properly. However with these fixes to the ratelimits and my ConcurrentQueue on requests where every role change, message sent, w/e is done 1 time every second I do not hit them ratelimits no more (currently).

@BitPatty mind testing this pr?

@BitPatty
Copy link

Will test it on my issue and report back asap

@BitPatty
Copy link

Tested, Fixes #1535

Thanks 👍

@AraHaan
Copy link

AraHaan commented Jul 20, 2020

@SubZero0 ok the issue creator has tested that this fixes the issue.

@AraHaan
Copy link

AraHaan commented Aug 2, 2020

Any ETA?

@foxbot foxbot merged commit 2f6c017 into discord-net:dev Aug 6, 2020
@SubZero0 SubZero0 deleted the fix-ratelimits branch August 6, 2020 00:36
anonymousheadless pushed a commit to anonymousheadless/Discord.Net that referenced this pull request Mar 29, 2021
…ts) (discord-net#1546)

* Don't disable when there's no resetTick

Sometimes Discord won't send any ratelimit headers, disabling the semaphore for endpoints that should have them.

* Undo changes and change comment

* Add HttpMethod to BucketIds

* Add X-RateLimit-Bucket

* BucketId changes

- BucketId is it's own class now
- Add WebhookId as a major parameter
- Add shared buckets using the hash and major parameters

* Add webhookId to BucketIds

* Update BucketId and redirect requests

* General bugfixes

* Assign semaphore and follow the same standard as Reset for ResetAfter
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.

Add preemptive rate limit to GET and PATCH /channels/.../messages
5 participants