Skip to content
This repository was archived by the owner on Mar 18, 2026. It is now read-only.

Commit 5c21bad

Browse files
committed
feat: Improve rate limiting and retry mechanism in RequestQueue
1 parent 3993146 commit 5c21bad

1 file changed

Lines changed: 19 additions & 7 deletions

File tree

src/services/request-queue-service.ts

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -93,14 +93,20 @@ export class RequestQueue<T> {
9393
* This method is called automatically when requests are enqueued
9494
*/
9595
private async processQueue(): Promise<void> {
96-
if (this.processing || this.queue.length === 0 || !this.rateLimiter.getToken()) {
96+
if (this.processing || this.queue.length === 0) {
9797
return;
9898
}
9999

100100
this.processing = true;
101101

102102
try {
103-
while (this.queue.length > 0 && this.rateLimiter.getAvailableTokens() > 0) {
103+
while (this.queue.length > 0) {
104+
// Try to get a token before processing the next request
105+
if (!this.rateLimiter.getToken()) {
106+
// No token available, stop processing this batch and wait for refill
107+
break;
108+
}
109+
104110
const now = Date.now();
105111
const timeSinceLastRequest = now - this.lastRequestTime;
106112

@@ -160,18 +166,21 @@ export class RequestQueue<T> {
160166
// Implement exponential backoff for retries
161167
if (request.retryCount < this.maxRetries) {
162168
request.retryCount++;
163-
this.queue.push(request);
164-
const retryDelay = this.retryDelay * Math.pow(2, request.retryCount - 1); // Exponential backoff
169+
const retryDelayMs = this.retryDelay * Math.pow(2, request.retryCount - 1); // Exponential backoff
165170

166171
logger.info(`Retrying request`, {
167172
requestId: request.requestId,
168173
attempt: request.retryCount,
169174
maxRetries: this.maxRetries,
170-
retryDelay,
175+
retryDelay: retryDelayMs,
171176
error: error instanceof Error ? error.message : String(error),
172177
});
173178

174-
await new Promise((resolve) => setTimeout(resolve, retryDelay));
179+
// Re-queue the request to be processed later, non-blockingly
180+
setTimeout(() => {
181+
this.queue.push(request); // Add to the back of the queue
182+
void this.processQueue(); // Attempt to process queue again
183+
}, retryDelayMs);
175184
} else {
176185
// If it's already an ApiError, pass it through
177186
if (error instanceof ApiError) {
@@ -192,7 +201,10 @@ export class RequestQueue<T> {
192201
}
193202
} finally {
194203
this.processing = false;
195-
if (this.queue.length > 0 && this.rateLimiter.getAvailableTokens() > 0) {
204+
// If there are still items in the queue and tokens might be available,
205+
// try to process again. This handles cases where the loop broke due to
206+
// lack of tokens but tokens might have refilled.
207+
if (this.queue.length > 0) {
196208
void this.processQueue();
197209
}
198210
}

0 commit comments

Comments
 (0)