refactor: use eslint-config-neon for packages. (#8579)

Co-authored-by: Noel <buechler.noel@outlook.com>
This commit is contained in:
Suneet Tipirneni
2022-09-01 14:50:16 -04:00
committed by GitHub
parent 4bdb0593ae
commit edadb9fe5d
219 changed files with 2608 additions and 2053 deletions

View File

@@ -1,14 +1,15 @@
import { setTimeout, clearTimeout } from 'node:timers';
import { setTimeout as sleep } from 'node:timers/promises';
import { AsyncQueue } from '@sapphire/async-queue';
import { request, type Dispatcher } from 'undici';
import type { IHandler } from './IHandler';
import type { RateLimitData, RequestOptions } from '../REST';
import type { HandlerRequestData, RequestManager, RouteData } from '../RequestManager';
import { DiscordAPIError, DiscordErrorData, OAuthErrorData } from '../errors/DiscordAPIError';
import { HTTPError } from '../errors/HTTPError';
import { RateLimitError } from '../errors/RateLimitError';
import { RESTEvents } from '../utils/constants';
import { hasSublimit, parseHeader, parseResponse } from '../utils/utils';
import { DiscordAPIError, type DiscordErrorData, type OAuthErrorData } from '../errors/DiscordAPIError.js';
import { HTTPError } from '../errors/HTTPError.js';
import { RateLimitError } from '../errors/RateLimitError.js';
import { RESTEvents } from '../utils/constants.js';
import { hasSublimit, parseHeader, parseResponse } from '../utils/utils.js';
import type { IHandler } from './IHandler.js';
/**
* Invalid request limiting is done on a per-IP basis, not a per-token basis.
@@ -47,7 +48,7 @@ export class SequentialHandler implements IHandler {
/**
* The total number of requests that can be made before we are rate limited
*/
private limit = Infinity;
private limit = Number.POSITIVE_INFINITY;
/**
* The interface used to sequence async requests sequentially
@@ -65,7 +66,7 @@ export class SequentialHandler implements IHandler {
* A promise wrapper for when the sublimited queue is finished being processed or null when not being processed
*/
// eslint-disable-next-line @typescript-eslint/explicit-member-accessibility
#sublimitPromise: { promise: Promise<void>; resolve: () => void } | null = null;
#sublimitPromise: { promise: Promise<void>; resolve(): void } | null = null;
/**
* Whether the sublimit queue needs to be shifted in the finally block
@@ -176,6 +177,7 @@ export class SequentialHandler implements IHandler {
queue = this.#sublimitedQueue!;
queueType = QueueType.Sublimit;
}
// Wait for any previous requests to be completed before this one is run
await queue.wait();
// This set handles retroactively sublimiting requests
@@ -194,6 +196,7 @@ export class SequentialHandler implements IHandler {
await this.#sublimitPromise.promise;
}
}
try {
// Make the request, and return the results
return await this.runRequest(routeId, url, options, requestData);
@@ -204,6 +207,7 @@ export class SequentialHandler implements IHandler {
this.#shiftSublimit = false;
this.#sublimitedQueue?.shift();
}
// If this request is the last request in a sublimit
if (this.#sublimitedQueue?.remaining === 0) {
this.#sublimitPromise?.resolve();
@@ -247,6 +251,7 @@ export class SequentialHandler implements IHandler {
// The global delay function clears the global delay state when it is resolved
this.manager.globalDelay = this.globalDelayFor(timeout);
}
delay = this.manager.globalDelay;
} else {
// Set RateLimitData based on the route-specific limit
@@ -254,6 +259,7 @@ export class SequentialHandler implements IHandler {
timeout = this.timeToReset;
delay = sleep(timeout);
}
const rateLimitData: RateLimitData = {
timeToReset: timeout,
limit,
@@ -274,14 +280,17 @@ export class SequentialHandler implements IHandler {
} else {
this.debug(`Waiting ${timeout}ms for rate limit to pass`);
}
// Wait the remaining time left before the rate limit resets
await delay;
}
// As the request goes out, update the global usage information
if (!this.manager.globalReset || this.manager.globalReset < Date.now()) {
this.manager.globalReset = Date.now() + 1000;
this.manager.globalReset = Date.now() + 1_000;
this.manager.globalRemaining = this.manager.options.globalRequestsPerSecond;
}
this.manager.globalRemaining--;
const method = options.method ?? 'get';
@@ -295,6 +304,7 @@ export class SequentialHandler implements IHandler {
} catch (error: unknown) {
// Retry the specified number of times for possible timed out requests
if (error instanceof Error && error.name === 'AbortError' && retries !== this.manager.options.retries) {
// eslint-disable-next-line no-param-reassign
return await this.runRequest(routeId, url, options, requestData, ++retries);
}
@@ -328,14 +338,14 @@ export class SequentialHandler implements IHandler {
const retry = parseHeader(res.headers['retry-after']);
// Update the total number of requests that can be made before the rate limit resets
this.limit = limit ? Number(limit) : Infinity;
this.limit = limit ? Number(limit) : Number.POSITIVE_INFINITY;
// Update the number of remaining requests that can be made before the rate limit resets
this.remaining = remaining ? Number(remaining) : 1;
// Update the time when this rate limit resets (reset-after is in seconds)
this.reset = reset ? Number(reset) * 1000 + Date.now() + this.manager.options.offset : Date.now();
this.reset = reset ? Number(reset) * 1_000 + Date.now() + this.manager.options.offset : Date.now();
// Amount of time in milliseconds until we should retry if rate limited (globally or otherwise)
if (retry) retryAfter = Number(retry) * 1000 + this.manager.options.offset;
if (retry) retryAfter = Number(retry) * 1_000 + this.manager.options.offset;
// Handle buckets via the hash header retroactively
if (hash && hash !== this.hash) {
@@ -373,9 +383,10 @@ export class SequentialHandler implements IHandler {
// Count the invalid requests
if (status === 401 || status === 403 || status === 429) {
if (!invalidCountResetTime || invalidCountResetTime < Date.now()) {
invalidCountResetTime = Date.now() + 1000 * 60 * 10;
invalidCountResetTime = Date.now() + 1_000 * 60 * 10;
invalidCount = 0;
}
invalidCount++;
const emitInvalid =
@@ -407,6 +418,7 @@ export class SequentialHandler implements IHandler {
limit = this.limit;
timeout = this.timeToReset;
}
await this.onRateLimit({
timeToReset: timeout,
limit,
@@ -440,10 +452,12 @@ export class SequentialHandler implements IHandler {
void this.#sublimitedQueue.wait();
this.#asyncQueue.shift();
}
this.#sublimitPromise?.resolve();
this.#sublimitPromise = null;
await sleep(sublimitTimeout, undefined, { ref: false });
let resolve: () => void;
// eslint-disable-next-line promise/param-names, no-promise-executor-return
const promise = new Promise<void>((res) => (resolve = res));
this.#sublimitPromise = { promise, resolve: resolve! };
if (firstSublimit) {
@@ -452,13 +466,16 @@ export class SequentialHandler implements IHandler {
this.#shiftSublimit = true;
}
}
// Since this is not a server side issue, the next request should pass, so we don't bump the retries counter
return this.runRequest(routeId, url, options, requestData, retries);
} else if (status >= 500 && status < 600) {
// Retry the specified number of times for possible server side issues
if (retries !== this.manager.options.retries) {
// eslint-disable-next-line no-param-reassign
return this.runRequest(routeId, url, options, requestData, ++retries);
}
// We are out of retries, throw an error
throw new HTTPError(res.constructor.name, status, method, url, requestData);
} else {
@@ -468,11 +485,13 @@ export class SequentialHandler implements IHandler {
if (status === 401 && requestData.auth) {
this.manager.setToken(null!);
}
// The request will not succeed for some reason, parse the error returned from the api
const data = (await parseResponse(res)) as DiscordErrorData | OAuthErrorData;
// throw the API error
throw new DiscordAPIError(data, 'code' in data ? data.code : data.error, status, method, url, requestData);
}
return res;
}
}