refactor(runtime): 优化管理端摘要查询与维护聚合链路

- 为 provider catalog key 和 video task 列表增加 summary/page 查询与排序能力,减少列表场景读取重字段
- 将多处 SQL 结果读取改为流式收集,降低 `fetch_all` 的内存占用
- 把日/小时统计、钱包日用量等维护任务改为数据库侧 `CTE + upsert` 聚合
- 修复视频任务轮询更新时从本地 snapshot 回填稀疏字段,避免 `prompt` 和请求体信息丢失
This commit is contained in:
AAEE86
2026-04-12 20:45:47 +08:00
committed by fawney19
parent 6aa16ec792
commit b2d85d70ca
55 changed files with 1954 additions and 1382 deletions

View File

@@ -1,4 +1,5 @@
use async_trait::async_trait;
use futures_util::TryStreamExt;
use sqlx::{PgPool, Postgres, QueryBuilder, Row};
use super::types::{
@@ -189,30 +190,31 @@ impl SqlxUserReadRepository {
if user_ids.is_empty() {
return Ok(Vec::new());
}
let rows = sqlx::query(LIST_USERS_BY_IDS_SQL)
.bind(user_ids)
.fetch_all(&self.pool)
.await
.map_postgres_err()?;
rows.iter().map(map_user_row).collect()
collect_query_rows(
sqlx::query(LIST_USERS_BY_IDS_SQL)
.bind(user_ids)
.fetch(&self.pool),
map_user_row,
)
.await
}
pub async fn list_non_admin_export_users(
&self,
) -> Result<Vec<StoredUserExportRow>, DataLayerError> {
let rows = sqlx::query(LIST_NON_ADMIN_EXPORT_USERS_SQL)
.fetch_all(&self.pool)
.await
.map_postgres_err()?;
rows.iter().map(map_user_export_row).collect()
collect_query_rows(
sqlx::query(LIST_NON_ADMIN_EXPORT_USERS_SQL).fetch(&self.pool),
map_user_export_row,
)
.await
}
pub async fn list_export_users(&self) -> Result<Vec<StoredUserExportRow>, DataLayerError> {
let rows = sqlx::query(LIST_EXPORT_USERS_SQL)
.fetch_all(&self.pool)
.await
.map_postgres_err()?;
rows.iter().map(map_user_export_row).collect()
collect_query_rows(
sqlx::query(LIST_EXPORT_USERS_SQL).fetch(&self.pool),
map_user_export_row,
)
.await
}
pub async fn list_export_users_page(
@@ -240,12 +242,8 @@ impl SqlxUserReadRepository {
DataLayerError::InvalidInput(format!("invalid user export limit: {}", query.limit))
})?);
let rows = builder
.build()
.fetch_all(&self.pool)
.await
.map_postgres_err()?;
rows.iter().map(map_user_export_row).collect()
let query = builder.build();
collect_query_rows(query.fetch(&self.pool), map_user_export_row).await
}
pub async fn summarize_export_users(&self) -> Result<UserExportSummary, DataLayerError> {
@@ -279,12 +277,13 @@ impl SqlxUserReadRepository {
return Ok(Vec::new());
}
let rows = sqlx::query(LIST_USER_AUTH_BY_IDS_SQL)
.bind(user_ids)
.fetch_all(&self.pool)
.await
.map_postgres_err()?;
rows.iter().map(map_user_auth_row).collect()
collect_query_rows(
sqlx::query(LIST_USER_AUTH_BY_IDS_SQL)
.bind(user_ids)
.fetch(&self.pool),
map_user_auth_row,
)
.await
}
pub async fn find_user_auth_by_id(
@@ -361,6 +360,20 @@ fn map_user_auth_row(row: &sqlx::postgres::PgRow) -> Result<StoredUserAuthRecord
)
}
async fn collect_query_rows<T, S>(
mut rows: S,
mapper: fn(&sqlx::postgres::PgRow) -> Result<T, DataLayerError>,
) -> Result<Vec<T>, DataLayerError>
where
S: futures_util::TryStream<Ok = sqlx::postgres::PgRow, Error = sqlx::Error> + Unpin,
{
let mut items = Vec::new();
while let Some(row) = rows.try_next().await.map_postgres_err()? {
items.push(mapper(&row)?);
}
Ok(items)
}
#[async_trait]
impl UserReadRepository for SqlxUserReadRepository {
async fn list_users_by_ids(