mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-03 01:40:21 +08:00
refactor: 大规模模块拆分与代码精简,新增 ai-pipeline/data-contracts 独立 crate
- 新增 aether-ai-pipeline 和 aether-data-contracts crate,将 pipeline 逻辑与数据契约从 gateway 中解耦 - 重构 admin handlers:拆分单体模块为 auth/billing/endpoint/features/model/observability/provider/system 等独立子模块 - 合并 chat/cli 重复代码路径:精简 conversion、finalize、planner 中的 sync/chat/cli 分支 - 重构 scheduler/executor/data 层,引入 facade 模式降低模块间耦合 - 移除冗余的 intent 模块,将 plan_fallback/policy/stream_path/sync_path 迁移至 executor - 前端适配:调整 admin API 调用和 provider 模型测试对话框
This commit is contained in:
@@ -1,141 +0,0 @@
|
||||
use crate::{scheduler, AppState, GatewayError};
|
||||
use aether_data::repository::audit::RequestAuditBundle;
|
||||
use aether_data::repository::usage::StoredRequestUsageAudit;
|
||||
|
||||
use super::super::{AUTH_API_KEY_LAST_USED_MAX_ENTRIES, AUTH_API_KEY_LAST_USED_TTL};
|
||||
|
||||
impl AppState {
|
||||
pub(crate) async fn read_request_candidate_trace(
|
||||
&self,
|
||||
request_id: &str,
|
||||
attempted_only: bool,
|
||||
) -> Result<Option<crate::data::candidates::RequestCandidateTrace>, GatewayError>
|
||||
{
|
||||
self.data
|
||||
.read_request_candidate_trace(request_id, attempted_only)
|
||||
.await
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))
|
||||
}
|
||||
|
||||
pub(crate) async fn read_decision_trace(
|
||||
&self,
|
||||
request_id: &str,
|
||||
attempted_only: bool,
|
||||
) -> Result<Option<crate::data::decision_trace::DecisionTrace>, GatewayError>
|
||||
{
|
||||
self.data
|
||||
.read_decision_trace(request_id, attempted_only)
|
||||
.await
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))
|
||||
}
|
||||
|
||||
pub(crate) async fn read_request_usage_audit(
|
||||
&self,
|
||||
request_id: &str,
|
||||
) -> Result<Option<StoredRequestUsageAudit>, GatewayError> {
|
||||
self.data
|
||||
.read_request_usage_audit(request_id)
|
||||
.await
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))
|
||||
}
|
||||
|
||||
pub(crate) async fn find_request_usage_by_id(
|
||||
&self,
|
||||
usage_id: &str,
|
||||
) -> Result<Option<aether_data::repository::usage::StoredRequestUsageAudit>, GatewayError> {
|
||||
self.data
|
||||
.find_request_usage_by_id(usage_id)
|
||||
.await
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))
|
||||
}
|
||||
|
||||
pub(crate) async fn read_request_audit_bundle(
|
||||
&self,
|
||||
request_id: &str,
|
||||
attempted_only: bool,
|
||||
now_unix_secs: u64,
|
||||
) -> Result<Option<RequestAuditBundle>, GatewayError> {
|
||||
self.data
|
||||
.read_request_audit_bundle(request_id, attempted_only, now_unix_secs)
|
||||
.await
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))
|
||||
}
|
||||
|
||||
pub(crate) async fn read_auth_api_key_snapshot(
|
||||
&self,
|
||||
user_id: &str,
|
||||
api_key_id: &str,
|
||||
now_unix_secs: u64,
|
||||
) -> Result<Option<crate::data::auth::GatewayAuthApiKeySnapshot>, GatewayError>
|
||||
{
|
||||
self.data
|
||||
.read_auth_api_key_snapshot(user_id, api_key_id, now_unix_secs)
|
||||
.await
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))
|
||||
}
|
||||
|
||||
pub(crate) async fn read_auth_api_key_snapshot_by_key_hash(
|
||||
&self,
|
||||
key_hash: &str,
|
||||
now_unix_secs: u64,
|
||||
) -> Result<Option<crate::data::auth::GatewayAuthApiKeySnapshot>, GatewayError>
|
||||
{
|
||||
self.data
|
||||
.read_auth_api_key_snapshot_by_key_hash(key_hash, now_unix_secs)
|
||||
.await
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))
|
||||
}
|
||||
|
||||
pub(crate) async fn read_auth_api_key_snapshots_by_ids(
|
||||
&self,
|
||||
api_key_ids: &[String],
|
||||
) -> Result<Vec<aether_data::repository::auth::StoredAuthApiKeySnapshot>, GatewayError> {
|
||||
self.data
|
||||
.list_auth_api_key_snapshots_by_ids(api_key_ids)
|
||||
.await
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))
|
||||
}
|
||||
|
||||
pub(crate) fn has_auth_api_key_writer(&self) -> bool {
|
||||
self.data.has_auth_api_key_writer()
|
||||
}
|
||||
|
||||
pub(crate) async fn touch_auth_api_key_last_used_best_effort(&self, api_key_id: &str) {
|
||||
let api_key_id = api_key_id.trim();
|
||||
if api_key_id.is_empty() || !self.has_auth_api_key_writer() {
|
||||
return;
|
||||
}
|
||||
if !self.auth_api_key_last_used_cache.should_touch(
|
||||
api_key_id,
|
||||
AUTH_API_KEY_LAST_USED_TTL,
|
||||
AUTH_API_KEY_LAST_USED_MAX_ENTRIES,
|
||||
) {
|
||||
return;
|
||||
}
|
||||
if let Err(err) = self.data.touch_auth_api_key_last_used(api_key_id).await {
|
||||
tracing::warn!(
|
||||
api_key_id = %api_key_id,
|
||||
error = ?err,
|
||||
"gateway auth api key last_used_at touch failed"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn read_minimal_candidate_selection(
|
||||
&self,
|
||||
api_format: &str,
|
||||
global_model_name: &str,
|
||||
require_streaming: bool,
|
||||
auth_snapshot: Option<&crate::data::auth::GatewayAuthApiKeySnapshot>,
|
||||
) -> Result<Vec<scheduler::GatewayMinimalCandidateSelectionCandidate>, GatewayError> {
|
||||
scheduler::read_minimal_candidate_selection(
|
||||
self.data.as_ref(),
|
||||
api_format,
|
||||
global_model_name,
|
||||
require_streaming,
|
||||
auth_snapshot,
|
||||
)
|
||||
.await
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))
|
||||
}
|
||||
}
|
||||
26
apps/aether-gateway/src/state/runtime/auth/api_keys.rs
Normal file
26
apps/aether-gateway/src/state/runtime/auth/api_keys.rs
Normal file
@@ -0,0 +1,26 @@
|
||||
use crate::AppState;
|
||||
|
||||
use super::super::super::{AUTH_API_KEY_LAST_USED_MAX_ENTRIES, AUTH_API_KEY_LAST_USED_TTL};
|
||||
|
||||
impl AppState {
|
||||
pub(crate) async fn touch_auth_api_key_last_used_best_effort(&self, api_key_id: &str) {
|
||||
let api_key_id = api_key_id.trim();
|
||||
if api_key_id.is_empty() || !self.data.has_auth_api_key_writer() {
|
||||
return;
|
||||
}
|
||||
if !self.auth_api_key_last_used_cache.should_touch(
|
||||
api_key_id,
|
||||
AUTH_API_KEY_LAST_USED_TTL,
|
||||
AUTH_API_KEY_LAST_USED_MAX_ENTRIES,
|
||||
) {
|
||||
return;
|
||||
}
|
||||
if let Err(err) = self.data.touch_auth_api_key_last_used(api_key_id).await {
|
||||
tracing::warn!(
|
||||
api_key_id = %api_key_id,
|
||||
error = ?err,
|
||||
"gateway auth api key last_used_at touch failed"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
mod api_keys;
|
||||
mod sessions;
|
||||
mod user_lifecycle;
|
||||
mod user_provisioning;
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
use crate::{AppState, GatewayError};
|
||||
use crate::{AppState, GatewayError, GatewayUserSessionView};
|
||||
|
||||
impl AppState {
|
||||
pub(crate) async fn find_user_session(
|
||||
&self,
|
||||
user_id: &str,
|
||||
session_id: &str,
|
||||
) -> Result<Option<crate::data::state::StoredUserSessionRecord>, GatewayError>
|
||||
{
|
||||
) -> Result<Option<GatewayUserSessionView>, GatewayError> {
|
||||
#[cfg(test)]
|
||||
if let Some(store) = self.auth_session_store.as_ref() {
|
||||
let key = format!("{user_id}:{session_id}");
|
||||
@@ -14,20 +13,21 @@ impl AppState {
|
||||
.lock()
|
||||
.expect("auth session store should lock")
|
||||
.get(&key)
|
||||
.cloned());
|
||||
.cloned()
|
||||
.map(Into::into));
|
||||
}
|
||||
|
||||
self.data
|
||||
.find_user_session(user_id, session_id)
|
||||
.await
|
||||
.map(|value| value.map(Into::into))
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))
|
||||
}
|
||||
|
||||
pub(crate) async fn list_user_sessions(
|
||||
&self,
|
||||
user_id: &str,
|
||||
) -> Result<Vec<crate::data::state::StoredUserSessionRecord>, GatewayError>
|
||||
{
|
||||
) -> Result<Vec<GatewayUserSessionView>, GatewayError> {
|
||||
#[cfg(test)]
|
||||
if let Some(store) = self.auth_session_store.as_ref() {
|
||||
let prefix = format!("{user_id}:");
|
||||
@@ -46,12 +46,13 @@ impl AppState {
|
||||
.cmp(&left.last_seen_at)
|
||||
.then_with(|| right.created_at.cmp(&left.created_at))
|
||||
});
|
||||
return Ok(sessions);
|
||||
return Ok(sessions.into_iter().map(Into::into).collect());
|
||||
}
|
||||
|
||||
self.data
|
||||
.list_user_sessions(user_id)
|
||||
.await
|
||||
.map(|sessions| sessions.into_iter().map(Into::into).collect())
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))
|
||||
}
|
||||
|
||||
@@ -112,11 +113,14 @@ impl AppState {
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))
|
||||
}
|
||||
|
||||
pub(crate) async fn create_user_session(
|
||||
pub(crate) async fn create_user_session<T>(
|
||||
&self,
|
||||
session: crate::data::state::StoredUserSessionRecord,
|
||||
) -> Result<Option<crate::data::state::StoredUserSessionRecord>, GatewayError>
|
||||
session: T,
|
||||
) -> Result<Option<GatewayUserSessionView>, GatewayError>
|
||||
where
|
||||
T: Into<GatewayUserSessionView>,
|
||||
{
|
||||
let session = session.into();
|
||||
#[cfg(test)]
|
||||
if let Some(store) = self.auth_session_store.as_ref() {
|
||||
let now = session
|
||||
@@ -138,14 +142,16 @@ impl AppState {
|
||||
}
|
||||
guard.insert(
|
||||
format!("{}:{}", session.user_id, session.id),
|
||||
session.clone(),
|
||||
session.clone().into(),
|
||||
);
|
||||
return Ok(Some(session));
|
||||
}
|
||||
|
||||
let raw_session: crate::data::state::StoredUserSessionRecord = session.into();
|
||||
self.data
|
||||
.create_user_session(&session)
|
||||
.create_user_session(&raw_session)
|
||||
.await
|
||||
.map(|value| value.map(Into::into))
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))
|
||||
}
|
||||
|
||||
|
||||
@@ -5,10 +5,9 @@ use aether_data::repository::wallet::{
|
||||
StoredAdminWalletRefundRequestItem, StoredAdminWalletTransaction,
|
||||
};
|
||||
|
||||
use crate::state::AdminPaymentCallbackRecord;
|
||||
use crate::{
|
||||
AdminWalletMutationOutcome, AdminWalletPaymentOrderRecord, AdminWalletRefundRecord, AppState,
|
||||
GatewayError,
|
||||
GatewayAdminPaymentCallbackView, GatewayError,
|
||||
};
|
||||
|
||||
impl AppState {
|
||||
@@ -124,7 +123,7 @@ impl AppState {
|
||||
payment_method: Option<&str>,
|
||||
limit: usize,
|
||||
offset: usize,
|
||||
) -> Result<Option<(Vec<AdminPaymentCallbackRecord>, u64)>, GatewayError> {
|
||||
) -> Result<Option<(Vec<GatewayAdminPaymentCallbackView>, u64)>, GatewayError> {
|
||||
#[cfg(test)]
|
||||
if let Some(store) = self.admin_payment_callback_store.as_ref() {
|
||||
let mut items = store
|
||||
@@ -147,6 +146,7 @@ impl AppState {
|
||||
.into_iter()
|
||||
.skip(offset)
|
||||
.take(limit)
|
||||
.map(Into::into)
|
||||
.collect::<Vec<_>>();
|
||||
return Ok(Some((items, total)));
|
||||
}
|
||||
@@ -160,6 +160,7 @@ impl AppState {
|
||||
page.items
|
||||
.into_iter()
|
||||
.map(stored_admin_payment_callback_to_gateway)
|
||||
.map(Into::into)
|
||||
.collect(),
|
||||
page.total,
|
||||
)))
|
||||
@@ -415,8 +416,8 @@ fn stored_admin_payment_order_to_gateway(
|
||||
|
||||
fn stored_admin_payment_callback_to_gateway(
|
||||
record: StoredAdminPaymentCallback,
|
||||
) -> AdminPaymentCallbackRecord {
|
||||
AdminPaymentCallbackRecord {
|
||||
) -> GatewayAdminPaymentCallbackView {
|
||||
GatewayAdminPaymentCallbackView {
|
||||
id: record.id,
|
||||
payment_order_id: record.payment_order_id,
|
||||
payment_method: record.payment_method,
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
use crate::{AppState, GatewayError};
|
||||
use aether_data_contracts::repository::{candidate_selection, candidates, quota};
|
||||
|
||||
impl AppState {
|
||||
pub(crate) async fn list_minimal_candidate_selection_rows_for_api_format(
|
||||
&self,
|
||||
api_format: &str,
|
||||
) -> Result<
|
||||
Vec<aether_data::repository::candidate_selection::StoredMinimalCandidateSelectionRow>,
|
||||
GatewayError,
|
||||
> {
|
||||
) -> Result<Vec<candidate_selection::StoredMinimalCandidateSelectionRow>, GatewayError> {
|
||||
self.data
|
||||
.list_minimal_candidate_selection_rows_for_api_format(api_format)
|
||||
.await
|
||||
@@ -18,10 +16,7 @@ impl AppState {
|
||||
&self,
|
||||
api_format: &str,
|
||||
global_model_name: &str,
|
||||
) -> Result<
|
||||
Vec<aether_data::repository::candidate_selection::StoredMinimalCandidateSelectionRow>,
|
||||
GatewayError,
|
||||
> {
|
||||
) -> Result<Vec<candidate_selection::StoredMinimalCandidateSelectionRow>, GatewayError> {
|
||||
self.data
|
||||
.list_minimal_candidate_selection_rows(api_format, global_model_name)
|
||||
.await
|
||||
@@ -31,8 +26,7 @@ impl AppState {
|
||||
pub(crate) async fn read_provider_quota_snapshot(
|
||||
&self,
|
||||
provider_id: &str,
|
||||
) -> Result<Option<aether_data::repository::quota::StoredProviderQuotaSnapshot>, GatewayError>
|
||||
{
|
||||
) -> Result<Option<quota::StoredProviderQuotaSnapshot>, GatewayError> {
|
||||
self.data
|
||||
.find_provider_quota_by_provider_id(provider_id)
|
||||
.await
|
||||
@@ -42,8 +36,7 @@ impl AppState {
|
||||
pub(crate) async fn read_recent_request_candidates(
|
||||
&self,
|
||||
limit: usize,
|
||||
) -> Result<Vec<aether_data::repository::candidates::StoredRequestCandidate>, GatewayError>
|
||||
{
|
||||
) -> Result<Vec<candidates::StoredRequestCandidate>, GatewayError> {
|
||||
self.data
|
||||
.list_recent_request_candidates(limit)
|
||||
.await
|
||||
@@ -52,9 +45,8 @@ impl AppState {
|
||||
|
||||
pub(crate) async fn upsert_request_candidate(
|
||||
&self,
|
||||
candidate: aether_data::repository::candidates::UpsertRequestCandidateRecord,
|
||||
) -> Result<Option<aether_data::repository::candidates::StoredRequestCandidate>, GatewayError>
|
||||
{
|
||||
candidate: candidates::UpsertRequestCandidateRecord,
|
||||
) -> Result<Option<candidates::StoredRequestCandidate>, GatewayError> {
|
||||
self.data
|
||||
.upsert_request_candidate(candidate)
|
||||
.await
|
||||
|
||||
@@ -5,12 +5,10 @@ use super::{
|
||||
AdminBillingRuleRecord, AdminBillingRuleWriteInput, AdminPaymentCallbackRecord,
|
||||
AdminSecurityBlacklistEntry, AdminWalletMutationOutcome, AdminWalletPaymentOrderRecord,
|
||||
AdminWalletRefundRecord, AdminWalletTransactionRecord, AppState, LocalMutationOutcome,
|
||||
AUTH_API_KEY_LAST_USED_MAX_ENTRIES, AUTH_API_KEY_LAST_USED_TTL,
|
||||
};
|
||||
|
||||
mod announcements;
|
||||
mod api_key_exports;
|
||||
mod audit;
|
||||
mod auth;
|
||||
mod billing;
|
||||
mod candidate_queries;
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
use super::admin_payment_gateway_response_map;
|
||||
use crate::{
|
||||
AdminWalletMutationOutcome, AdminWalletPaymentOrderRecord, AppState, GatewayError,
|
||||
};
|
||||
use crate::{AdminWalletMutationOutcome, AdminWalletPaymentOrderRecord, AppState, GatewayError};
|
||||
|
||||
impl AppState {
|
||||
pub(crate) async fn admin_expire_payment_order(
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use crate::{AppState, GatewayError};
|
||||
use aether_data_contracts::repository::{candidates, usage};
|
||||
|
||||
impl AppState {
|
||||
pub(crate) async fn read_request_candidates_by_request_id(
|
||||
&self,
|
||||
request_id: &str,
|
||||
) -> Result<Vec<aether_data::repository::candidates::StoredRequestCandidate>, GatewayError>
|
||||
{
|
||||
) -> Result<Vec<candidates::StoredRequestCandidate>, GatewayError> {
|
||||
self.data
|
||||
.list_request_candidates_by_request_id(request_id)
|
||||
.await
|
||||
@@ -16,8 +16,7 @@ impl AppState {
|
||||
&self,
|
||||
provider_id: &str,
|
||||
limit: usize,
|
||||
) -> Result<Vec<aether_data::repository::candidates::StoredRequestCandidate>, GatewayError>
|
||||
{
|
||||
) -> Result<Vec<candidates::StoredRequestCandidate>, GatewayError> {
|
||||
self.data
|
||||
.list_request_candidates_by_provider_id(provider_id, limit)
|
||||
.await
|
||||
@@ -28,7 +27,7 @@ impl AppState {
|
||||
&self,
|
||||
provider_id: &str,
|
||||
since_unix_secs: u64,
|
||||
) -> Result<aether_data::repository::usage::StoredProviderUsageSummary, GatewayError> {
|
||||
) -> Result<usage::StoredProviderUsageSummary, GatewayError> {
|
||||
self.data
|
||||
.summarize_provider_usage_since(provider_id, since_unix_secs)
|
||||
.await
|
||||
@@ -37,8 +36,8 @@ impl AppState {
|
||||
|
||||
pub(crate) async fn list_usage_audits(
|
||||
&self,
|
||||
query: &aether_data::repository::usage::UsageAuditListQuery,
|
||||
) -> Result<Vec<aether_data::repository::usage::StoredRequestUsageAudit>, GatewayError> {
|
||||
query: &usage::UsageAuditListQuery,
|
||||
) -> Result<Vec<usage::StoredRequestUsageAudit>, GatewayError> {
|
||||
self.data
|
||||
.list_usage_audits(query)
|
||||
.await
|
||||
@@ -49,7 +48,7 @@ impl AppState {
|
||||
&self,
|
||||
user_id: Option<&str>,
|
||||
limit: usize,
|
||||
) -> Result<Vec<aether_data::repository::usage::StoredRequestUsageAudit>, GatewayError> {
|
||||
) -> Result<Vec<usage::StoredRequestUsageAudit>, GatewayError> {
|
||||
self.data
|
||||
.list_recent_usage_audits(user_id, limit)
|
||||
.await
|
||||
|
||||
@@ -1,25 +1,30 @@
|
||||
use crate::{AppState, GatewayError};
|
||||
use crate::{AppState, GatewayError, GatewayUserPreferenceView};
|
||||
|
||||
impl AppState {
|
||||
pub(crate) async fn read_user_preferences(
|
||||
&self,
|
||||
user_id: &str,
|
||||
) -> Result<Option<crate::data::state::StoredUserPreferenceRecord>, GatewayError>
|
||||
{
|
||||
) -> Result<Option<GatewayUserPreferenceView>, GatewayError> {
|
||||
self.data
|
||||
.read_user_preferences(user_id)
|
||||
.await
|
||||
.map(|value| value.map(Into::into))
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))
|
||||
}
|
||||
|
||||
pub(crate) async fn write_user_preferences(
|
||||
pub(crate) async fn write_user_preferences<T>(
|
||||
&self,
|
||||
preferences: &crate::data::state::StoredUserPreferenceRecord,
|
||||
) -> Result<Option<crate::data::state::StoredUserPreferenceRecord>, GatewayError>
|
||||
preferences: T,
|
||||
) -> Result<Option<GatewayUserPreferenceView>, GatewayError>
|
||||
where
|
||||
T: Into<GatewayUserPreferenceView>,
|
||||
{
|
||||
let preferences = preferences.into();
|
||||
let raw_preferences: crate::data::state::StoredUserPreferenceRecord = preferences.into();
|
||||
self.data
|
||||
.write_user_preferences(preferences)
|
||||
.write_user_preferences(&raw_preferences)
|
||||
.await
|
||||
.map(|value| value.map(Into::into))
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
use crate::{
|
||||
AdminWalletPaymentOrderRecord, AdminWalletTransactionRecord, AppState, GatewayError,
|
||||
};
|
||||
use crate::{AdminWalletPaymentOrderRecord, AdminWalletTransactionRecord, AppState, GatewayError};
|
||||
|
||||
use super::admin_wallet_build_order_no;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user