diff --git a/package-lock.json b/package-lock.json index 673245d83..ac8345f0e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "@discordjs/collection": "^0.1.6", "@discordjs/form-data": "^3.0.1", + "@sapphire/async-queue": "^1.1.2", "abort-controller": "^3.0.0", "node-fetch": "^2.6.1", "prism-media": "^1.2.9", @@ -1527,6 +1528,15 @@ "node": ">= 10.14.2" } }, + "node_modules/@sapphire/async-queue": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.1.2.tgz", + "integrity": "sha512-NkR7AzC9uyb++tMIZgG4X0ci8JM1rnvNmKbLwY42RgotRV8JGUntZ7ZpR7MN7p5zPlVdKo/YmOqcCCsBJ6LNuw==", + "engines": { + "node": ">=14", + "npm": ">=6" + } + }, "node_modules/@sinonjs/commons": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.1.tgz", @@ -12389,6 +12399,11 @@ "chalk": "^4.0.0" } }, + "@sapphire/async-queue": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.1.2.tgz", + "integrity": "sha512-NkR7AzC9uyb++tMIZgG4X0ci8JM1rnvNmKbLwY42RgotRV8JGUntZ7ZpR7MN7p5zPlVdKo/YmOqcCCsBJ6LNuw==" + }, "@sinonjs/commons": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.1.tgz", diff --git a/package.json b/package.json index f6aa5a9b3..bb18b26aa 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "dependencies": { "@discordjs/collection": "^0.1.6", "@discordjs/form-data": "^3.0.1", + "@sapphire/async-queue": "^1.1.2", "abort-controller": "^3.0.0", "node-fetch": "^2.6.1", "prism-media": "^1.2.9", diff --git a/src/rest/AsyncQueue.js b/src/rest/AsyncQueue.js deleted file mode 100644 index b465f6aaf..000000000 --- a/src/rest/AsyncQueue.js +++ /dev/null @@ -1,95 +0,0 @@ -/** - * MIT License - * - * Copyright (c) 2020 kyranet, discord.js - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -'use strict'; - -// TODO(kyranet, vladfrangu): replace this with discord.js v13's core AsyncQueue. - -/** - * An async queue that preserves the stack and prevents lock-ups. - * @private - */ -class AsyncQueue { - constructor() { - /** - * The promises array. - * @type {Array<{promise: Promise, resolve: Function}>} - * @private - */ - this.promises = []; - } - - /** - * The remaining amount of queued promises - * @type {number} - */ - get remaining() { - return this.promises.length; - } - - /** - * Waits for last promise and queues a new one. - * @returns {Promise} - * @example - * const queue = new AsyncQueue(); - * async function request(url, options) { - * await queue.wait(); - * try { - * const result = await fetch(url, options); - * // Do some operations with 'result' - * } finally { - * // Remove first entry from the queue and resolve for the next entry - * queue.shift(); - * } - * } - * - * request(someUrl1, someOptions1); // Will call fetch() immediately - * request(someUrl2, someOptions2); // Will call fetch() after the first finished - * request(someUrl3, someOptions3); // Will call fetch() after the second finished - */ - wait() { - const next = this.promises.length ? this.promises[this.promises.length - 1].promise : Promise.resolve(); - let resolve; - const promise = new Promise(res => { - resolve = res; - }); - - this.promises.push({ - resolve, - promise, - }); - - return next; - } - - /** - * Frees the queue's lock for the next item to process. - */ - shift() { - const deferred = this.promises.shift(); - if (typeof deferred !== 'undefined') deferred.resolve(); - } -} - -module.exports = AsyncQueue; diff --git a/src/rest/RequestHandler.js b/src/rest/RequestHandler.js index 2ede1f5a7..2b76ecf2c 100644 --- a/src/rest/RequestHandler.js +++ b/src/rest/RequestHandler.js @@ -1,6 +1,6 @@ 'use strict'; -const AsyncQueue = require('./AsyncQueue'); +const { AsyncQueue } = require('@sapphire/async-queue'); const DiscordAPIError = require('./DiscordAPIError'); const HTTPError = require('./HTTPError'); const {