mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-16 11:33:30 +01:00
feat: present x-ratelimit-scope for 429s hit (#9973)
* feat: present x-ratelimit-scope for 429s hit * fix: get scope from headers for burst too
This commit is contained in:
@@ -21,6 +21,8 @@ export class RateLimitError extends Error implements RateLimitData {
|
|||||||
|
|
||||||
public sublimitTimeout: number;
|
public sublimitTimeout: number;
|
||||||
|
|
||||||
|
public scope: RateLimitData['scope'];
|
||||||
|
|
||||||
public constructor({
|
public constructor({
|
||||||
timeToReset,
|
timeToReset,
|
||||||
limit,
|
limit,
|
||||||
@@ -32,6 +34,7 @@ export class RateLimitError extends Error implements RateLimitData {
|
|||||||
global,
|
global,
|
||||||
retryAfter,
|
retryAfter,
|
||||||
sublimitTimeout,
|
sublimitTimeout,
|
||||||
|
scope,
|
||||||
}: RateLimitData) {
|
}: RateLimitData) {
|
||||||
super();
|
super();
|
||||||
this.timeToReset = timeToReset;
|
this.timeToReset = timeToReset;
|
||||||
@@ -44,6 +47,7 @@ export class RateLimitError extends Error implements RateLimitData {
|
|||||||
this.global = global;
|
this.global = global;
|
||||||
this.retryAfter = retryAfter;
|
this.retryAfter = retryAfter;
|
||||||
this.sublimitTimeout = sublimitTimeout;
|
this.sublimitTimeout = sublimitTimeout;
|
||||||
|
this.scope = scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import type { RequestInit } from 'undici';
|
|||||||
import type { REST } from '../REST.js';
|
import type { REST } from '../REST.js';
|
||||||
import type { IHandler } from '../interfaces/Handler.js';
|
import type { IHandler } from '../interfaces/Handler.js';
|
||||||
import { RESTEvents } from '../utils/constants.js';
|
import { RESTEvents } from '../utils/constants.js';
|
||||||
import type { ResponseLike, HandlerRequestData, RouteData } from '../utils/types.js';
|
import type { ResponseLike, HandlerRequestData, RouteData, RateLimitData } from '../utils/types.js';
|
||||||
import { onRateLimit, sleep } from '../utils/utils.js';
|
import { onRateLimit, sleep } from '../utils/utils.js';
|
||||||
import { handleErrors, incrementInvalidCount, makeNetworkRequest } from './Shared.js';
|
import { handleErrors, incrementInvalidCount, makeNetworkRequest } from './Shared.js';
|
||||||
|
|
||||||
@@ -102,6 +102,7 @@ export class BurstHandler implements IHandler {
|
|||||||
} else if (status === 429) {
|
} else if (status === 429) {
|
||||||
// Unexpected ratelimit
|
// Unexpected ratelimit
|
||||||
const isGlobal = res.headers.has('X-RateLimit-Global');
|
const isGlobal = res.headers.has('X-RateLimit-Global');
|
||||||
|
const scope = (res.headers.get('X-RateLimit-Scope') ?? 'user') as RateLimitData['scope'];
|
||||||
|
|
||||||
await onRateLimit(this.manager, {
|
await onRateLimit(this.manager, {
|
||||||
global: isGlobal,
|
global: isGlobal,
|
||||||
@@ -114,6 +115,7 @@ export class BurstHandler implements IHandler {
|
|||||||
timeToReset: retryAfter,
|
timeToReset: retryAfter,
|
||||||
retryAfter,
|
retryAfter,
|
||||||
sublimitTimeout: 0,
|
sublimitTimeout: 0,
|
||||||
|
scope,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.debug(
|
this.debug(
|
||||||
@@ -128,6 +130,7 @@ export class BurstHandler implements IHandler {
|
|||||||
` Limit : ${Number.POSITIVE_INFINITY}`,
|
` Limit : ${Number.POSITIVE_INFINITY}`,
|
||||||
` Retry After : ${retryAfter}ms`,
|
` Retry After : ${retryAfter}ms`,
|
||||||
` Sublimit : None`,
|
` Sublimit : None`,
|
||||||
|
` Scope : ${scope}`,
|
||||||
].join('\n'),
|
].join('\n'),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -237,6 +237,7 @@ export class SequentialHandler implements IHandler {
|
|||||||
timeToReset: timeout,
|
timeToReset: timeout,
|
||||||
retryAfter: timeout,
|
retryAfter: timeout,
|
||||||
sublimitTimeout: 0,
|
sublimitTimeout: 0,
|
||||||
|
scope: 'user',
|
||||||
};
|
};
|
||||||
|
|
||||||
// Let library users know they have hit a rate limit
|
// Let library users know they have hit a rate limit
|
||||||
@@ -281,6 +282,7 @@ export class SequentialHandler implements IHandler {
|
|||||||
const reset = res.headers.get('X-RateLimit-Reset-After');
|
const reset = res.headers.get('X-RateLimit-Reset-After');
|
||||||
const hash = res.headers.get('X-RateLimit-Bucket');
|
const hash = res.headers.get('X-RateLimit-Bucket');
|
||||||
const retry = res.headers.get('Retry-After');
|
const retry = res.headers.get('Retry-After');
|
||||||
|
const scope = (res.headers.get('X-RateLimit-Scope') ?? 'user') as RateLimitData['scope'];
|
||||||
|
|
||||||
// Update the total number of requests that can be made before the rate limit resets
|
// Update the total number of requests that can be made before the rate limit resets
|
||||||
this.limit = limit ? Number(limit) : Number.POSITIVE_INFINITY;
|
this.limit = limit ? Number(limit) : Number.POSITIVE_INFINITY;
|
||||||
@@ -359,6 +361,7 @@ export class SequentialHandler implements IHandler {
|
|||||||
timeToReset: timeout,
|
timeToReset: timeout,
|
||||||
retryAfter,
|
retryAfter,
|
||||||
sublimitTimeout: sublimitTimeout ?? 0,
|
sublimitTimeout: sublimitTimeout ?? 0,
|
||||||
|
scope,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.debug(
|
this.debug(
|
||||||
@@ -373,6 +376,7 @@ export class SequentialHandler implements IHandler {
|
|||||||
` Limit : ${limit}`,
|
` Limit : ${limit}`,
|
||||||
` Retry After : ${retryAfter}ms`,
|
` Retry After : ${retryAfter}ms`,
|
||||||
` Sublimit : ${sublimitTimeout ? `${sublimitTimeout}ms` : 'None'}`,
|
` Sublimit : ${sublimitTimeout ? `${sublimitTimeout}ms` : 'None'}`,
|
||||||
|
` Scope : ${scope}`,
|
||||||
].join('\n'),
|
].join('\n'),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -164,6 +164,13 @@ export interface RateLimitData {
|
|||||||
* The route being hit in this request
|
* The route being hit in this request
|
||||||
*/
|
*/
|
||||||
route: string;
|
route: string;
|
||||||
|
/**
|
||||||
|
* The scope of the rate limit that was hit.
|
||||||
|
*
|
||||||
|
* This can be `user` for rate limits that are per client, `global` for rate limits that affect all clients or `shared` for rate limits that
|
||||||
|
* are shared per resource.
|
||||||
|
*/
|
||||||
|
scope: 'global' | 'shared' | 'user';
|
||||||
/**
|
/**
|
||||||
* The time, in milliseconds, that will need to pass before the sublimit lock for the route resets, and requests that fall under a sublimit
|
* 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
|
* can be retried
|
||||||
|
|||||||
Reference in New Issue
Block a user