axios+telemetry cleanup
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
import axios, { type AxiosRequestConfig, type AxiosResponse } from 'axios'
|
||||
import { randomUUID } from 'crypto'
|
||||
import { getOauthConfig } from 'src/constants/oauth.js'
|
||||
import { getOrganizationUUID } from 'src/services/oauth/client.js'
|
||||
@@ -7,6 +6,7 @@ import { getClaudeAIOAuthTokens } from '../auth.js'
|
||||
import { logForDebugging } from '../debug.js'
|
||||
import { parseGitHubRepository } from '../detectRepository.js'
|
||||
import { errorMessage, toError } from '../errors.js'
|
||||
import { isHttpError, nativeRequest } from '../http.js'
|
||||
import { lazySchema } from '../lazySchema.js'
|
||||
import { logError } from '../log.js'
|
||||
import { sleep } from '../sleep.js'
|
||||
@@ -19,40 +19,40 @@ const MAX_TELEPORT_RETRIES = TELEPORT_RETRY_DELAYS.length
|
||||
export const CCR_BYOC_BETA = 'ccr-byoc-2025-07-29'
|
||||
|
||||
/**
|
||||
* Checks if an axios error is a transient network error that should be retried
|
||||
* Checks if an error is a transient network error that should be retried
|
||||
*/
|
||||
export function isTransientNetworkError(error: unknown): boolean {
|
||||
if (!axios.isAxiosError(error)) {
|
||||
return false
|
||||
if (isHttpError(error)) {
|
||||
// Retry on server errors (5xx)
|
||||
return !!error.status && error.status >= 500
|
||||
}
|
||||
|
||||
// Retry on network errors (no response received)
|
||||
if (!error.response) {
|
||||
return true
|
||||
// Treat generic Error as transient?
|
||||
// Native fetch throws generic Error for network issues
|
||||
if (error instanceof Error) {
|
||||
const msg = error.message.toLowerCase()
|
||||
return msg.includes('network') || msg.includes('timeout') || msg.includes('aborted')
|
||||
}
|
||||
|
||||
// Retry on server errors (5xx)
|
||||
if (error.response.status >= 500) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Don't retry on client errors (4xx) - they're not transient
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes an axios GET request with automatic retry for transient network errors
|
||||
* Makes a native GET request with automatic retry for transient network errors
|
||||
* Uses exponential backoff: 2s, 4s, 8s, 16s (4 retries = 5 total attempts)
|
||||
*/
|
||||
export async function axiosGetWithRetry<T>(
|
||||
export async function nativeGetWithRetry<T>(
|
||||
url: string,
|
||||
config?: AxiosRequestConfig,
|
||||
): Promise<AxiosResponse<T>> {
|
||||
options: { headers?: Record<string, string> } = {},
|
||||
): Promise<{ data: T; status: number }> {
|
||||
let lastError: unknown
|
||||
|
||||
for (let attempt = 0; attempt <= MAX_TELEPORT_RETRIES; attempt++) {
|
||||
try {
|
||||
return await axios.get<T>(url, config)
|
||||
return await nativeRequest<T>(url, {
|
||||
method: 'GET',
|
||||
...options,
|
||||
})
|
||||
} catch (error) {
|
||||
lastError = error
|
||||
|
||||
@@ -215,12 +215,12 @@ export async function fetchCodeSessionsFromSessionsAPI(): Promise<
|
||||
'x-organization-uuid': orgUUID,
|
||||
}
|
||||
|
||||
const response = await axiosGetWithRetry<ListSessionsResponse>(url, {
|
||||
const response = await nativeGetWithRetry<ListSessionsResponse>(url, {
|
||||
headers,
|
||||
})
|
||||
|
||||
if (response.status !== 200) {
|
||||
throw new Error(`Failed to fetch code sessions: ${response.statusText}`)
|
||||
throw new Error(`Failed to fetch code sessions: ${response.status}`)
|
||||
}
|
||||
|
||||
// Transform SessionResource[] to CodeSession[] format
|
||||
@@ -298,10 +298,10 @@ export async function fetchSession(
|
||||
'x-organization-uuid': orgUUID,
|
||||
}
|
||||
|
||||
const response = await axios.get<SessionResource>(url, {
|
||||
const response = await nativeRequest<SessionResource>(url, {
|
||||
method: 'GET',
|
||||
headers,
|
||||
timeout: 15000,
|
||||
validateStatus: status => status < 500,
|
||||
})
|
||||
|
||||
if (response.status !== 200) {
|
||||
@@ -319,7 +319,7 @@ export async function fetchSession(
|
||||
|
||||
throw new Error(
|
||||
apiMessage ||
|
||||
`Failed to fetch session: ${response.status} ${response.statusText}`,
|
||||
`Failed to fetch session: ${response.status}`,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -393,9 +393,10 @@ export async function sendEventToRemoteSession(
|
||||
)
|
||||
// The endpoint may block until the CCR worker is ready. Observed ~2.6s
|
||||
// in normal cases; allow a generous margin for cold-start containers.
|
||||
const response = await axios.post(url, requestBody, {
|
||||
const response = await nativeRequest<any>(url, {
|
||||
method: 'POST',
|
||||
body: requestBody,
|
||||
headers,
|
||||
validateStatus: status => status < 500,
|
||||
timeout: 30000,
|
||||
})
|
||||
|
||||
@@ -439,14 +440,11 @@ export async function updateSessionTitle(
|
||||
logForDebugging(
|
||||
`[updateSessionTitle] Updating title for session ${sessionId}: "${title}"`,
|
||||
)
|
||||
const response = await axios.patch(
|
||||
url,
|
||||
{ title },
|
||||
{
|
||||
headers,
|
||||
validateStatus: status => status < 500,
|
||||
},
|
||||
)
|
||||
const response = await nativeRequest<any>(url, {
|
||||
method: 'PATCH',
|
||||
body: { title },
|
||||
headers,
|
||||
})
|
||||
|
||||
if (response.status === 200) {
|
||||
logForDebugging(
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import axios from 'axios'
|
||||
import { getOauthConfig } from 'src/constants/oauth.js'
|
||||
import { getOrganizationUUID } from 'src/services/oauth/client.js'
|
||||
import { getClaudeAIOAuthTokens } from '../auth.js'
|
||||
import { toError } from '../errors.js'
|
||||
import { nativeRequest } from '../http.js'
|
||||
import { logError } from '../log.js'
|
||||
import { getOAuthHeaders } from './api.js'
|
||||
|
||||
@@ -50,15 +50,14 @@ export async function fetchEnvironments(): Promise<EnvironmentResource[]> {
|
||||
'x-organization-uuid': orgUUID,
|
||||
}
|
||||
|
||||
const response = await axios.get<EnvironmentListResponse>(url, {
|
||||
const response = await nativeRequest<EnvironmentListResponse>(url, {
|
||||
method: 'GET',
|
||||
headers,
|
||||
timeout: 15000,
|
||||
})
|
||||
|
||||
if (response.status !== 200) {
|
||||
throw new Error(
|
||||
`Failed to fetch environments: ${response.status} ${response.statusText}`,
|
||||
)
|
||||
throw new Error(`Failed to fetch environments: ${response.status}`)
|
||||
}
|
||||
|
||||
return response.data.environments
|
||||
@@ -86,9 +85,9 @@ export async function createDefaultCloudEnvironment(
|
||||
}
|
||||
|
||||
const url = `${getOauthConfig().BASE_API_URL}/v1/environment_providers/cloud/create`
|
||||
const response = await axios.post<EnvironmentResource>(
|
||||
url,
|
||||
{
|
||||
const response = await nativeRequest<EnvironmentResource>(url, {
|
||||
method: 'POST',
|
||||
body: {
|
||||
name,
|
||||
kind: 'anthropic_cloud',
|
||||
description: '',
|
||||
@@ -107,14 +106,12 @@ export async function createDefaultCloudEnvironment(
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
...getOAuthHeaders(accessToken),
|
||||
'anthropic-beta': 'ccr-byoc-2025-07-29',
|
||||
'x-organization-uuid': orgUUID,
|
||||
},
|
||||
timeout: 15000,
|
||||
headers: {
|
||||
...getOAuthHeaders(accessToken),
|
||||
'anthropic-beta': 'ccr-byoc-2025-07-29',
|
||||
'x-organization-uuid': orgUUID,
|
||||
},
|
||||
)
|
||||
timeout: 15000,
|
||||
})
|
||||
return response.data
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user