mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-03 09:50:21 +08:00
perf: 全栈查询优化、前端缓存去重与页面可见性优化
后端: - SQL count 查询统一改用 func.count() 子查询替代 query.count() - Dashboard/Audit 等页面多次独立查询合并为单次聚合查询 - Provider summary 列表改为批量查询消除 N+1 问题 - DailyStats 逐天循环查询改为 CASE 分桶单次查询 - 使用 load_only() 减少不必要的列加载 - cache_decorator 支持嵌套属性路径解析(dotted vary_by) - 多个管理/公共端点新增 @cache_result 缓存装饰 前端: - cache.ts 新增 in-flight 请求复用、dedupedRequest、buildCacheKey - 大量 API 调用添加前端缓存或去重 - 多个页面定时器在标签页隐藏时暂停、可见时恢复 - Auth 检查从 setInterval 改为 storage + visibilitychange 事件驱动 - 请求竞态防护(requestId 模式) 数据库: - Usage 表新增 idx_usage_status_user_created 复合索引
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import client from '../client'
|
||||
import { dedupedRequest, buildCacheKey } from '@/utils/cache'
|
||||
import type {
|
||||
GlobalModelCreate,
|
||||
GlobalModelUpdate,
|
||||
@@ -27,16 +28,21 @@ export async function getGlobalModels(params?: {
|
||||
is_active?: boolean
|
||||
search?: string
|
||||
}): Promise<GlobalModelListResponse> {
|
||||
const response = await client.get('/api/admin/models/global', { params })
|
||||
return response.data
|
||||
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
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单个 GlobalModel 详情
|
||||
*/
|
||||
export async function getGlobalModel(id: string): Promise<GlobalModelWithStats> {
|
||||
const response = await client.get(`/api/admin/models/global/${id}`)
|
||||
return response.data
|
||||
return dedupedRequest(`global-models:detail:${id}`, async () => {
|
||||
const response = await client.get(`/api/admin/models/global/${id}`)
|
||||
return response.data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,10 +118,12 @@ export async function getGlobalModelProviders(globalModelId: string): Promise<{
|
||||
providers: ModelCatalogProviderDetail[]
|
||||
total: number
|
||||
}> {
|
||||
const response = await client.get(
|
||||
`/api/admin/models/global/${globalModelId}/providers`
|
||||
)
|
||||
return response.data
|
||||
return dedupedRequest(`global-models:providers:${globalModelId}`, async () => {
|
||||
const response = await client.get(
|
||||
`/api/admin/models/global/${globalModelId}/providers`
|
||||
)
|
||||
return response.data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import client from '../client'
|
||||
import { dedupedRequest } from '@/utils/cache'
|
||||
import type { AllowedModels, ProxyConfig } from './types/provider'
|
||||
|
||||
export interface PoolKeyStatus {
|
||||
@@ -175,16 +176,21 @@ export interface PoolBatchAction {
|
||||
}
|
||||
|
||||
export async function getPoolOverview(): Promise<PoolOverviewResponse> {
|
||||
const response = await client.get('/api/admin/pool/overview')
|
||||
return response.data
|
||||
return dedupedRequest('pool:overview', async () => {
|
||||
const response = await client.get<PoolOverviewResponse>('/api/admin/pool/overview')
|
||||
return response.data
|
||||
})
|
||||
}
|
||||
|
||||
export async function listPoolKeys(
|
||||
providerId: string,
|
||||
params: PoolKeysQuery = {},
|
||||
): Promise<PoolKeysPageResponse> {
|
||||
const response = await client.get(`/api/admin/pool/${providerId}/keys`, { params })
|
||||
return response.data
|
||||
const key = `pool:keys:${providerId}|${params.page ?? ''}|${params.page_size ?? ''}|${params.search ?? ''}|${params.status ?? ''}`
|
||||
return dedupedRequest(key, async () => {
|
||||
const response = await client.get<PoolKeysPageResponse>(`/api/admin/pool/${providerId}/keys`, { params })
|
||||
return response.data
|
||||
})
|
||||
}
|
||||
|
||||
export async function batchActionPoolKeys(
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import client from '../client'
|
||||
import { dedupedRequest } from '@/utils/cache'
|
||||
import type {
|
||||
ClaudeCodeAdvancedConfig,
|
||||
FailoverRulesConfig,
|
||||
@@ -11,16 +12,20 @@ import type {
|
||||
* 获取 Providers 摘要(包含 Endpoints 统计)
|
||||
*/
|
||||
export async function getProvidersSummary(): Promise<ProviderWithEndpointsSummary[]> {
|
||||
const response = await client.get('/api/admin/providers/summary')
|
||||
return response.data
|
||||
return dedupedRequest('providers:summary', async () => {
|
||||
const response = await client.get<ProviderWithEndpointsSummary[]>('/api/admin/providers/summary')
|
||||
return response.data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单个 Provider 的详细信息
|
||||
*/
|
||||
export async function getProvider(providerId: string): Promise<ProviderWithEndpointsSummary> {
|
||||
const response = await client.get(`/api/admin/providers/${providerId}/summary`)
|
||||
return response.data
|
||||
return dedupedRequest(`providers:detail:${providerId}`, async () => {
|
||||
const response = await client.get<ProviderWithEndpointsSummary>(`/api/admin/providers/${providerId}/summary`)
|
||||
return response.data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -214,6 +219,8 @@ export interface ProviderMappingPreviewResponse {
|
||||
export async function getProviderMappingPreview(
|
||||
providerId: string
|
||||
): Promise<ProviderMappingPreviewResponse> {
|
||||
const response = await client.get(`/api/admin/providers/${providerId}/mapping-preview`)
|
||||
return response.data
|
||||
return dedupedRequest(`providers:mapping-preview:${providerId}`, async () => {
|
||||
const response = await client.get<ProviderMappingPreviewResponse>(`/api/admin/providers/${providerId}/mapping-preview`)
|
||||
return response.data
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user