()
| 101 | } |
| 102 | |
| 103 | public async retryAll(): Promise<void> { |
| 104 | if (this.isProcessing) { |
| 105 | this.log("[RetryQueue] Already processing, skipping retry cycle") |
| 106 | return |
| 107 | } |
| 108 | |
| 109 | // Check if the queue is manually paused (e.g., due to auth state) |
| 110 | if (this.isPaused) { |
| 111 | this.log("[RetryQueue] Queue is manually paused") |
| 112 | return |
| 113 | } |
| 114 | |
| 115 | // Check if the entire queue is paused due to rate limiting |
| 116 | if (this.queuePausedUntil && Date.now() < this.queuePausedUntil) { |
| 117 | this.log(`[RetryQueue] Queue is paused until ${new Date(this.queuePausedUntil).toISOString()}`) |
| 118 | return |
| 119 | } |
| 120 | |
| 121 | const requests = Array.from(this.queue.values()) |
| 122 | if (requests.length === 0) { |
| 123 | return |
| 124 | } |
| 125 | |
| 126 | this.isProcessing = true |
| 127 | |
| 128 | try { |
| 129 | // Sort by timestamp to process in FIFO order (oldest first) |
| 130 | requests.sort((a, b) => a.timestamp - b.timestamp) |
| 131 | |
| 132 | // Process all requests in FIFO order |
| 133 | for (const request of requests) { |
| 134 | try { |
| 135 | const response = await this.retryRequest(request) |
| 136 | |
| 137 | // Check if we got a 429 rate limiting response |
| 138 | if (response && response.status === 429) { |
| 139 | const retryAfter = response.headers.get("Retry-After") |
| 140 | if (retryAfter) { |
| 141 | // Parse Retry-After (could be seconds or a date) |
| 142 | let delayMs: number |
| 143 | const retryAfterSeconds = parseInt(retryAfter, 10) |
| 144 | if (!isNaN(retryAfterSeconds)) { |
| 145 | delayMs = retryAfterSeconds * 1000 |
| 146 | } else { |
| 147 | // Try parsing as a date |
| 148 | const retryDate = new Date(retryAfter) |
| 149 | if (!isNaN(retryDate.getTime())) { |
| 150 | delayMs = retryDate.getTime() - Date.now() |
| 151 | } else { |
| 152 | delayMs = 60000 // Default to 1 minute if we can't parse |
| 153 | } |
| 154 | } |
| 155 | // Pause the entire queue |
| 156 | this.queuePausedUntil = Date.now() + delayMs |
| 157 | this.log(`[RetryQueue] Rate limited, pausing entire queue for ${delayMs}ms`) |
| 158 | // Keep the request in the queue for later retry |
| 159 | this.queue.set(request.id, request) |
| 160 | // Stop processing further requests since the queue is paused |
no test coverage detected