Files
Aether/crates/aether-video-tasks-core/src/service.rs
fawney19 5d96d6673b 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 模型测试对话框
2026-04-07 02:50:19 +08:00

331 lines
12 KiB
Rust

use std::path::PathBuf;
use std::sync::Arc;
use aether_contracts::ExecutionPlan;
use aether_data_contracts::repository::video_tasks::StoredVideoTask;
use serde_json::{Map, Value};
use crate::{
extract_gemini_short_id_from_cancel_path, extract_gemini_short_id_from_path,
extract_openai_task_id_from_cancel_path, extract_openai_task_id_from_content_path,
extract_openai_task_id_from_path, extract_openai_task_id_from_remix_path,
resolve_local_video_registry_mutation, FileVideoTaskStore, InMemoryVideoTaskStore,
LocalVideoTaskContentAction, LocalVideoTaskFollowUpPlan, LocalVideoTaskProjectionTarget,
LocalVideoTaskReadRefreshPlan, LocalVideoTaskReadResponse, LocalVideoTaskSnapshot,
LocalVideoTaskSuccessPlan, VideoTaskStore, VideoTaskTruthSourceMode,
};
#[derive(Debug)]
pub struct VideoTaskService {
truth_source_mode: VideoTaskTruthSourceMode,
store: Arc<dyn VideoTaskStore>,
}
impl VideoTaskService {
pub fn new(mode: VideoTaskTruthSourceMode) -> Self {
Self::with_store(mode, Arc::new(InMemoryVideoTaskStore::default()))
}
pub fn with_file_store(
mode: VideoTaskTruthSourceMode,
path: impl Into<PathBuf>,
) -> std::io::Result<Self> {
Ok(Self::with_store(
mode,
Arc::new(FileVideoTaskStore::new(path)?),
))
}
fn with_store(mode: VideoTaskTruthSourceMode, store: Arc<dyn VideoTaskStore>) -> Self {
Self {
truth_source_mode: mode,
store,
}
}
pub fn with_truth_source_mode(&self, mode: VideoTaskTruthSourceMode) -> Self {
Self {
truth_source_mode: mode,
store: self.store.clone(),
}
}
pub fn is_rust_authoritative(&self) -> bool {
self.truth_source_mode == VideoTaskTruthSourceMode::RustAuthoritative
}
pub fn truth_source_mode(&self) -> VideoTaskTruthSourceMode {
self.truth_source_mode
}
pub fn prepare_sync_success(
&self,
report_kind: &str,
provider_body: &Map<String, Value>,
report_context: &Map<String, Value>,
plan: &ExecutionPlan,
) -> Option<LocalVideoTaskSuccessPlan> {
self.truth_source_mode.prepare_sync_success(
report_kind,
provider_body,
report_context,
plan,
)
}
pub fn record_snapshot(&self, snapshot: LocalVideoTaskSnapshot) {
self.store.insert(snapshot);
}
pub fn hydrate_from_stored_task(&self, task: &StoredVideoTask) -> bool {
let Some(snapshot) = LocalVideoTaskSnapshot::from_stored_task(task) else {
return false;
};
self.store.insert(snapshot);
true
}
pub fn apply_finalize_mutation(&self, request_path: &str, report_kind: &str) {
let Some(mutation) = resolve_local_video_registry_mutation(
self.truth_source_mode,
request_path,
report_kind,
) else {
return;
};
self.store.apply_mutation(mutation);
}
pub fn read_response(
&self,
route_family: Option<&str>,
request_path: &str,
) -> Option<LocalVideoTaskReadResponse> {
if self.truth_source_mode != VideoTaskTruthSourceMode::RustAuthoritative {
return None;
}
match route_family {
Some("openai") => extract_openai_task_id_from_path(request_path)
.and_then(|task_id| self.store.read_openai(task_id)),
Some("gemini") => extract_gemini_short_id_from_path(request_path)
.and_then(|short_id| self.store.read_gemini(short_id)),
_ => None,
}
}
pub fn snapshot_for_route(
&self,
route_family: Option<&str>,
request_path: &str,
) -> Option<LocalVideoTaskSnapshot> {
match route_family {
Some("openai") => extract_openai_task_id_from_path(request_path)
.and_then(|task_id| self.store.clone_openai(task_id))
.map(LocalVideoTaskSnapshot::OpenAi),
Some("gemini") => extract_gemini_short_id_from_path(request_path)
.and_then(|short_id| self.store.clone_gemini(short_id))
.map(LocalVideoTaskSnapshot::Gemini),
_ => None,
}
}
pub fn prepare_openai_content_stream_action(
&self,
request_path: &str,
query_string: Option<&str>,
trace_id: &str,
) -> Option<LocalVideoTaskContentAction> {
if self.truth_source_mode != VideoTaskTruthSourceMode::RustAuthoritative {
return None;
}
let task_id = extract_openai_task_id_from_content_path(request_path)?;
let seed = self.store.clone_openai(task_id)?;
seed.build_content_stream_action(query_string, trace_id)
}
pub fn snapshot_for_refresh_plan(
&self,
refresh_plan: &LocalVideoTaskReadRefreshPlan,
) -> Option<LocalVideoTaskSnapshot> {
match &refresh_plan.projection_target {
LocalVideoTaskProjectionTarget::OpenAi { task_id } => self
.store
.clone_openai(task_id)
.map(LocalVideoTaskSnapshot::OpenAi),
LocalVideoTaskProjectionTarget::Gemini { short_id } => self
.store
.clone_gemini(short_id)
.map(LocalVideoTaskSnapshot::Gemini),
}
}
pub fn project_openai_task_response(
&self,
task_id: &str,
provider_body: &Map<String, Value>,
) -> bool {
if self.truth_source_mode != VideoTaskTruthSourceMode::RustAuthoritative {
return false;
}
self.store.project_openai(task_id, provider_body)
}
pub fn project_gemini_task_response(
&self,
short_id: &str,
provider_body: &Map<String, Value>,
) -> bool {
if self.truth_source_mode != VideoTaskTruthSourceMode::RustAuthoritative {
return false;
}
self.store.project_gemini(short_id, provider_body)
}
pub fn prepare_read_refresh_sync_plan(
&self,
route_family: Option<&str>,
request_path: &str,
trace_id: &str,
) -> Option<LocalVideoTaskReadRefreshPlan> {
if self.truth_source_mode != VideoTaskTruthSourceMode::RustAuthoritative {
return None;
}
match route_family {
Some("openai") => {
let task_id = extract_openai_task_id_from_path(request_path)?;
let seed = self.store.clone_openai(task_id)?;
Some(LocalVideoTaskReadRefreshPlan {
plan: seed.build_get_follow_up_plan(trace_id)?,
projection_target: LocalVideoTaskProjectionTarget::OpenAi {
task_id: task_id.to_string(),
},
})
}
Some("gemini") => {
let short_id = extract_gemini_short_id_from_path(request_path)?;
let seed = self.store.clone_gemini(short_id)?;
Some(LocalVideoTaskReadRefreshPlan {
plan: seed.build_get_follow_up_plan(trace_id)?,
projection_target: LocalVideoTaskProjectionTarget::Gemini {
short_id: short_id.to_string(),
},
})
}
_ => None,
}
}
pub fn prepare_poll_refresh_batch(
&self,
limit: usize,
trace_prefix: &str,
) -> Vec<LocalVideoTaskReadRefreshPlan> {
if self.truth_source_mode != VideoTaskTruthSourceMode::RustAuthoritative || limit == 0 {
return Vec::new();
}
self.store
.list_active_snapshots(limit)
.into_iter()
.enumerate()
.filter_map(|(index, snapshot)| {
let trace_id = format!("{trace_prefix}-{index}");
match snapshot {
LocalVideoTaskSnapshot::OpenAi(seed) => Some(LocalVideoTaskReadRefreshPlan {
plan: seed.build_get_follow_up_plan(&trace_id)?,
projection_target: LocalVideoTaskProjectionTarget::OpenAi {
task_id: seed.local_task_id.clone(),
},
}),
LocalVideoTaskSnapshot::Gemini(seed) => Some(LocalVideoTaskReadRefreshPlan {
plan: seed.build_get_follow_up_plan(&trace_id)?,
projection_target: LocalVideoTaskProjectionTarget::Gemini {
short_id: seed.local_short_id.clone(),
},
}),
}
})
.collect()
}
pub fn prepare_poll_refresh_plan_for_stored_task(
&self,
task: &StoredVideoTask,
trace_id: &str,
) -> Option<LocalVideoTaskReadRefreshPlan> {
if self.truth_source_mode != VideoTaskTruthSourceMode::RustAuthoritative {
return None;
}
let snapshot = LocalVideoTaskSnapshot::from_stored_task(task)?;
match snapshot {
LocalVideoTaskSnapshot::OpenAi(seed) => Some(LocalVideoTaskReadRefreshPlan {
plan: seed.build_get_follow_up_plan(trace_id)?,
projection_target: LocalVideoTaskProjectionTarget::OpenAi {
task_id: seed.local_task_id.clone(),
},
}),
LocalVideoTaskSnapshot::Gemini(seed) => Some(LocalVideoTaskReadRefreshPlan {
plan: seed.build_get_follow_up_plan(trace_id)?,
projection_target: LocalVideoTaskProjectionTarget::Gemini {
short_id: seed.local_short_id.clone(),
},
}),
}
}
pub fn apply_read_refresh_projection(
&self,
refresh_plan: &LocalVideoTaskReadRefreshPlan,
provider_body: &Map<String, Value>,
) -> bool {
match &refresh_plan.projection_target {
LocalVideoTaskProjectionTarget::OpenAi { task_id } => {
self.project_openai_task_response(task_id, provider_body)
}
LocalVideoTaskProjectionTarget::Gemini { short_id } => {
self.project_gemini_task_response(short_id, provider_body)
}
}
}
pub fn prepare_follow_up_sync_plan(
&self,
plan_kind: &str,
request_path: &str,
body_json: Option<&Value>,
fallback_user_id: Option<&str>,
fallback_api_key_id: Option<&str>,
trace_id: &str,
) -> Option<LocalVideoTaskFollowUpPlan> {
match plan_kind {
"openai_video_remix_sync" => {
let task_id = extract_openai_task_id_from_remix_path(request_path)?;
let seed = self.store.clone_openai(task_id)?;
seed.build_remix_follow_up_plan(
body_json?,
fallback_user_id,
fallback_api_key_id,
trace_id,
)
}
"openai_video_delete_sync" => {
let task_id = extract_openai_task_id_from_path(request_path)?;
let seed = self.store.clone_openai(task_id)?;
seed.build_delete_follow_up_plan(fallback_user_id, fallback_api_key_id, trace_id)
}
"openai_video_cancel_sync" => {
let task_id = extract_openai_task_id_from_cancel_path(request_path)?;
let seed = self.store.clone_openai(task_id)?;
seed.build_cancel_follow_up_plan(fallback_user_id, fallback_api_key_id, trace_id)
}
"gemini_video_cancel_sync" => {
let short_id = extract_gemini_short_id_from_cancel_path(request_path)?;
let seed = self.store.clone_gemini(short_id)?;
seed.build_cancel_follow_up_plan(fallback_user_id, fallback_api_key_id, trace_id)
}
_ => None,
}
}
}