Files
Aether/apps/aether-gateway/src/maintenance/runtime/config.rs
T
fawney19 b0b40c16ff feat: 全栈功能增强 - 扩展 provider/pool 管理、完善调度与数据层、重构前端 Pool 页面
后端:
- 扩展 pool_admin payloads 和 provider query models,增强 endpoint key 管理
- 完善 scheduler-core 候选排序与请求候选逻辑
- 增强 usage-runtime 写入、provider-transport 网络层与 OAuth 刷新
- 改进 AI pipeline 响应转换与流式处理
- 扩展 global_models/provider_catalog 数据层查询能力
- 增强 video-tasks-core 多 provider 支持
- 新增大量集成测试覆盖 pool/keys/provider_query/frontdoor

前端:
- 重构 PoolManagement 页面,拆分状态管理/对话框逻辑到独立模块
- 新增 poolAdvancedDialog/poolSchedulingDialog/poolManagementState/poolMobilePresentation 工具函数及测试
- 改进 Dialog 组件与 provider tabs 显示

部署:
- 更新 Rust CI workflow 和 Dockerfile 构建配置

Closes #275
Co-authored-by: AAEE86 <[email protected]>
2026-04-09 13:51:50 +08:00

123 lines
4.1 KiB
Rust

use aether_data_contracts::DataLayerError;
use chrono::{DateTime, Utc};
use serde_json::Value;
use crate::data::GatewayDataState;
use super::{UsageCleanupSettings, UsageCleanupWindow};
pub(super) async fn system_config_bool(
data: &GatewayDataState,
key: &str,
default: bool,
) -> Result<bool, DataLayerError> {
Ok(match data.find_system_config_value(key).await? {
Some(Value::Bool(value)) => value,
Some(Value::Number(value)) => value.as_i64().map(|raw| raw != 0).unwrap_or(default),
Some(Value::String(value)) => match value.trim().to_ascii_lowercase().as_str() {
"true" | "1" | "yes" | "on" => true,
"false" | "0" | "no" | "off" => false,
_ => default,
},
_ => default,
})
}
pub(super) async fn system_config_u64(
data: &GatewayDataState,
key: &str,
default: u64,
) -> Result<u64, DataLayerError> {
Ok(match data.find_system_config_value(key).await? {
Some(Value::Number(value)) => value
.as_u64()
.or_else(|| value.as_i64().and_then(|raw| u64::try_from(raw).ok()))
.unwrap_or(default),
Some(Value::String(value)) => value.trim().parse::<u64>().unwrap_or(default),
_ => default,
})
}
pub(super) async fn system_config_usize(
data: &GatewayDataState,
key: &str,
default: usize,
) -> Result<usize, DataLayerError> {
Ok(match data.find_system_config_value(key).await? {
Some(Value::Number(value)) => value
.as_u64()
.and_then(|raw| usize::try_from(raw).ok())
.or_else(|| {
value
.as_i64()
.and_then(|raw| u64::try_from(raw).ok())
.and_then(|raw| usize::try_from(raw).ok())
})
.unwrap_or(default),
Some(Value::String(value)) => value.trim().parse::<usize>().unwrap_or(default),
_ => default,
})
}
pub(super) async fn system_config_string(
data: &GatewayDataState,
key: &str,
default: &str,
) -> Result<String, DataLayerError> {
Ok(match data.find_system_config_value(key).await? {
Some(Value::String(value)) => {
let trimmed = value.trim();
if trimmed.is_empty() {
default.to_string()
} else {
trimmed.to_string()
}
}
_ => default.to_string(),
})
}
pub(super) async fn pending_cleanup_timeout_minutes(
data: &GatewayDataState,
) -> Result<u64, DataLayerError> {
system_config_u64(data, "pending_request_timeout_minutes", 10).await
}
pub(super) async fn pending_cleanup_batch_size(
data: &GatewayDataState,
) -> Result<usize, DataLayerError> {
Ok(system_config_usize(data, "cleanup_batch_size", 1_000)
.await?
.clamp(1, 200))
}
pub(super) async fn usage_cleanup_settings(
data: &GatewayDataState,
) -> Result<UsageCleanupSettings, DataLayerError> {
Ok(UsageCleanupSettings {
detail_retention_days: system_config_u64(data, "detail_log_retention_days", 7).await?,
compressed_retention_days: system_config_u64(data, "compressed_log_retention_days", 30)
.await?,
header_retention_days: system_config_u64(data, "header_retention_days", 90).await?,
log_retention_days: system_config_u64(data, "log_retention_days", 365).await?,
batch_size: system_config_usize(data, "cleanup_batch_size", 1_000)
.await?
.max(1),
auto_delete_expired_keys: system_config_bool(data, "auto_delete_expired_keys", false)
.await?,
})
}
pub(super) fn usage_cleanup_window(
now_utc: DateTime<Utc>,
settings: UsageCleanupSettings,
) -> UsageCleanupWindow {
let minutes = |days: u64| chrono::Duration::days(i64::try_from(days).unwrap_or(i64::MAX));
UsageCleanupWindow {
detail_cutoff: now_utc - minutes(settings.detail_retention_days),
compressed_cutoff: now_utc - minutes(settings.compressed_retention_days),
header_cutoff: now_utc - minutes(settings.header_retention_days),
log_cutoff: now_utc - minutes(settings.log_retention_days),
}
}