mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-03 09:50:21 +08:00
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:
@@ -1,20 +1,14 @@
|
||||
use aether_data::repository::video_tasks::VideoTaskLookupKey;
|
||||
use serde_json::{Map, Value};
|
||||
use aether_usage_runtime::{
|
||||
build_locally_actionable_report_context_from_request_candidate,
|
||||
build_locally_actionable_report_context_from_video_task,
|
||||
};
|
||||
use serde_json::Value;
|
||||
|
||||
use crate::gateway::AppState;
|
||||
use crate::video_tasks::{resolve_video_task_report_lookup, VideoTaskReportLookup};
|
||||
use crate::AppState;
|
||||
|
||||
pub(crate) fn report_context_is_locally_actionable(report_context: Option<&Value>) -> bool {
|
||||
let Some(context) = report_context else {
|
||||
return false;
|
||||
};
|
||||
|
||||
has_non_empty_str(context, "request_id")
|
||||
&& (has_non_empty_str(context, "candidate_id")
|
||||
|| has_u64(context, "candidate_index")
|
||||
|| has_non_empty_str(context, "provider_id")
|
||||
|| has_non_empty_str(context, "endpoint_id")
|
||||
|| has_non_empty_str(context, "key_id"))
|
||||
}
|
||||
pub(crate) use aether_usage_runtime::report_context_is_locally_actionable;
|
||||
|
||||
pub(crate) async fn resolve_locally_actionable_report_context(
|
||||
state: &AppState,
|
||||
@@ -61,143 +55,38 @@ async fn resolve_locally_actionable_report_context_from_request_candidates(
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut object = context.as_object()?.clone();
|
||||
let candidate = &existing_candidates[0];
|
||||
insert_missing_string_value(&mut object, "candidate_id", Some(&candidate.id));
|
||||
if !object.contains_key("candidate_index") {
|
||||
object.insert(
|
||||
"candidate_index".to_string(),
|
||||
Value::Number(candidate.candidate_index.into()),
|
||||
);
|
||||
}
|
||||
insert_missing_optional_string_value(
|
||||
&mut object,
|
||||
"provider_id",
|
||||
candidate.provider_id.as_deref(),
|
||||
);
|
||||
insert_missing_optional_string_value(
|
||||
&mut object,
|
||||
"endpoint_id",
|
||||
candidate.endpoint_id.as_deref(),
|
||||
);
|
||||
insert_missing_optional_string_value(&mut object, "key_id", candidate.key_id.as_deref());
|
||||
insert_missing_optional_string_value(&mut object, "user_id", candidate.user_id.as_deref());
|
||||
insert_missing_optional_string_value(
|
||||
&mut object,
|
||||
"api_key_id",
|
||||
candidate.api_key_id.as_deref(),
|
||||
);
|
||||
|
||||
let resolved = Value::Object(object);
|
||||
report_context_is_locally_actionable(Some(&resolved)).then_some(resolved)
|
||||
build_locally_actionable_report_context_from_request_candidate(context, &existing_candidates[0])
|
||||
}
|
||||
|
||||
async fn resolve_locally_actionable_report_context_from_video_task(
|
||||
state: &AppState,
|
||||
context: &Value,
|
||||
) -> Option<Value> {
|
||||
let local_task_id = context
|
||||
.get("local_task_id")
|
||||
.and_then(Value::as_str)
|
||||
.map(str::trim)
|
||||
.filter(|value| !value.is_empty());
|
||||
let local_short_id = context
|
||||
.get("local_short_id")
|
||||
.and_then(Value::as_str)
|
||||
.map(str::trim)
|
||||
.filter(|value| !value.is_empty());
|
||||
let task_id = context
|
||||
.get("task_id")
|
||||
.and_then(Value::as_str)
|
||||
.map(str::trim)
|
||||
.filter(|value| !value.is_empty());
|
||||
let user_id = context
|
||||
.get("user_id")
|
||||
.and_then(Value::as_str)
|
||||
.map(str::trim)
|
||||
.filter(|value| !value.is_empty());
|
||||
|
||||
let task = if let Some(task_id) = local_task_id {
|
||||
state
|
||||
.data
|
||||
.find_video_task(VideoTaskLookupKey::Id(task_id))
|
||||
.await
|
||||
.ok()??
|
||||
} else if let Some(short_id) = local_short_id {
|
||||
state
|
||||
.data
|
||||
.find_video_task(VideoTaskLookupKey::ShortId(short_id))
|
||||
.await
|
||||
.ok()??
|
||||
} else if let Some(task_id) = task_id {
|
||||
if let Some(task) = state
|
||||
.data
|
||||
.find_video_task(VideoTaskLookupKey::Id(task_id))
|
||||
.await
|
||||
.ok()?
|
||||
{
|
||||
task
|
||||
} else {
|
||||
let user_id = user_id?;
|
||||
state
|
||||
.data
|
||||
.find_video_task(VideoTaskLookupKey::UserExternal {
|
||||
user_id,
|
||||
external_task_id: task_id,
|
||||
})
|
||||
.await
|
||||
.ok()??
|
||||
let task = match resolve_video_task_report_lookup(context)? {
|
||||
VideoTaskReportLookup::Lookup(lookup) => {
|
||||
state.data.find_video_task(lookup).await.ok()??
|
||||
}
|
||||
VideoTaskReportLookup::TaskIdOrExternal { task_id, user_id } => {
|
||||
if let Some(task) = state
|
||||
.data
|
||||
.find_video_task(VideoTaskLookupKey::Id(task_id))
|
||||
.await
|
||||
.ok()?
|
||||
{
|
||||
task
|
||||
} else {
|
||||
let user_id = user_id?;
|
||||
state
|
||||
.data
|
||||
.find_video_task(VideoTaskLookupKey::UserExternal {
|
||||
user_id,
|
||||
external_task_id: task_id,
|
||||
})
|
||||
.await
|
||||
.ok()??
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return None;
|
||||
};
|
||||
|
||||
let mut object = context.as_object()?.clone();
|
||||
insert_missing_string_value(&mut object, "request_id", Some(task.request_id.as_str()));
|
||||
insert_missing_optional_string_value(&mut object, "provider_id", task.provider_id.as_deref());
|
||||
insert_missing_optional_string_value(&mut object, "endpoint_id", task.endpoint_id.as_deref());
|
||||
insert_missing_optional_string_value(&mut object, "key_id", task.key_id.as_deref());
|
||||
insert_missing_optional_string_value(&mut object, "user_id", task.user_id.as_deref());
|
||||
insert_missing_optional_string_value(&mut object, "api_key_id", task.api_key_id.as_deref());
|
||||
insert_missing_optional_string_value(
|
||||
&mut object,
|
||||
"client_api_format",
|
||||
task.client_api_format.as_deref(),
|
||||
);
|
||||
insert_missing_optional_string_value(
|
||||
&mut object,
|
||||
"provider_api_format",
|
||||
task.provider_api_format.as_deref(),
|
||||
);
|
||||
Some(Value::Object(object))
|
||||
}
|
||||
|
||||
fn insert_missing_string_value(object: &mut Map<String, Value>, key: &str, value: Option<&str>) {
|
||||
if object.contains_key(key) {
|
||||
return;
|
||||
}
|
||||
let Some(value) = value.map(str::trim).filter(|value| !value.is_empty()) else {
|
||||
return;
|
||||
};
|
||||
object.insert(key.to_string(), Value::String(value.to_string()));
|
||||
}
|
||||
|
||||
fn insert_missing_optional_string_value(
|
||||
object: &mut Map<String, Value>,
|
||||
key: &str,
|
||||
value: Option<&str>,
|
||||
) {
|
||||
insert_missing_string_value(object, key, value);
|
||||
}
|
||||
|
||||
fn has_non_empty_str(value: &Value, key: &str) -> bool {
|
||||
value
|
||||
.get(key)
|
||||
.and_then(Value::as_str)
|
||||
.map(str::trim)
|
||||
.is_some_and(|value| !value.is_empty())
|
||||
}
|
||||
|
||||
fn has_u64(value: &Value, key: &str) -> bool {
|
||||
value.get(key).and_then(Value::as_u64).is_some()
|
||||
build_locally_actionable_report_context_from_video_task(context, &task)
|
||||
}
|
||||
|
||||
1102
apps/aether-gateway/src/usage/reporting/mod.rs
Normal file
1102
apps/aether-gateway/src/usage/reporting/mod.rs
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user