Skip to content

Commit

Permalink
feat: expose Retry-After and sublimit timeouts in RatelimitData (#9864)
Browse files Browse the repository at this point in the history
* feat: expose Retry-After and sublimit timeouts in RatelimitData

* chore: better docs?

* Apply suggestions from code review

Co-authored-by: ckohen <[email protected]>

---------

Co-authored-by: ckohen <[email protected]>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
  • Loading branch information
3 people authored Nov 12, 2023
1 parent 62e6573 commit 81e7866
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 14 deletions.
19 changes: 18 additions & 1 deletion packages/rest/src/lib/errors/RateLimitError.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,22 @@ export class RateLimitError extends Error implements RateLimitData {

public global: boolean;

public constructor({ timeToReset, limit, method, hash, url, route, majorParameter, global }: RateLimitData) {
public retryAfter: number;

public sublimitTimeout: number;

public constructor({
timeToReset,
limit,
method,
hash,
url,
route,
majorParameter,
global,
retryAfter,
sublimitTimeout,
}: RateLimitData) {
super();
this.timeToReset = timeToReset;
this.limit = limit;
Expand All @@ -27,6 +42,8 @@ export class RateLimitError extends Error implements RateLimitData {
this.route = route;
this.majorParameter = majorParameter;
this.global = global;
this.retryAfter = retryAfter;
this.sublimitTimeout = sublimitTimeout;
}

/**
Expand Down
12 changes: 8 additions & 4 deletions packages/rest/src/lib/handlers/BurstHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,16 +102,20 @@ export class BurstHandler implements IHandler {
} else if (status === 429) {
// Unexpected ratelimit
const isGlobal = res.headers.has('X-RateLimit-Global');

await onRateLimit(this.manager, {
timeToReset: retryAfter,
limit: Number.POSITIVE_INFINITY,
global: isGlobal,
method,
hash: this.hash,
url,
route: routeId.bucketRoute,
majorParameter: this.majorParameter,
global: isGlobal,
hash: this.hash,
limit: Number.POSITIVE_INFINITY,
timeToReset: retryAfter,
retryAfter,
sublimitTimeout: 0,
});

this.debug(
[
'Encountered unexpected 429 rate limit',
Expand Down
24 changes: 16 additions & 8 deletions packages/rest/src/lib/handlers/SequentialHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,19 +227,23 @@ export class SequentialHandler implements IHandler {
}

const rateLimitData: RateLimitData = {
timeToReset: timeout,
limit,
global: isGlobal,
method: options.method ?? 'get',
hash: this.hash,
url,
route: routeId.bucketRoute,
majorParameter: this.majorParameter,
global: isGlobal,
hash: this.hash,
limit,
timeToReset: timeout,
retryAfter: timeout,
sublimitTimeout: 0,
};

// Let library users know they have hit a rate limit
this.manager.emit(RESTEvents.RateLimited, rateLimitData);
// Determine whether a RateLimitError should be thrown
await onRateLimit(this.manager, rateLimitData);

// When not erroring, emit debug for what is happening
if (isGlobal) {
this.debug(`Global rate limit hit, blocking all requests for ${timeout}ms`);
Expand Down Expand Up @@ -345,15 +349,18 @@ export class SequentialHandler implements IHandler {
}

await onRateLimit(this.manager, {
timeToReset: timeout,
limit,
global: isGlobal,
method,
hash: this.hash,
url,
route: routeId.bucketRoute,
majorParameter: this.majorParameter,
global: isGlobal,
hash: this.hash,
limit,
timeToReset: timeout,
retryAfter,
sublimitTimeout: sublimitTimeout ?? 0,
});

this.debug(
[
'Encountered unexpected 429 rate limit',
Expand All @@ -368,6 +375,7 @@ export class SequentialHandler implements IHandler {
` Sublimit : ${sublimitTimeout ? `${sublimitTimeout}ms` : 'None'}`,
].join('\n'),
);

// If caused by a sublimit, wait it out here so other requests on the route can be handled
if (sublimitTimeout) {
// Normally the sublimit queue will not exist, however, if a sublimit is hit while in the sublimit queue, it will
Expand Down
13 changes: 12 additions & 1 deletion packages/rest/src/lib/utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,12 +155,23 @@ export interface RateLimitData {
* The HTTP method being performed
*/
method: string;
/**
* The time, in milliseconds, that will need to pass before this specific request can be retried
*/
retryAfter: number;
/**
* The route being hit in this request
*/
route: string;
/**
* The time, in milliseconds, until the request-lock is reset
* The time, in milliseconds, that will need to pass before the sublimit lock for the route resets, and requests that fall under a sublimit
* can be retried
*
* This is only present on certain sublimits, and `0` otherwise
*/
sublimitTimeout: number;
/**
* The time, in milliseconds, until the route's request-lock is reset
*/
timeToReset: number;
/**
Expand Down

0 comments on commit 81e7866

Please sign in to comment.