refactor: 拆分 gateway 单体为独立 crate,新增 systemd 部署方案

将 gateway 内部的 model-fetch、provider-transport、scheduler-core、
usage-runtime、video-tasks-core 模块提取为独立 crate;重构 gateway
内部模块结构(state/router/cache/data/query 等);移除大量遗留模块
文件;新增 systemd 二进制部署骨架及相关文档;更新前端 usage 相关
API 和组件。
This commit is contained in:
fawney19
2026-04-05 20:23:16 +08:00
parent cbc811f6ce
commit 763ff03a7b
777 changed files with 42659 additions and 21469 deletions

View File

@@ -3,12 +3,13 @@ use aether_wallet::{
WalletAccessDecision, WalletAccessFailure, WalletLimitMode, WalletSnapshot, WalletStatus,
};
use crate::gateway::gateway_data::StoredGatewayAuthApiKeySnapshot;
use crate::gateway::{AppState, GatewayError, GatewayLocalAuthRejection};
use crate::control::GatewayLocalAuthRejection;
use crate::data::auth::GatewayAuthApiKeySnapshot;
use crate::{AppState, GatewayError};
pub(crate) async fn resolve_wallet_auth_gate(
state: &AppState,
auth_snapshot: &StoredGatewayAuthApiKeySnapshot,
auth_snapshot: &GatewayAuthApiKeySnapshot,
) -> Result<Option<WalletAccessDecision>, GatewayError> {
if !state.has_wallet_data_reader() {
return Ok(None);
@@ -65,7 +66,7 @@ mod tests {
use aether_wallet::{WalletAccessFailure, WalletLimitMode, WalletSnapshot, WalletStatus};
use super::{local_rejection_from_wallet_access, map_wallet_snapshot};
use crate::gateway::GatewayLocalAuthRejection;
use crate::control::GatewayLocalAuthRejection;
#[test]
fn maps_wallet_snapshot_and_derives_balance_denied() {

View File

@@ -1,7 +1,5 @@
mod access;
mod quota;
mod runtime;
pub(crate) use access::{local_rejection_from_wallet_access, resolve_wallet_auth_gate};
pub(crate) use quota::spawn_provider_quota_reset_worker;
pub(crate) use runtime::settle_usage_if_needed;

View File

@@ -3,7 +3,7 @@ use std::time::Duration;
use tracing::warn;
use crate::gateway::gateway_data::GatewayDataState;
use crate::data::GatewayDataState;
const QUOTA_RESET_INTERVAL: Duration = Duration::from_secs(60 * 60);
@@ -50,7 +50,7 @@ mod tests {
};
use super::{reset_due_provider_quotas_once, spawn_provider_quota_reset_worker};
use crate::gateway::gateway_data::GatewayDataState;
use crate::data::GatewayDataState;
#[tokio::test]
async fn resets_due_provider_quotas_from_runtime() {

View File

@@ -1,44 +0,0 @@
use aether_data::repository::usage::StoredRequestUsageAudit;
use aether_data::repository::wallet::UsageSettlementInput;
use aether_data::{DataLayerError, DataLayerError::InvalidInput};
use crate::gateway::gateway_data::GatewayDataState;
pub(crate) async fn settle_usage_if_needed(
data: &GatewayDataState,
usage: &StoredRequestUsageAudit,
) -> Result<(), DataLayerError> {
if !data.has_wallet_writer() || usage.billing_status != "pending" {
return Ok(());
}
if !matches!(usage.status.as_str(), "completed" | "failed" | "cancelled") {
return Ok(());
}
let finalized_at_unix_secs = usage
.finalized_at_unix_secs
.or(Some(usage.updated_at_unix_secs));
let input = UsageSettlementInput {
request_id: usage.request_id.clone(),
user_id: usage.user_id.clone(),
api_key_id: usage.api_key_id.clone(),
provider_id: usage.provider_id.clone(),
status: usage.status.clone(),
billing_status: usage.billing_status.clone(),
total_cost_usd: finite_cost(usage.total_cost_usd)?,
actual_total_cost_usd: finite_cost(usage.actual_total_cost_usd)?,
finalized_at_unix_secs,
};
let _ = data.settle_usage(input).await?;
Ok(())
}
fn finite_cost(value: f64) -> Result<f64, DataLayerError> {
if value.is_finite() {
Ok(value)
} else {
Err(InvalidInput(
"wallet settlement cost must be finite".to_string(),
))
}
}