新增外部生成队列概览和单任务状态契约 将跳一跳、拼消消、敲木鱼图片生成动作接入worker队列 前端生成等待页展示当前任务和队列数量 更新外部生成worker运维文档和团队决策记录
109 lines
3.6 KiB
Rust
109 lines
3.6 KiB
Rust
use axum::{
|
|
Json,
|
|
extract::{Extension, Path, State},
|
|
http::StatusCode,
|
|
response::Response,
|
|
};
|
|
use serde_json::json;
|
|
use shared_contracts::external_generation::{
|
|
ExternalGenerationJobStatus, ExternalGenerationJobStatusRecord,
|
|
ExternalGenerationJobStatusResponse, ExternalGenerationQueueOverview,
|
|
ExternalGenerationQueueOverviewResponse,
|
|
};
|
|
use spacetime_client::{
|
|
ExternalGenerationJobGetRecordInput, ExternalGenerationJobRecord,
|
|
ExternalGenerationQueueStatsRecord, SpacetimeClientError,
|
|
};
|
|
|
|
use crate::{
|
|
api_response::json_success_body, auth::AuthenticatedAccessToken, http_error::AppError,
|
|
request_context::RequestContext, state::AppState,
|
|
};
|
|
|
|
const EXTERNAL_GENERATION_PROVIDER: &str = "external_generation";
|
|
|
|
pub async fn get_external_generation_queue_overview(
|
|
State(state): State<AppState>,
|
|
Extension(request_context): Extension<RequestContext>,
|
|
) -> Result<Json<serde_json::Value>, Response> {
|
|
let stats = state
|
|
.spacetime_client()
|
|
.get_external_generation_queue_stats()
|
|
.await
|
|
.map_err(|error| external_generation_error_response(&request_context, error))?;
|
|
|
|
Ok(json_success_body(
|
|
Some(&request_context),
|
|
ExternalGenerationQueueOverviewResponse {
|
|
overview: map_external_generation_queue_overview(stats),
|
|
},
|
|
))
|
|
}
|
|
|
|
pub async fn get_external_generation_job_status(
|
|
State(state): State<AppState>,
|
|
Extension(request_context): Extension<RequestContext>,
|
|
Extension(authenticated): Extension<AuthenticatedAccessToken>,
|
|
Path(job_id): Path<String>,
|
|
) -> Result<Json<serde_json::Value>, Response> {
|
|
let owner_user_id = authenticated.claims().user_id().to_string();
|
|
let job = state
|
|
.spacetime_client()
|
|
.get_external_generation_job(ExternalGenerationJobGetRecordInput {
|
|
job_id,
|
|
owner_user_id,
|
|
})
|
|
.await
|
|
.map_err(|error| external_generation_error_response(&request_context, error))?;
|
|
|
|
Ok(json_success_body(
|
|
Some(&request_context),
|
|
ExternalGenerationJobStatusResponse {
|
|
job: map_external_generation_job_status(job),
|
|
},
|
|
))
|
|
}
|
|
|
|
fn map_external_generation_queue_overview(
|
|
stats: ExternalGenerationQueueStatsRecord,
|
|
) -> ExternalGenerationQueueOverview {
|
|
ExternalGenerationQueueOverview {
|
|
pending_count: stats.pending_count,
|
|
running_count: stats.running_active_count,
|
|
updated_at_micros: stats.now_micros,
|
|
}
|
|
}
|
|
|
|
fn map_external_generation_job_status(
|
|
job: ExternalGenerationJobRecord,
|
|
) -> ExternalGenerationJobStatusRecord {
|
|
let (status, phase_detail, progress) = match job.status.as_str() {
|
|
"completed" => (ExternalGenerationJobStatus::Completed, "生成已完成。", 100),
|
|
"running" => (ExternalGenerationJobStatus::Running, "正在生成。", 35),
|
|
"failed" => (ExternalGenerationJobStatus::Failed, "生成失败。", 0),
|
|
_ => (ExternalGenerationJobStatus::Queued, "排队中。", 8),
|
|
};
|
|
|
|
ExternalGenerationJobStatusRecord {
|
|
operation_id: job.job_id,
|
|
status,
|
|
phase_label: job.request_label,
|
|
phase_detail: phase_detail.to_string(),
|
|
progress,
|
|
error: job.last_error_message,
|
|
updated_at_micros: job.updated_at_micros,
|
|
}
|
|
}
|
|
|
|
fn external_generation_error_response(
|
|
request_context: &RequestContext,
|
|
error: SpacetimeClientError,
|
|
) -> Response {
|
|
AppError::from_status(StatusCode::BAD_GATEWAY)
|
|
.with_details(json!({
|
|
"provider": EXTERNAL_GENERATION_PROVIDER,
|
|
"message": error.to_string(),
|
|
}))
|
|
.into_response_with_context(Some(request_context))
|
|
}
|