0579741f64
新增图片画布外部生成队列封装和 worker job 分发 将画板图片、改图、图标、UI 素材、角色动作、视频和音频生成切到队列模式 前端提交生成任务后轮询 queueState 并应用后端项目快照 补充共享契约、测试和 worker 化文档说明
106 lines
4.0 KiB
Rust
106 lines
4.0 KiB
Rust
use axum::http::StatusCode;
|
|
use serde::Serialize;
|
|
use serde_json::json;
|
|
use shared_contracts::external_generation::{
|
|
ExternalGenerationJobStatus, ExternalGenerationJobStatusRecord,
|
|
};
|
|
use shared_kernel::{build_prefixed_uuid_id, offset_datetime_to_unix_micros};
|
|
use spacetime_client::{ExternalGenerationJobEnqueueRecordInput, ExternalGenerationJobRecord};
|
|
|
|
use crate::{http_error::AppError, request_context::RequestContext, state::AppState};
|
|
|
|
pub(crate) const EDITOR_IMAGE_GENERATION_JOB_KIND: &str = "editor_image_generation";
|
|
pub(crate) const EDITOR_IMAGE_EDIT_JOB_KIND: &str = "editor_image_edit";
|
|
pub(crate) const EDITOR_ICON_SPRITESHEET_GENERATION_JOB_KIND: &str =
|
|
"editor_icon_spritesheet_generation";
|
|
pub(crate) const EDITOR_UI_DESIGN_ASSET_EXTRACTION_JOB_KIND: &str =
|
|
"editor_ui_design_asset_extraction";
|
|
pub(crate) const EDITOR_CHARACTER_ANIMATION_GENERATION_JOB_KIND: &str =
|
|
"editor_character_animation_generation";
|
|
pub(crate) const EDITOR_VIDEO_GENERATION_JOB_KIND: &str = "editor_video_generation";
|
|
pub(crate) const EDITOR_SOUND_EFFECT_GENERATION_JOB_KIND: &str = "editor_sound_effect_generation";
|
|
pub(crate) const EDITOR_BACKGROUND_MUSIC_GENERATION_JOB_KIND: &str =
|
|
"editor_background_music_generation";
|
|
|
|
pub(crate) const EDITOR_GENERATION_QUEUE_SOURCE_MODULE: &str = "editor-canvas";
|
|
const EDITOR_GENERATION_QUEUE_PROVIDER: &str = "editor-generation-worker";
|
|
|
|
#[derive(Debug, Serialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub(crate) struct EditorGenerationQueuedResponse {
|
|
pub(crate) queue_state: ExternalGenerationJobStatusRecord,
|
|
}
|
|
|
|
pub(crate) async fn enqueue_editor_generation_job<T>(
|
|
state: &AppState,
|
|
_request_context: &RequestContext,
|
|
owner_user_id: &str,
|
|
job_kind: &str,
|
|
source_entity_id: impl Into<String>,
|
|
request_label: impl Into<String>,
|
|
payload: &T,
|
|
) -> Result<ExternalGenerationJobRecord, AppError>
|
|
where
|
|
T: Serialize,
|
|
{
|
|
let job_id = build_prefixed_uuid_id("extgen-");
|
|
let request_payload_json = serde_json::to_string(payload).map_err(|error| {
|
|
AppError::from_status(StatusCode::INTERNAL_SERVER_ERROR).with_details(json!({
|
|
"provider": EDITOR_GENERATION_QUEUE_PROVIDER,
|
|
"message": format!("编辑器 worker 任务参数序列化失败:{error}"),
|
|
}))
|
|
})?;
|
|
let now_micros = current_utc_micros();
|
|
state
|
|
.spacetime_client()
|
|
.enqueue_external_generation_job(ExternalGenerationJobEnqueueRecordInput {
|
|
dedupe_key: format!("editor-canvas:{job_kind}:{job_id}"),
|
|
job_id,
|
|
job_kind: job_kind.to_string(),
|
|
owner_user_id: owner_user_id.to_string(),
|
|
source_module: EDITOR_GENERATION_QUEUE_SOURCE_MODULE.to_string(),
|
|
source_entity_id: source_entity_id.into(),
|
|
request_label: request_label.into(),
|
|
request_payload_json,
|
|
max_attempts: 1,
|
|
available_at_micros: now_micros,
|
|
created_at_micros: now_micros,
|
|
})
|
|
.await
|
|
.map_err(|error| {
|
|
AppError::from_status(StatusCode::BAD_GATEWAY).with_details(json!({
|
|
"provider": EDITOR_GENERATION_QUEUE_PROVIDER,
|
|
"message": error.to_string(),
|
|
}))
|
|
})
|
|
}
|
|
|
|
pub(crate) fn editor_generation_queue_state(
|
|
job: ExternalGenerationJobRecord,
|
|
) -> ExternalGenerationJobStatusRecord {
|
|
ExternalGenerationJobStatusRecord {
|
|
operation_id: job.job_id,
|
|
status: ExternalGenerationJobStatus::Queued,
|
|
phase_label: job.request_label,
|
|
phase_detail: "排队中。".to_string(),
|
|
progress: 8,
|
|
error: job.last_error_message,
|
|
updated_at_micros: job.updated_at_micros,
|
|
}
|
|
}
|
|
|
|
pub(crate) fn editor_generation_source_entity_id(
|
|
project_id: Option<&str>,
|
|
fallback: &str,
|
|
) -> String {
|
|
project_id
|
|
.map(str::trim)
|
|
.filter(|value| !value.is_empty())
|
|
.unwrap_or(fallback)
|
|
.to_string()
|
|
}
|
|
|
|
fn current_utc_micros() -> i64 {
|
|
offset_datetime_to_unix_micros(time::OffsetDateTime::now_utc())
|
|
}
|