fix(usage): session touch 独立提交避免行锁阻塞 & 管理员页面顺序加载降低并发压力

后端: 将 session touch 的 commit 从请求事务中分离,防止管理员 usage
页面的长查询持有 user_sessions 行锁阻塞后续请求。touch_session 改为
返回 bool 以支持按需提交。

前端: 管理员 Usage 页面将并行 API 调用改为顺序加载,优先显示记录表格,
统计面板在后台异步刷新,避免瞬时并发打满后端 worker。loadRecords 支持
传入 dateRange 参数确保时间范围一致性。
This commit is contained in:
fawney19
2026-03-18 00:12:00 +08:00
parent eeb5f41bad
commit 684689a82b
6 changed files with 373 additions and 57 deletions

View File

@@ -77,13 +77,8 @@ export function useUsageData(options: UseUsageDataOptions) {
try {
if (isAdminPage.value) {
// 管理员页面,并行加载统计数据
const [statsData, modelData, providerData, apiFormatData] = await Promise.all([
usageApi.getUsageStats(dateRange),
usageApi.getUsageByModel(dateRange),
usageApi.getUsageByProvider(dateRange),
usageApi.getUsageByApiFormat(dateRange)
])
// 管理员页面顺序加载统计数据,避免刷新使用记录时瞬时打满后端 worker。
const statsData = await usageApi.getUsageStats(dateRange)
if (requestId !== loadStatsRequestId) {
return
@@ -104,6 +99,11 @@ export function useUsageData(options: UseUsageDataOptions) {
period_end: '',
}
const modelData = await usageApi.getUsageByModel(dateRange)
if (requestId !== loadStatsRequestId) {
return
}
modelStats.value = modelData.map(item => {
const raw = item as Record<string, unknown>
return {
@@ -120,6 +120,11 @@ export function useUsageData(options: UseUsageDataOptions) {
}
})
const providerData = await usageApi.getUsageByProvider(dateRange)
if (requestId !== loadStatsRequestId) {
return
}
providerStats.value = providerData.map(item => ({
provider: item.provider,
requests: item.request_count,
@@ -137,6 +142,11 @@ export function useUsageData(options: UseUsageDataOptions) {
: '-'
}))
const apiFormatData = await usageApi.getUsageByApiFormat(dateRange)
if (requestId !== loadStatsRequestId) {
return
}
apiFormatStats.value = apiFormatData.map(item => ({
api_format: item.api_format,
request_count: item.request_count || 0,
@@ -255,19 +265,24 @@ export function useUsageData(options: UseUsageDataOptions) {
// 加载记录(真正的后端分页)
async function loadRecords(
pagination: PaginationParams,
filters?: FilterParams
filters?: FilterParams,
dateRange?: DateRangeParams
): Promise<void> {
const requestId = ++loadRecordsRequestId
isLoadingRecords.value = true
try {
const offset = (pagination.page - 1) * pagination.pageSize
const effectiveDateRange = dateRange ?? currentDateRange.value
if (dateRange) {
currentDateRange.value = dateRange
}
// 构建请求参数
const params: Record<string, unknown> = {
limit: pagination.pageSize,
offset,
...currentDateRange.value
...effectiveDateRange
}
// 添加筛选条件