mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-01 17:00:21 +08:00
perf(usage): user-me usage 查询避免全量加载,默认限制 7 天范围
- UsageAuditListQuery 新增 limit 字段,支持在 SQL 层 LIMIT - user-me usage 端点无时间范围时默认查最近 7 天 - active usage 端点无 ids 过滤时限制查最近 1 小时 - InMemory 实现同步支持 limit truncate
This commit is contained in:
@@ -26,6 +26,7 @@ pub(crate) async fn list_usage_for_range(
|
|||||||
provider_name: filters.provider_name.clone(),
|
provider_name: filters.provider_name.clone(),
|
||||||
model: filters.model.clone(),
|
model: filters.model.clone(),
|
||||||
statuses: None,
|
statuses: None,
|
||||||
|
limit: None,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@@ -46,6 +47,7 @@ pub(crate) async fn list_usage_for_optional_range(
|
|||||||
provider_name: filters.provider_name.clone(),
|
provider_name: filters.provider_name.clone(),
|
||||||
model: filters.model.clone(),
|
model: filters.model.clone(),
|
||||||
statuses: None,
|
statuses: None,
|
||||||
|
limit: None,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ pub(in super::super) async fn list_recent_completed_usage_for_cache_affinity(
|
|||||||
provider_name: None,
|
provider_name: None,
|
||||||
model: None,
|
model: None,
|
||||||
statuses: None,
|
statuses: None,
|
||||||
|
limit: None,
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
items.retain(|item| item.status == "completed");
|
items.retain(|item| item.status == "completed");
|
||||||
|
|||||||
@@ -486,6 +486,7 @@ async fn dashboard_list_usage_for_range(
|
|||||||
provider_name: None,
|
provider_name: None,
|
||||||
model: None,
|
model: None,
|
||||||
statuses: None,
|
statuses: None,
|
||||||
|
limit: None,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
@@ -1215,6 +1216,7 @@ pub(super) async fn handle_dashboard_provider_status_get(
|
|||||||
provider_name: None,
|
provider_name: None,
|
||||||
model: None,
|
model: None,
|
||||||
statuses: None,
|
statuses: None,
|
||||||
|
limit: None,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -690,9 +690,22 @@ pub(super) async fn handle_users_me_usage_get(
|
|||||||
Err(detail) => return admin_stats_bad_request_response(detail),
|
Err(detail) => return admin_stats_bad_request_response(detail),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// When no time range is specified, default to 7 days to avoid full-table scans.
|
||||||
|
let effective_time_range = time_range.or_else(|| {
|
||||||
|
let today = Utc::now().date_naive();
|
||||||
|
let start_date = today
|
||||||
|
.checked_sub_signed(chrono::Duration::days(6))
|
||||||
|
.unwrap_or(today);
|
||||||
|
Some(AdminStatsTimeRange {
|
||||||
|
start_date,
|
||||||
|
end_date: today,
|
||||||
|
tz_offset_minutes: 0,
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
let usage = match list_usage_for_optional_range(
|
let usage = match list_usage_for_optional_range(
|
||||||
&AdminAppState::new(state),
|
&AdminAppState::new(state),
|
||||||
time_range.as_ref(),
|
effective_time_range.as_ref(),
|
||||||
&AdminStatsUsageFilter {
|
&AdminStatsUsageFilter {
|
||||||
user_id: Some(auth.user.id.clone()),
|
user_id: Some(auth.user.id.clone()),
|
||||||
provider_name: None,
|
provider_name: None,
|
||||||
@@ -872,14 +885,22 @@ pub(super) async fn handle_users_me_usage_active_get(
|
|||||||
Err(response) => return response,
|
Err(response) => return response,
|
||||||
};
|
};
|
||||||
let ids = parse_users_me_usage_ids(request_context.request_query_string.as_deref());
|
let ids = parse_users_me_usage_ids(request_context.request_query_string.as_deref());
|
||||||
|
// When polling for active (pending/streaming) requests without specific ids,
|
||||||
|
// limit to the last 1 hour to avoid scanning all historical records.
|
||||||
|
let created_from = if ids.is_none() {
|
||||||
|
Some(Utc::now().timestamp().saturating_sub(3600) as u64)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
let items = match state
|
let items = match state
|
||||||
.list_usage_audits(&UsageAuditListQuery {
|
.list_usage_audits(&UsageAuditListQuery {
|
||||||
created_from_unix_secs: None,
|
created_from_unix_secs: created_from,
|
||||||
created_until_unix_secs: None,
|
created_until_unix_secs: None,
|
||||||
user_id: Some(auth.user.id.clone()),
|
user_id: Some(auth.user.id.clone()),
|
||||||
provider_name: None,
|
provider_name: None,
|
||||||
model: None,
|
model: None,
|
||||||
statuses: None,
|
statuses: None,
|
||||||
|
limit: None,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
@@ -952,6 +973,7 @@ pub(super) async fn handle_users_me_usage_interval_timeline_get(
|
|||||||
provider_name: None,
|
provider_name: None,
|
||||||
model: None,
|
model: None,
|
||||||
statuses: None,
|
statuses: None,
|
||||||
|
limit: None,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -218,6 +218,7 @@ pub(super) async fn handle_wallet_today_cost(
|
|||||||
provider_name: None,
|
provider_name: None,
|
||||||
model: None,
|
model: None,
|
||||||
statuses: None,
|
statuses: None,
|
||||||
|
limit: None,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -481,6 +481,7 @@ pub struct UsageAuditListQuery {
|
|||||||
pub provider_name: Option<String>,
|
pub provider_name: Option<String>,
|
||||||
pub model: Option<String>,
|
pub model: Option<String>,
|
||||||
pub statuses: Option<Vec<String>>,
|
pub statuses: Option<Vec<String>>,
|
||||||
|
pub limit: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Default, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Default, serde::Serialize, serde::Deserialize)]
|
||||||
|
|||||||
@@ -214,6 +214,9 @@ impl UsageReadRepository for InMemoryUsageReadRepository {
|
|||||||
.cmp(&right.created_at_unix_ms)
|
.cmp(&right.created_at_unix_ms)
|
||||||
.then_with(|| left.request_id.cmp(&right.request_id))
|
.then_with(|| left.request_id.cmp(&right.request_id))
|
||||||
});
|
});
|
||||||
|
if let Some(limit) = query.limit {
|
||||||
|
items.truncate(limit);
|
||||||
|
}
|
||||||
Ok(items)
|
Ok(items)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1213,6 +1213,9 @@ impl SqlxUsageReadRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
builder.push(" ORDER BY \"usage\".created_at ASC, \"usage\".request_id ASC");
|
builder.push(" ORDER BY \"usage\".created_at ASC, \"usage\".request_id ASC");
|
||||||
|
if let Some(limit) = query.limit {
|
||||||
|
builder.push(" LIMIT ").push_bind(limit as i64);
|
||||||
|
}
|
||||||
let query = builder.build();
|
let query = builder.build();
|
||||||
let mut rows = query.fetch(&self.pool);
|
let mut rows = query.fetch(&self.pool);
|
||||||
let mut items = Vec::new();
|
let mut items = Vec::new();
|
||||||
|
|||||||
Reference in New Issue
Block a user