The queue entry that failed.
The error that triggered the retry.
export function retryQueueEntry(entry: QueueEntry, error: Error): void {
const attempt = entry.attempt ?? 0;
const maxAttempts = entry.maxAttempts ?? MAX_RETRIES;
if (attempt < maxAttempts) {
// Calculate backoff and re-enqueue with incremented attempt
const backoffMs = calculateBackoff(attempt);
const newEntry: QueueEntry = {
...entry,
attempt: attempt + 1,
nextEligibleAt: Date.now() + backoffMs,
};
requestQueue.push(newEntry);
console.warn(
`[RateLimitQueue] Retrying request (attempt ${attempt + 1}/${maxAttempts}) after ${backoffMs}ms`,
);
// Ensure processor is running to handle the re-queued entry
if (!isProcessingQueue()) {
processRateLimitQueue();
}
} else {
// Max retries exceeded - notify listeners and emit event
console.error(
`[RateLimitQueue] Request failed after ${maxAttempts} attempts:`,
error.message,
);
if (entry.onRetryFailed) {
entry.onRetryFailed(error);
}
if (typeof globalThis.dispatchEvent === "function") {
globalThis.dispatchEvent(
new CustomEvent("ratelimit:permanent-failure", {
detail: { error: error.message, attempt: maxAttempts },
}),
);
}
}
}
Re-queue a failed request with exponential backoff.
Computes backoff based on attempt count, increments the attempt counter, and re-enqueues the entry. Emits permanent failure event when max retries are exceeded.