(path: string, options: RequestInit, allowQueueing = true)
| 100 | } |
| 101 | |
| 102 | private async fetch(path: string, options: RequestInit, allowQueueing = true) { |
| 103 | if (!this.authService.isAuthenticated()) { |
| 104 | return |
| 105 | } |
| 106 | |
| 107 | const token = this.authService.getSessionToken() |
| 108 | |
| 109 | if (!token) { |
| 110 | console.error(`[TelemetryClient#fetch] Unauthorized: No session token available.`) |
| 111 | return |
| 112 | } |
| 113 | |
| 114 | const url = `${getRooCodeApiUrl()}/api/${path}` |
| 115 | const fetchOptions: RequestInit = { |
| 116 | ...options, |
| 117 | headers: { |
| 118 | Authorization: `Bearer ${token}`, |
| 119 | "Content-Type": "application/json", |
| 120 | }, |
| 121 | } |
| 122 | |
| 123 | try { |
| 124 | const response = await fetch(url, fetchOptions) |
| 125 | |
| 126 | if (!response.ok) { |
| 127 | console.error( |
| 128 | `[TelemetryClient#fetch] ${options.method} ${path} -> ${response.status} ${response.statusText}`, |
| 129 | ) |
| 130 | |
| 131 | // Queue for retry on server errors (5xx) or rate limiting (429) |
| 132 | // Do NOT retry on client errors (4xx) except 429 - they won't succeed |
| 133 | if (this.retryQueue && allowQueueing && (response.status >= 500 || response.status === 429)) { |
| 134 | await this.retryQueue.enqueue(url, fetchOptions, "telemetry") |
| 135 | } |
| 136 | } |
| 137 | |
| 138 | return response |
| 139 | } catch (error) { |
| 140 | console.error(`[TelemetryClient#fetch] Network error for ${options.method} ${path}: ${error}`) |
| 141 | |
| 142 | // Queue for retry on network failures (typically TypeError with "fetch failed" message) |
| 143 | // These are transient network issues that may succeed on retry |
| 144 | if ( |
| 145 | this.retryQueue && |
| 146 | allowQueueing && |
| 147 | error instanceof TypeError && |
| 148 | error.message.includes("fetch failed") |
| 149 | ) { |
| 150 | await this.retryQueue.enqueue(url, fetchOptions, "telemetry") |
| 151 | } |
| 152 | |
| 153 | throw error |
| 154 | } |
| 155 | } |
| 156 | |
| 157 | public override async capture(event: TelemetryEvent) { |
| 158 | if (!this.isTelemetryEnabled() || !this.isEventCapturable(event.event)) { |
no test coverage detected