Skip to content

Commit

Permalink
Add option to limit ratelimit retry window
Browse files Browse the repository at this point in the history
  • Loading branch information
DonovanDMC committed Aug 18, 2024
1 parent 25472f6 commit 85d6538
Show file tree
Hide file tree
Showing 6 changed files with 22 additions and 4 deletions.
2 changes: 1 addition & 1 deletion lib/gateway/Shard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import type { RawGuild } from "../types/guilds";
import ExtendedUser from "../structures/ExtendedUser";
import type Guild from "../structures/Guild";
import type { ShardEvents } from "../types/events";
import GatewayError, { DependencyError } from "../util/Errors";
import { GatewayError, DependencyError } from "../util/Errors";
import ClientApplication from "../structures/ClientApplication";
import WebSocket, { type Data } from "ws";
import { randomBytes } from "node:crypto";
Expand Down
2 changes: 1 addition & 1 deletion lib/gateway/compression/pako.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Compression from "./base";
import type Shard from "../Shard";
import GatewayError from "../../util/Errors";
import { GatewayError } from "../../util/Errors";
import { Inflate, constants } from "pako";

interface PakoExtra {
Expand Down
2 changes: 1 addition & 1 deletion lib/gateway/compression/zlib-sync.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Compression from "./base";
import type Shard from "../Shard";
import GatewayError from "../../util/Errors";
import { GatewayError } from "../../util/Errors";
import ZlibSync from "zlib-sync";

export default class ZlibSyncCompression extends Compression {
Expand Down
5 changes: 5 additions & 0 deletions lib/rest/RequestHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { API_URL, RESTMethods, USER_AGENT, type RESTMethod } from "../Constants"
import Base from "../structures/Base";
import type { LatencyRef, RequestHandlerInstanceOptions, RequestOptions } from "../types/request-handler";
import type { RESTOptions } from "../types/client";
import { RateLimitedError } from "../util/Errors";

/**
* Latency & ratelimit related things lovingly borrowed from eris
Expand All @@ -33,6 +34,7 @@ export default class RequestHandler {
followRedirects: !!options.followRedirects,
host: options.host ?? (options.baseURL ? new URL(options.baseURL).host : new URL(API_URL).host),
latencyThreshold: options.latencyThreshold ?? 30000,
maxRatelimitRetryWindow: options.maxRatelimitRetryWindow ?? Infinity,
ratelimiterOffset: options.ratelimiterOffset ?? 0,
requestTimeout: options.requestTimeout ?? 15000,
superProperties: options.superProperties ?? null,
Expand Down Expand Up @@ -262,6 +264,9 @@ export default class RequestHandler {

this._manager.client.emit("debug", `${res.headers.has("x-ratelimit-global") ? "Global" : "Unexpected"} RateLimit: ${JSON.stringify(resBody)}\n${now} ${route} ${res.status}: ${latency}ms (${this.latencyRef.latency}ms avg) | ${this.ratelimits[route].remaining}/${this.ratelimits[route].limit} left | Reset ${delay} (${this.ratelimits[route].reset - now}ms left) | Scope ${res.headers.get("x-ratelimit-scope")!}`);
if (delay) {
if (delay > this.options.maxRatelimitRetryWindow) {
throw new RateLimitedError(`Ratelimit on "${options.method} ${route}" exceeds the maximum retry window (${delay} > ${this.options.maxRatelimitRetryWindow})`);
}
setTimeout(() => {
cb();
// eslint-disable-next-line prefer-rest-params, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call, prefer-spread
Expand Down
6 changes: 6 additions & 0 deletions lib/types/client.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ export interface RESTOptions {
* @defaultValue 30000
*/
latencyThreshold?: number;
/**
* In milliseconds, the maximum ratelimit delay (in seconds) the lib will internally wait for to retry the request. If a ratelimit resets after this window, an error will be thrown instead.
* @note This currently defaults to Infinity for backwards compatibility, but this will be changed in 1.12.0.
* @defaultValue Infinity
*/
maxRatelimitRetryWindow?: number;
/**
* In milliseconds, the time to offset ratelimit calculations by.
* @defaultValue 0
Expand Down
9 changes: 8 additions & 1 deletion lib/util/Errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,18 @@ export class DependencyError extends Error {


/** A gateway error. */
export default class GatewayError extends Error {
export class GatewayError extends Error {
code: number;
override name = "GatewayError";
constructor(message: string, code: number) {
super(message);
this.code = code;
}
}

export class RateLimitedError extends Error {
override name = "RateLimitedError";
constructor(message: string) {
super(message);
}
}

0 comments on commit 85d6538

Please sign in to comment.