Add provider key cycle stats reset handling

This commit is contained in:
fawney19
2026-05-07 03:23:20 +08:00
parent 6c0ac2e8da
commit 10e679bb2f
35 changed files with 1443 additions and 273 deletions
@@ -189,7 +189,7 @@ describe('poolTrace', () => {
expect(isAttemptedCandidate(buildCandidate({ status: 'unused' }))).toBe(false)
})
it('shows only attempted pool children when attempted nodes exist', () => {
it('keeps skipped pool children visible when attempted nodes exist', () => {
const attempts = buildPoolGroupVisibleAttempts([
buildCandidate({
id: 'cand-skipped',
@@ -210,10 +210,10 @@ describe('poolTrace', () => {
}),
])
expect(attempts.map(item => item.id)).toEqual(['cand-failed', 'cand-success'])
expect(attempts.map(item => item.id)).toEqual(['cand-skipped', 'cand-failed', 'cand-success'])
})
it('collapses all-skipped pool nodes to a single provider node', () => {
it('keeps all skipped pool children visible', () => {
const attempts = buildPoolGroupVisibleAttempts([
buildCandidate({
id: 'cand-skipped-1',
@@ -227,6 +227,6 @@ describe('poolTrace', () => {
}),
])
expect(attempts.map(item => item.id)).toEqual(['cand-skipped-2'])
expect(attempts.map(item => item.id)).toEqual(['cand-skipped-1', 'cand-skipped-2'])
})
})
@@ -91,12 +91,19 @@ describe('usage status helpers', () => {
expect(isUsageRecordFailed(record)).toBe(true)
})
it('treats explicit success status code as authoritative for the timeline', () => {
it('prefers terminal request lifecycle status over status code for the timeline', () => {
expect(resolveTimelineFinalStatus({
traceFinalStatus: 'success',
requestStatus: 'failed',
statusCode: 200,
})).toBe('success')
})).toBe('failed')
})
it('prefers terminal trace status over status code when request lifecycle is absent', () => {
expect(resolveTimelineFinalStatus({
traceFinalStatus: 'failed',
statusCode: 200,
})).toBe('failed')
})
it('falls back to request lifecycle status when status code and trace are missing', () => {
@@ -68,14 +68,7 @@ export const isAttemptedCandidate = (
export function buildPoolGroupVisibleAttempts(
attempts: CandidateRecord[],
): CandidateRecord[] {
if (attempts.length === 0) return []
const attempted = attempts.filter(isAttemptedCandidate)
if (attempted.length > 0) {
return attempted
}
return [attempts[attempts.length - 1]]
return attempts.filter(isPoolParticipatedCandidate)
}
export const parseTimelineStatus = (value: unknown): CandidateRecord['status'] | null => {
+5 -5
View File
@@ -272,8 +272,9 @@ export function resolveTimelineFinalStatus(params: {
requestStatus?: RequestStatusLike
statusCode?: number
}): TimelineFinalStatus {
if (typeof params.statusCode === 'number') {
return params.statusCode >= 200 && params.statusCode < 400 ? 'success' : 'failed'
const requestStatus = mapRequestStatusToTimelineStatus(params.requestStatus)
if (requestStatus === 'success' || requestStatus === 'failed' || requestStatus === 'cancelled') {
return requestStatus
}
const traceStatus = normalizeTimelineFinalStatus(params.traceFinalStatus)
@@ -281,9 +282,8 @@ export function resolveTimelineFinalStatus(params: {
return traceStatus
}
const requestStatus = mapRequestStatusToTimelineStatus(params.requestStatus)
if (requestStatus === 'success' || requestStatus === 'failed' || requestStatus === 'cancelled') {
return requestStatus
if (typeof params.statusCode === 'number') {
return params.statusCode >= 200 && params.statusCode < 400 ? 'success' : 'failed'
}
if (params.hasPendingCandidates) {