mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-03 01:40:21 +08:00
perf: 并行化 admin 聚合路由并完善前端缓存预取
- gateway: usage detail / provider summary / pool overview / users list 改为 tokio join 并行拉取依赖数据 - usage: interval timeline 支持自动刷新并按查询区间动态展示,取消服务端 120 分钟过滤并在 ScatterChart 统一封顶 - frontend: 新增管理端导航预取工具及 SidebarNav/MainLayout 触发,admin 读接口统一走 cachedRequest 的短期缓存 - dashboard: request detail 支持短 TTL 缓存并在 UsageRecordsTable mousedown 时预取 - data: migrate 测试在 wait_for_postgres 失败时清理子进程,避免遗留
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import client from '../client'
|
||||
import { dedupedRequest, buildCacheKey } from '@/utils/cache'
|
||||
import { buildCacheKey, cachedRequest, dedupedRequest } from '@/utils/cache'
|
||||
import type {
|
||||
GlobalModelCreate,
|
||||
GlobalModelUpdate,
|
||||
@@ -22,17 +22,26 @@ export type {
|
||||
/**
|
||||
* 获取 GlobalModel 列表
|
||||
*/
|
||||
interface GlobalModelListOptions {
|
||||
cacheTtlMs?: number
|
||||
}
|
||||
|
||||
export async function getGlobalModels(params?: {
|
||||
skip?: number
|
||||
limit?: number
|
||||
is_active?: boolean
|
||||
search?: string
|
||||
}): Promise<GlobalModelListResponse> {
|
||||
}, options: GlobalModelListOptions = {}): Promise<GlobalModelListResponse> {
|
||||
const cacheTtlMs = options.cacheTtlMs ?? 0
|
||||
const key = buildCacheKey('global-models:list', params as Record<string, unknown> | undefined)
|
||||
return dedupedRequest(key, async () => {
|
||||
const response = await client.get('/api/admin/models/global', { params })
|
||||
return response.data
|
||||
})
|
||||
return cachedRequest(
|
||||
key,
|
||||
async () => {
|
||||
const response = await client.get('/api/admin/models/global', { params })
|
||||
return response.data
|
||||
},
|
||||
cacheTtlMs,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import client from '../client'
|
||||
import { dedupedRequest } from '@/utils/cache'
|
||||
import { buildCacheKey, cachedRequest } from '@/utils/cache'
|
||||
import type {
|
||||
AllowedModels,
|
||||
OAuthOrganizationInfo,
|
||||
@@ -230,33 +230,59 @@ export interface PoolBatchAction {
|
||||
payload?: Record<string, unknown> | null
|
||||
}
|
||||
|
||||
export async function getPoolOverview(): Promise<PoolOverviewResponse> {
|
||||
return dedupedRequest('pool:overview', async () => {
|
||||
const response = await client.get<PoolOverviewResponse>('/api/admin/pool/overview')
|
||||
return response.data
|
||||
})
|
||||
interface PoolReadOptions {
|
||||
cacheTtlMs?: number
|
||||
}
|
||||
|
||||
export async function getPoolSchedulingPresets(): Promise<PoolPresetMeta[]> {
|
||||
return dedupedRequest('pool:scheduling-presets', async () => {
|
||||
const response = await client.get<PoolPresetMeta[]>('/api/admin/pool/scheduling-presets')
|
||||
return response.data
|
||||
})
|
||||
export async function getPoolOverview(
|
||||
options: PoolReadOptions = {},
|
||||
): Promise<PoolOverviewResponse> {
|
||||
const cacheTtlMs = options.cacheTtlMs ?? 0
|
||||
return cachedRequest(
|
||||
'pool:overview',
|
||||
async () => {
|
||||
const response = await client.get<PoolOverviewResponse>('/api/admin/pool/overview')
|
||||
return response.data
|
||||
},
|
||||
cacheTtlMs,
|
||||
)
|
||||
}
|
||||
|
||||
export async function getPoolSchedulingPresets(
|
||||
options: PoolReadOptions = {},
|
||||
): Promise<PoolPresetMeta[]> {
|
||||
const cacheTtlMs = options.cacheTtlMs ?? 0
|
||||
return cachedRequest(
|
||||
'pool:scheduling-presets',
|
||||
async () => {
|
||||
const response = await client.get<PoolPresetMeta[]>('/api/admin/pool/scheduling-presets')
|
||||
return response.data
|
||||
},
|
||||
cacheTtlMs,
|
||||
)
|
||||
}
|
||||
|
||||
export async function listPoolKeys(
|
||||
providerId: string,
|
||||
params: PoolKeysQuery = {},
|
||||
options: PoolReadOptions = {},
|
||||
): Promise<PoolKeysPageResponse> {
|
||||
const normalizedParams = {
|
||||
...params,
|
||||
quick_selectors: params.quick_selectors?.length ? params.quick_selectors.join(',') : undefined,
|
||||
}
|
||||
const key = `pool:keys:${providerId}|${normalizedParams.page ?? ''}|${normalizedParams.page_size ?? ''}|${normalizedParams.search ?? ''}|${normalizedParams.status ?? ''}|${normalizedParams.quick_selectors ?? ''}|${normalizedParams.search_scope ?? ''}`
|
||||
return dedupedRequest(key, async () => {
|
||||
const response = await client.get<PoolKeysPageResponse>(`/api/admin/pool/${providerId}/keys`, { params: normalizedParams })
|
||||
return response.data
|
||||
})
|
||||
const cacheKey = buildCacheKey(
|
||||
`pool:keys:${providerId}`,
|
||||
normalizedParams as Record<string, unknown>,
|
||||
)
|
||||
return cachedRequest(
|
||||
cacheKey,
|
||||
async () => {
|
||||
const response = await client.get<PoolKeysPageResponse>(`/api/admin/pool/${providerId}/keys`, { params: normalizedParams })
|
||||
return response.data
|
||||
},
|
||||
options.cacheTtlMs ?? 0,
|
||||
)
|
||||
}
|
||||
|
||||
export async function resolvePoolKeySelection(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import client from '../client'
|
||||
import { dedupedRequest } from '@/utils/cache'
|
||||
import { buildCacheKey, cachedRequest, dedupedRequest } from '@/utils/cache'
|
||||
import type {
|
||||
ClaudeCodeAdvancedConfig,
|
||||
FailoverRulesConfig,
|
||||
@@ -13,6 +13,11 @@ interface ProviderRequestOptions {
|
||||
timeout?: number
|
||||
}
|
||||
|
||||
interface ProviderReadOptions {
|
||||
timeout?: number
|
||||
cacheTtlMs?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 Providers 摘要(分页)
|
||||
*/
|
||||
@@ -43,15 +48,27 @@ function normalizeProviderSummary(
|
||||
|
||||
export async function getProvidersSummary(
|
||||
params: ProviderSummaryQuery = {},
|
||||
options: ProviderReadOptions = {},
|
||||
): Promise<ProviderSummaryPageResponse> {
|
||||
const response = await client.get<ProviderSummaryPageResponse>(
|
||||
'/api/admin/providers/summary',
|
||||
{ params },
|
||||
const cacheTtlMs = options.cacheTtlMs ?? 0
|
||||
const cacheKey = buildCacheKey('providers:summary', params as Record<string, unknown>)
|
||||
return cachedRequest(
|
||||
cacheKey,
|
||||
async () => {
|
||||
const response = await client.get<ProviderSummaryPageResponse>(
|
||||
'/api/admin/providers/summary',
|
||||
{
|
||||
params,
|
||||
timeout: options.timeout,
|
||||
},
|
||||
)
|
||||
return {
|
||||
...response.data,
|
||||
items: response.data.items.map(normalizeProviderSummary),
|
||||
}
|
||||
},
|
||||
cacheTtlMs,
|
||||
)
|
||||
return {
|
||||
...response.data,
|
||||
items: response.data.items.map(normalizeProviderSummary),
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user