{"id":"ddavness/http-queue","name":"http-queue","scope":"ddavness","platform":"roblox","description":"A library that lets you send HTTP requests to external services while respecting their rate limits.","version":"1.1.6","latest":"1.1.6","versions":["1.1.6"],"license":"MIT","licenseRating":"safe","licenseCaveats":[],"licenseVerified":true,"dependencies":{"evaera/promise":{"version":"^4.0.0","alias":"Promise"},"osyrisrblx/t":{"version":"^3.0.0","alias":"t"}},"integrity":"5969f6696baf2bfd61dbd5bfe31222b9b57cd7722b9f12a23567a1adf0debe58","likes":0,"downloads":0,"install":"forest install ddavness/http-queue","url":"https://forest.dev/p/roblox/ddavness/http-queue","files":"https://api.forest.dev/ai/package/roblox/ddavness/http-queue/files","readme":"# Roblox Http Queue\r\n\r\n## Current version: `v1.1.6`\r\n\r\nWriting code to make requests is simple, and maybe fun. Writing code that gracefully handles everything that can go wrong in a request... Well, that's a boring thing to do.\r\n\r\nThis library is intended to help easing this by, in particular, handling servers that impose rate limits. Writing code to handle that and make sure every request we make is accepted<b>*</b> by the server and is not lost.\r\n\r\nThis project is powered by [evaera's Promise implementation](https://github.com/evaera/roblox-lua-promise) and [Osyris' **t** typechecking library](https://github.com/osyrisrblx/t).\r\n\r\nYou can use this library according to the terms of the MIT license.\r\n\r\n<b>*</b> <small>For *accepted* I mean \"not rate-limited\". I cannot make guarantees that the service will not refuse to process the request due to, for example, invalid tokens or permissions.</small>\r\n\r\n## Installation\r\n\r\n### GitHub Releases\r\n\r\nJust grab the `.rbxmx` file from the releases page and drop into your project - as simple as that!\r\n\r\n### Roblox-TS users\r\n\r\nUse `npm`:\r\n\r\n```\r\nnpm install @rbxts/http-queue\r\n```\r\n\r\n> A more comprehensive guide for Roblox-TS users can be read [here](./README-TS.md).\r\n\r\n## Usage\r\n\r\nRequire the module:\r\n\r\n```lua\r\nlocal Http = require(game:GetService(\"ServerScriptService\").HttpQueue)\r\n```\r\n\r\nCreate a request and send it:\r\n\r\n```lua\r\nlocal request = Http.HttpRequest.new(\"https://some.website.com/\", \"GET\", nil, {auth = \"im very cool\", cool = true})\r\n-- Actual Request URL is https://some.website.com/?auth=im very cool&cool=true\r\n\r\n-- The :Send() method returns a Promise that resolves to a response!\r\nrequest:Send():andThen(function(response)\r\n    print(response.Body)\r\nend):catch(function(err)\r\n    print(\"ERROR!\", err)\r\nend)\r\n\r\n-- Do some work while we wait for the response to arrive\r\n\r\n-- If you want to yield the script until the response arrives\r\nlocal response = request:AwaitSend()\r\n```\r\n\r\nThis is cool and all, but we can make this more interesting. Let's say you want to use Trello in your application. Unfortunately, the rate limiting of Trello is very tight (10 requests per 10 seconds per token for Roblox clients).\r\n\r\nInstead of worrying about it yourself, you can delegate the responsability of dealing with the rate limits to a queue.\r\n\r\n```lua\r\nlocal TrelloQueue = Http.HttpQueue.new({\r\n    retryAfter = {cooldown = 10} -- If rate limited, retry in 10 seconds\r\n    maxSimultaneousSendOperations = 10 -- Don't send more than 10 requests at a time (optional)\r\n})\r\n\r\n-- Let's change the name to a Trello board, 1000 times (don't do this at home!)\r\nfor i = 1, 1000 do\r\n    local request = Http.HttpRequest.new(\"https://api.trello.com/1/boards/5d6f8ec6764c2112a27e3d12\", \"PUT\", nil, {\r\n        key = \"Your developer key\",\r\n        token = \"Your developer token\",\r\n        name = \"Your board's new name (\" .. tostring(i) ..\")\"\r\n    }))\r\n\r\n    TrelloQueue:Push(request):andThen(function(response)\r\n        -- This will never print \"429 Too Many Requests\"\r\n        print(response.StatusMessage)\r\n    end)\r\nend\r\n\r\n-- Do some work while we wait for the response to arrive\r\n\r\n-- If you want to yield the script until the response comes in:\r\nlocal response = TrelloQueue:AwaitPush(request)\r\n```\r\n\r\nDepending on what service you're using, sometimes the cooldown period varies over time: When creating a new Queue, you can specify how to deal with this on the `retryAfter` option:\r\n\r\n- `{cooldown = (number)}` - If you know that the cooldown period is a fixed number of seconds.\r\n- `{header = (string)}` - If the cooldown time is present, in **seconds**, in a response header sent by the service.\r\n- `{callback = (function)}` - For all other cases. Takes the server response and returns the number of seconds that the queue should stall before sending more requests.\r\n\r\n**Examples:**\r\n\r\n```lua\r\n-- Cooldown is fixed to 5 seconds\r\nlocal staticQueue = HttpQueue.new({\r\n    retryAfter = {cooldown = 5}\r\n})\r\n\r\n-- We check the \"x-rate-limit-cooldown-s\" header to determine how long to stall\r\nlocal headerQueue = HttpQueue.new({\r\n    retryAfter = {header = \"x-rate-limit-cooldown-s\"}\r\n})\r\n\r\n-- We use a callback to parse the response body and retrieve the cooldown period\r\nlocal callbackQueue = HttpQueue.new({\r\n    retryAfter = {callback = function(response)\r\n        -- Our service returns a JSON body. The cooldown period is noted in milliseconds on the \"cooldown\" field.\r\n        return game:GetService(\"HttpService\"):JSONDecode(response.Body).cooldown / 1000\r\n    end}\r\n})\r\n```\r\n\r\nThe queue works on a \"first come, first serve\" basis. This means that requests being pushed first will be dealt with first by the queue. (**HOWEVER, this doesn't mean the responses will arrive in order!**)\r\n\r\nYou can override that behavior by passing a `priority` parameter to the `:Push()` or `:AwaitPush()` methods. There are three options available:\r\n\r\n`HttpRequestPriority.Normal` - the default priority. The request is pushed to the back of the regular queue.\r\n\r\n`HttpRequestPriority.Prioritary` - The request is pushed to the back of the prioritary queue, that is done by the queue runner before the regular queue.\r\n\r\n`HttpRequestPriority.First` - The request is pushed to the front of the prioritary queue.\r\n\r\n**NOTE:** The priority features should be used sparingly.\r\n\r\n**Example:**\r\n\r\n```lua\r\nTrelloQueue:Push(request, Http.HttpRequestPriority.Prioritary)\r\n```\r\n\r\n## Type Guards\r\n\r\nThis library also comes with type guard functions that allow you to check whether a value is actually what you want:\r\n\r\n`isHttpRequest(value)`\r\n\r\n`isHttpRequestPriority(value)`\r\n\r\n`isHttpResponse(value)`\r\n\r\n`isHttpQueue(value)`\r\n","readmeTruncated":false}