I'm working on a private browser extension which extracts some information from a web page and posts it into a Discord channel via a webhook.
The browser extension does evaluate the x-ratelimit-...
response headers to observe the rate limit restrictions.
While doing a "spam test" it seems that the rate limit restrictions are respected correctly and everything is working so far. However, every now and then I'm still getting rate limited after sending a stack of messages (15+) even though ratelimit-remaining
is > 0
.
To counter this I already stop when ratelimit-remaining
is 1
and also add an additional second to the ratelimit-reset
timestamp. But this doesn't seem to help.
let rateLimitRemaining = 5;
let rateLimitReset = 0;
function sendContent()
{
if ( contentQueue.length > 0 )
{
console.log( "Messages in content queue: " + contentQueue.length );
let content = contentQueue[ 0 ];
let dateTimestamp = getCurrentUTCTimestamp();
// Don't send if remaining rate limit is <= 1 and current UTC time is less than reset timestamp
if ( rateLimitRemaining <= 1 && dateTimestamp <= rateLimitReset )
return;
contentQueue.shift();
let url = "...";
sendMessage( content, url );
}
}
function sendMessage( content, url )
{
let payload = JSON.stringify( { "content": content } );
$.ajax(
{
contentType: 'application/json',
method: "POST",
url: url,
data: payload,
dataType: 'json'
} ).done( function( response, status, jqXHR )
{
rateLimitRemaining = parseInt( jqXHR.getResponseHeader( 'x-ratelimit-remaining' ) );
// Add an additional second to the reset timestamp
rateLimitReset = parseInt( jqXHR.getResponseHeader( 'x-ratelimit-reset' ) ) + 1;
let timeToResetRemaining = rateLimitReset - getCurrentUTCTimestamp();
console.log( '[' + getCurrentDateTime() + '] Content sent to webhook. Remaining until rate limit: ' + rateLimitRemaining + ' / Reset @ ' + rateLimitReset + ' (' + getCurrentUTCTimestamp() + ') (' + timeToResetRemaining + ')' );
} ).fail( function( jqXHR, status, error )
{
let response = jqXHR.responseJSON;
// If we got rate limited, respect the retry_after delay
if ( response.hasOwnProperty( 'message' ) && response.message.indexOf( 'rate limited' ) !== 0 )
{
rateLimitRemaining = 0;
rateLimitReset = getCurrentUTCTimestamp() + Math.ceil( response.retry_after / 1000 ) + 1;
}
console.log( '[' + getCurrentDateTime() + '] Error sending request to webhook.' );
console.log( response );
} );
}
It is also strange that the same request, which triggers the rate limit, has its x-ratelimit-remaining
response header at > 0.
What do I miss here? Where is my mistake? Do I need to take x-ratelimit-bucket
and x-ratelimit-reset-after
into account aswell?