mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 17:30:23 +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:
@@ -19,7 +19,7 @@ use super::{
|
||||
read_video_task_detail, read_video_task_page, read_video_task_stats,
|
||||
read_video_task_video_source,
|
||||
};
|
||||
use crate::gateway::{AppState, GatewayError};
|
||||
use crate::{AppState, GatewayError};
|
||||
|
||||
pub(crate) use self::cancel::{cancel_video_task_record, CancelVideoTaskError};
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ use axum::response::IntoResponse;
|
||||
use axum::Json;
|
||||
use serde_json::{json, Map, Value};
|
||||
|
||||
use crate::gateway::{AppState, GatewayError};
|
||||
use crate::{AppState, GatewayError};
|
||||
|
||||
use super::super::finalize_video_task_if_terminal;
|
||||
use super::super::read_video_task_detail;
|
||||
@@ -126,15 +126,19 @@ async fn execute_video_task_cancel_plan(
|
||||
trace_id: &str,
|
||||
plan: aether_contracts::ExecutionPlan,
|
||||
) -> Result<(), axum::response::Response> {
|
||||
let result = crate::gateway::execute_execution_runtime_sync_plan(state, Some(trace_id), &plan)
|
||||
.await
|
||||
.map_err(|err| {
|
||||
GatewayError::UpstreamUnavailable {
|
||||
trace_id: trace_id.to_string(),
|
||||
message: format!("{err:?}"),
|
||||
}
|
||||
.into_response()
|
||||
})?;
|
||||
let result = crate::execution_runtime::execute_execution_runtime_sync_plan(
|
||||
state,
|
||||
Some(trace_id),
|
||||
&plan,
|
||||
)
|
||||
.await
|
||||
.map_err(|err| {
|
||||
GatewayError::UpstreamUnavailable {
|
||||
trace_id: trace_id.to_string(),
|
||||
message: format!("{err:?}"),
|
||||
}
|
||||
.into_response()
|
||||
})?;
|
||||
|
||||
if result.status_code >= 400 {
|
||||
let status = axum::http::StatusCode::from_u16(result.status_code)
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
#[path = "../video_tasks/mod.rs"]
|
||||
pub(crate) mod video;
|
||||
|
||||
mod http;
|
||||
mod query;
|
||||
mod runtime;
|
||||
@@ -18,5 +15,5 @@ pub(crate) use runtime::{
|
||||
execute_video_task_refresh_plan, finalize_video_task_if_terminal, spawn_video_task_poller,
|
||||
VideoTaskPollerConfig,
|
||||
};
|
||||
pub(crate) use video::VideoTaskService;
|
||||
pub use video::VideoTaskTruthSourceMode;
|
||||
pub(crate) use crate::video_tasks::VideoTaskService;
|
||||
pub use crate::video_tasks::VideoTaskTruthSourceMode;
|
||||
|
||||
@@ -5,7 +5,7 @@ use aether_data::repository::video_tasks::{
|
||||
};
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::gateway::{AppState, GatewayError};
|
||||
use crate::{AppState, GatewayError};
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub(crate) struct VideoTaskPageResponse {
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use aether_billing::enrich_usage_event_with_billing;
|
||||
use aether_contracts::{ExecutionErrorKind, ExecutionResult};
|
||||
use aether_data::repository::video_tasks::{StoredVideoTask, UpsertVideoTask, VideoTaskStatus};
|
||||
use aether_usage_runtime::{build_upsert_usage_record_from_event, settle_usage_if_needed};
|
||||
use serde_json::{Map, Value};
|
||||
use tokio::task::JoinHandle;
|
||||
use tracing::warn;
|
||||
use tracing::{info, warn};
|
||||
|
||||
use super::video::{LocalVideoTaskReadRefreshPlan, LocalVideoTaskSnapshot};
|
||||
use crate::gateway::billing_runtime::enrich_usage_event_with_billing;
|
||||
use crate::gateway::usage::{
|
||||
build_upsert_usage_record_from_event, UsageEvent, UsageEventData, UsageEventType,
|
||||
};
|
||||
use crate::gateway::wallet_runtime::settle_usage_if_needed;
|
||||
use crate::gateway::{AppState, GatewayError};
|
||||
use crate::usage::event::{UsageEvent, UsageEventData, UsageEventType};
|
||||
use crate::video_tasks::{LocalVideoTaskReadRefreshPlan, LocalVideoTaskSnapshot};
|
||||
use crate::{AppState, GatewayError};
|
||||
|
||||
const MAX_VIDEO_TASK_POLL_BACKOFF_SECONDS: u64 = 300;
|
||||
const VIDEO_TASK_POLL_CLAIM_SECONDS: u64 = 30;
|
||||
@@ -51,7 +49,13 @@ pub(crate) async fn execute_video_task_refresh_plan(
|
||||
Ok(projected)
|
||||
}
|
||||
VideoTaskRefreshAttempt::Error(err) => {
|
||||
warn!(error = %err.message, permanent = err.permanent, "gateway video task refresh failed");
|
||||
warn!(
|
||||
event_name = "video_task_refresh_failed",
|
||||
log_type = "event",
|
||||
error = %err.message,
|
||||
permanent = err.permanent,
|
||||
"gateway video task refresh failed"
|
||||
);
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
@@ -91,6 +95,14 @@ async fn poll_video_tasks_once(state: &AppState, batch_size: usize) -> Result<us
|
||||
if let Some(snapshot) = LocalVideoTaskSnapshot::from_stored_task(&stored) {
|
||||
state.video_tasks.record_snapshot(snapshot);
|
||||
}
|
||||
info!(
|
||||
event_name = "video_task_status_updated",
|
||||
log_type = "event",
|
||||
request_id = %stored.request_id,
|
||||
task_id = %stored.id,
|
||||
status = ?stored.status,
|
||||
"gateway updated video task status from poll refresh"
|
||||
);
|
||||
finalize_video_task_if_terminal(state, &stored).await;
|
||||
refreshed += 1;
|
||||
}
|
||||
@@ -104,6 +116,14 @@ async fn poll_video_tasks_once(state: &AppState, batch_size: usize) -> Result<us
|
||||
if let Some(snapshot) = LocalVideoTaskSnapshot::from_stored_task(&stored) {
|
||||
state.video_tasks.record_snapshot(snapshot);
|
||||
}
|
||||
info!(
|
||||
event_name = "video_task_status_updated",
|
||||
log_type = "event",
|
||||
request_id = %stored.request_id,
|
||||
task_id = %stored.id,
|
||||
status = ?stored.status,
|
||||
"gateway updated video task status from poll refresh"
|
||||
);
|
||||
finalize_video_task_if_terminal(state, &stored).await;
|
||||
refreshed += 1;
|
||||
}
|
||||
@@ -128,7 +148,12 @@ pub(crate) fn spawn_video_task_poller(state: AppState) -> Option<JoinHandle<()>>
|
||||
loop {
|
||||
interval.tick().await;
|
||||
if let Err(err) = poll_video_tasks_once(&state, config.batch_size).await {
|
||||
warn!(error = ?err, "gateway video task poller tick failed");
|
||||
warn!(
|
||||
event_name = "video_task_poller_tick_failed",
|
||||
log_type = "event",
|
||||
error = ?err,
|
||||
"gateway video task poller tick failed"
|
||||
);
|
||||
}
|
||||
}
|
||||
}))
|
||||
@@ -138,18 +163,21 @@ async fn fetch_video_task_refresh_attempt(
|
||||
state: &AppState,
|
||||
refresh_plan: &LocalVideoTaskReadRefreshPlan,
|
||||
) -> Result<VideoTaskRefreshAttempt, GatewayError> {
|
||||
let result =
|
||||
match crate::gateway::execute_execution_runtime_sync_plan(state, None, &refresh_plan.plan)
|
||||
.await
|
||||
{
|
||||
Ok(result) => result,
|
||||
Err(err) => {
|
||||
return Ok(VideoTaskRefreshAttempt::Error(VideoTaskRefreshError {
|
||||
message: format!("{err:?}"),
|
||||
permanent: false,
|
||||
}));
|
||||
}
|
||||
};
|
||||
let result = match crate::execution_runtime::execute_execution_runtime_sync_plan(
|
||||
state,
|
||||
None,
|
||||
&refresh_plan.plan,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(result) => result,
|
||||
Err(err) => {
|
||||
return Ok(VideoTaskRefreshAttempt::Error(VideoTaskRefreshError {
|
||||
message: format!("{err:?}"),
|
||||
permanent: false,
|
||||
}));
|
||||
}
|
||||
};
|
||||
if result.status_code >= 400 {
|
||||
return Ok(VideoTaskRefreshAttempt::Error(
|
||||
classify_refresh_result_error(&result),
|
||||
@@ -410,23 +438,47 @@ pub(crate) async fn finalize_video_task_if_terminal(state: &AppState, task: &Sto
|
||||
return;
|
||||
};
|
||||
let mut event = event;
|
||||
if let Err(err) = enrich_usage_event_with_billing(&state.data, &mut event).await {
|
||||
warn!(error = %err, request_id = %task.request_id, "gateway video task finalize failed to enrich billing");
|
||||
if let Err(err) = enrich_usage_event_with_billing(state.data.as_ref(), &mut event).await {
|
||||
warn!(
|
||||
event_name = "video_task_finalize_billing_enrichment_failed",
|
||||
log_type = "event",
|
||||
request_id = %task.request_id,
|
||||
error = %err,
|
||||
"gateway video task finalize failed to enrich billing"
|
||||
);
|
||||
}
|
||||
match build_upsert_usage_record_from_event(&event) {
|
||||
Ok(record) => match state.data.upsert_usage(record).await {
|
||||
Ok(Some(stored)) => {
|
||||
if let Err(err) = settle_usage_if_needed(&state.data, &stored).await {
|
||||
warn!(error = %err, request_id = %task.request_id, "gateway video task finalize failed to settle usage");
|
||||
if let Err(err) = settle_usage_if_needed(state.data.as_ref(), &stored).await {
|
||||
warn!(
|
||||
event_name = "video_task_finalize_settlement_failed",
|
||||
log_type = "event",
|
||||
request_id = %task.request_id,
|
||||
error = %err,
|
||||
"gateway video task finalize failed to settle usage"
|
||||
);
|
||||
}
|
||||
}
|
||||
Ok(None) => {}
|
||||
Err(err) => {
|
||||
warn!(error = %err, request_id = %task.request_id, "gateway video task finalize failed to upsert usage");
|
||||
warn!(
|
||||
event_name = "video_task_finalize_usage_upsert_failed",
|
||||
log_type = "event",
|
||||
request_id = %task.request_id,
|
||||
error = %err,
|
||||
"gateway video task finalize failed to upsert usage"
|
||||
);
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
warn!(error = %err, request_id = %task.request_id, "gateway video task finalize failed to build usage record");
|
||||
warn!(
|
||||
event_name = "video_task_finalize_usage_build_failed",
|
||||
log_type = "event",
|
||||
request_id = %task.request_id,
|
||||
error = %err,
|
||||
"gateway video task finalize failed to build usage record"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user