mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-07 01:47:47 +08:00
fix(conversion): improve stream failures and diagnostic exports
This commit is contained in:
@@ -4,6 +4,7 @@ const { getMock } = vi.hoisted(() => ({ getMock: vi.fn() }))
|
||||
vi.mock('@/api/client', () => ({ default: { get: getMock } }))
|
||||
|
||||
import { dashboardApi } from '@/api/dashboard'
|
||||
import { requestTraceApi } from '@/api/requestTrace'
|
||||
import { cache } from '@/utils/cache'
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -13,6 +14,20 @@ beforeEach(() => {
|
||||
})
|
||||
|
||||
describe('dashboard body loading', () => {
|
||||
it('reports download progress so diagnostic exports can abort oversized bodies', async () => {
|
||||
const onProgress = vi.fn()
|
||||
getMock.mockResolvedValue({ data: new ArrayBuffer(0), headers: { 'x-aether-body-encoding': 'json', 'x-aether-usage-id': 'usage-1', 'x-aether-body-field': 'response_body' } })
|
||||
await dashboardApi.getRequestBody('usage-1', 'response_body', undefined, onProgress)
|
||||
getMock.mock.calls[0][1].onDownloadProgress({ loaded: 2 * 1024 * 1024 })
|
||||
expect(onProgress).toHaveBeenCalledWith(2 * 1024 * 1024)
|
||||
})
|
||||
|
||||
it('records the gateway version at export without confusing it with failure-time metadata', async () => {
|
||||
getMock.mockResolvedValue({ data: { request_id: 'request-1', candidates: [] }, headers: { 'x-aether-build-version': 'test-build' } })
|
||||
expect(await requestTraceApi.getRequestTrace('request-1')).toMatchObject({ gateway_version: 'test-build' })
|
||||
getMock.mockResolvedValue({ data: { request_id: 'request-1', candidates: [] } })
|
||||
expect(await requestTraceApi.getRequestTrace('request-1')).toMatchObject({ gateway_version: null })
|
||||
})
|
||||
it('requests opaque body bytes, outside the JSON detail cache', async () => {
|
||||
const bytes = new ArrayBuffer(20)
|
||||
const controller = new AbortController()
|
||||
|
||||
@@ -481,11 +481,12 @@ export const dashboardApi = {
|
||||
return options.signal ? fetchDetail() : cachedRequest(cacheKey, fetchDetail, cacheTtlMs)
|
||||
},
|
||||
|
||||
async getRequestBody(requestId: string, field: RequestBodyField, signal?: AbortSignal) {
|
||||
async getRequestBody(requestId: string, field: RequestBodyField, signal?: AbortSignal, onProgress?: (loaded: number) => void) {
|
||||
const response = await apiClient.get<ArrayBuffer>(`/api/admin/usage/${requestId}`, {
|
||||
params: { include_bodies: true, body_field: field, body_format: 'raw' },
|
||||
responseType: 'arraybuffer',
|
||||
signal,
|
||||
...(onProgress ? { onDownloadProgress: (event: { loaded: number }) => onProgress(event.loaded) } : {}),
|
||||
})
|
||||
const encoding = response.headers['x-aether-body-encoding']
|
||||
if ((encoding !== 'gzip' && encoding !== 'json') || response.headers['x-aether-usage-id'] !== requestId || response.headers['x-aether-body-field'] !== field) {
|
||||
|
||||
@@ -121,6 +121,8 @@ export interface CandidateRecord {
|
||||
}
|
||||
|
||||
export interface RequestTrace {
|
||||
gateway_version?: string | null
|
||||
diagnostic_request?: { usage_id: string, body_state?: string | null } | null
|
||||
request_id: string
|
||||
request_path?: string
|
||||
request_query_string?: string
|
||||
@@ -154,7 +156,7 @@ export const requestTraceApi = {
|
||||
const response = await apiClient.get<RequestTrace>(`/api/admin/monitoring/trace/${requestId}`, {
|
||||
params: { attempted_only: attemptedOnly },
|
||||
})
|
||||
return response.data
|
||||
return { ...response.data, gateway_version: response.headers?.['x-aether-build-version'] ?? response.data.gateway_version ?? null }
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user