mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-13 01:53:30 +01:00
rework concurrency
This commit is contained in:
@@ -1,82 +1,104 @@
|
||||
const handlers = require('./handlers');
|
||||
const APIRequest = require('./APIRequest');
|
||||
const routeBuilder = require('./APIRouter');
|
||||
const RequestBucket = require('./RequestBucket');
|
||||
const { Error } = require('../errors');
|
||||
const { Endpoints } = require('../util/Constants');
|
||||
const Collection = require('../util/Collection');
|
||||
|
||||
/**
|
||||
* Rest manager.
|
||||
* @private
|
||||
*/
|
||||
class RESTManager {
|
||||
constructor(client, tokenPrefix = 'Bot') {
|
||||
/**
|
||||
* @type {Client}
|
||||
*/
|
||||
this.client = client;
|
||||
this.handlers = new Collection();
|
||||
|
||||
/**
|
||||
* Request buckets, mapped by bucket
|
||||
* @type {Collection<string, RequestHandler>}
|
||||
*/
|
||||
this.buckets = new Collection();
|
||||
|
||||
/**
|
||||
* Whether we're globally limited
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.globallyRateLimited = false;
|
||||
|
||||
/**
|
||||
* The token prefix to use when generating authorization headers
|
||||
* @type {string}
|
||||
*/
|
||||
this.tokenPrefix = tokenPrefix;
|
||||
|
||||
/**
|
||||
* Whether to use a versioned endpoint. Default to true.
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.versioned = true;
|
||||
this.timeDifferences = [];
|
||||
|
||||
if (client.options.restSweepInterval > 0) {
|
||||
client.setInterval(() => {
|
||||
this.handlers.sweep(handler => handler._inactive);
|
||||
this.buckets.sweep(handler => handler.queue.idle());
|
||||
}, client.options.restSweepInterval * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The authorization header to use
|
||||
* @readonly
|
||||
* @type {string}
|
||||
*/
|
||||
get auth() {
|
||||
const token = this.client.token || this.client.accessToken;
|
||||
const prefixed = !!this.client.application || (this.client.user && this.client.user.bot);
|
||||
if (token) {
|
||||
if (prefixed) return `${this.tokenPrefix} ${token}`;
|
||||
return token;
|
||||
} else {
|
||||
throw new Error('TOKEN_MISSING');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a new API router
|
||||
* @readonly
|
||||
* @type {APIRouter}
|
||||
*/
|
||||
get api() {
|
||||
return routeBuilder(this);
|
||||
}
|
||||
|
||||
get timeDifference() {
|
||||
return Math.round(this.timeDifferences.reduce((a, b) => a + b, 0) / this.timeDifferences.length);
|
||||
}
|
||||
|
||||
set timeDifference(ms) {
|
||||
this.timeDifferences.unshift(ms);
|
||||
if (this.timeDifferences.length > 5) this.timeDifferences.length = 5;
|
||||
}
|
||||
|
||||
getAuth() {
|
||||
const token = this.client.token || this.client.accessToken;
|
||||
const prefixed = !!this.client.application || (this.client.user && this.client.user.bot);
|
||||
if (token && prefixed) return `${this.tokenPrefix} ${token}`;
|
||||
else if (token) return token;
|
||||
throw new Error('TOKEN_MISSING');
|
||||
}
|
||||
|
||||
/**
|
||||
* The CDN endpoint
|
||||
* @readonly
|
||||
* @type {string}
|
||||
*/
|
||||
get cdn() {
|
||||
return Endpoints.CDN(this.client.options.http.cdn);
|
||||
}
|
||||
|
||||
push(handler, apiRequest) {
|
||||
return new Promise((resolve, reject) => {
|
||||
handler.push({
|
||||
request: apiRequest,
|
||||
resolve,
|
||||
reject,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getRequestHandler() {
|
||||
const method = this.client.options.apiRequestMethod;
|
||||
if (typeof method === 'function') return method;
|
||||
const handler = handlers[method];
|
||||
if (!handler) throw new Error('RATELIMIT_INVALID_METHOD');
|
||||
return handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a request
|
||||
* @param {string} method The HTTP verb to use
|
||||
* @param {string} url The Discord URL
|
||||
* @param {*} options Options to send
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
request(method, url, options = {}) {
|
||||
const apiRequest = new APIRequest(this, method, url, options);
|
||||
let handler = this.handlers.get(apiRequest.route);
|
||||
const req = new APIRequest(this, method, url, options);
|
||||
let bucket = this.buckets.get(req.route);
|
||||
|
||||
if (!handler) {
|
||||
handler = new handlers.RequestHandler(this, this.getRequestHandler());
|
||||
this.handlers.set(apiRequest.route, handler);
|
||||
if (!bucket) {
|
||||
bucket = new RequestBucket(this, req.route);
|
||||
this.buckets.set(req.route, bucket);
|
||||
}
|
||||
|
||||
return this.push(handler, apiRequest);
|
||||
}
|
||||
|
||||
set endpoint(endpoint) {
|
||||
this.client.options.http.api = endpoint;
|
||||
return bucket.enqueue(req);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user