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

refactor: clean up rate limit handling #2694

Merged
merged 16 commits into from Aug 24, 2018
Merged

refactor: clean up rate limit handling #2694

merged 16 commits into from Aug 24, 2018

Conversation

Lewdcario
Copy link
Contributor

@Lewdcario Lewdcario commented Jul 31, 2018

Please describe the changes this PR makes and why it should be merged:
This (tries to) accomplish a few things:

  • Add an error class for the other errors we get with requests
  • Removes burst due to almost complete lack of use
  • Catches node-fetch errors
  • Simply rework ratelimit handling slightly (hopefully makes it easier to work with in the future)
  • Hardcode reaction ratelimit
  • Emit Client#debug notifying of an actual 429 being hit if it ever happens
  • Make errors in RequestHandler#execute catchable (via normally catching the request at top level)

Please suggest anything that can be done better, as there probably are things. Thanks!

Semantic versioning classification:

  • This PR changes the library's interface (methods or parameters added)
    • This PR includes breaking changes (methods removed or renamed, parameters moved or removed)
  • This PR only includes non-code changes, like changes to documentation, README, etc.

Copy link
Member

@appellation appellation left a comment

Choose a reason for hiding this comment

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

you're mixing standard promises with async/await syntax. I would like to see this rewritten using async/await and then review further then.

function parseResponse(res) {
if (res.headers.get('content-type').startsWith('application/json')) return res.json();
// eslint-disable-next-line no-undef
if (browser) return res.blob();
Copy link
Member

Choose a reason for hiding this comment

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

why the eslint disable

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My eslint was acting up, it seems, will remove it.


this.limit = limit ? Number(limit) : Infinity;
this.remaining = remaining ? Number(remaining) : 1;
this.reset = reset ? this._calculateReset(reset, serverDate) + 100 : Date.now();
Copy link
Member

Choose a reason for hiding this comment

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

why are we offsetting reset times by 100ms

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I figured, as before, we should have some leeway in case we are ever barely off in calculations. Is it better removed entirely, or reduced?

Copy link
Contributor

Choose a reason for hiding this comment

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

Removed entirely. We already have a rainy day fund that no other discord library implements (let alone has on by default), which is d.js reactions are slower than any other library, even those who don't hardcode. ClientOptions#restTimeOffset... Speaking of, it looks like you have inadvertently removed that functionality.

A rainy day fund is really not necessary, but if it's there, it should continue to be configurable.

if (this.limited) {
const timeout = this.reset - Date.now();

if (this.manager.client.listenerCount(RATE_LIMIT)) {
Copy link
Member

Choose a reason for hiding this comment

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

no need to access client from the manager

Copy link
Contributor

Choose a reason for hiding this comment

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

this.client is undefined?

// A ratelimit was hit - this should never happen
this.queue.unshift(item);
await Util.delayFor(this.retryAfter);
return this.run();
Copy link
Member

Choose a reason for hiding this comment

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

we should emit an event for this, whether it's debug or its own special event

* @param {string} rateLimitInfo.path Path used for request that triggered this event
* @param {string} rateLimitInfo.route Route used for request that triggered this event
*/
this.client.emit(RATE_LIMIT, {
Copy link
Contributor

Choose a reason for hiding this comment

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

this.manager.client

this.retryAfter = retryAfter ? Number(retryAfter) : -1;

// https://github.com/discordapp/discord-api-docs/issues/182
if (item.request.route.includes('reactions')) {
this.reset = Date.now() + this._getAPIOffset(serverDate) + 250 + this.client.options.restTimeOffset;
this.reset = Date.now() + this._getAPIOffset(serverDate) + 250;
}
}

// After calculations, pre-emptively stop farther requests
Copy link
Contributor

@bdistin bdistin Aug 9, 2018

Choose a reason for hiding this comment

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

"Further" Versus "Farther" The quick and dirty tip is to use “farther” for physical distance and “further” for metaphorical, or figurative, distance.


_getAPIOffset(serverDate) {
return new Date(serverDate).getTime() - Date.now();
}
Copy link
Member

Choose a reason for hiding this comment

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

this seems like it can be moved to a simple function in this file rather than being a class method, as it doesn't seem like this should be used anywhere else and doesn't require this context


_calculateReset(reset, serverDate) {
return new Date(Number(reset) * 1000).getTime() - this._getAPIOffset(serverDate);
}
Copy link
Member

Choose a reason for hiding this comment

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

^


run() {
if (this.queue.length === 0) return;
this.execute(this.queue.shift());

This comment was marked as resolved.


/* eslint-disable-next-line complexity */
async execute(item) {
// Insert item back to the beginning if currently busy

This comment was marked as resolved.

*/
this.path = path;

if (Error.captureStackTrace) Error.captureStackTrace(this, this.constructor);
Copy link
Member

Choose a reason for hiding this comment

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

If #2744 lands first, this line could be removed since it would capture the stack trace twice.

@iCrawl iCrawl merged commit 13f46b9 into discordjs:master Aug 24, 2018
@Lewdcario Lewdcario deleted the rest branch August 28, 2018 15:23
SpaceEEC pushed a commit that referenced this pull request Sep 23, 2018
Class was introduced with #2694 

* typings: Add HTTPError class definition

* typings: Sort HTTPError's members by name
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.

None yet

6 participants