diff --git a/server-rs/crates/api-server/src/tripo3d/worker.rs b/server-rs/crates/api-server/src/tripo3d/worker.rs index 24311a203..081f5129b 100644 --- a/server-rs/crates/api-server/src/tripo3d/worker.rs +++ b/server-rs/crates/api-server/src/tripo3d/worker.rs @@ -94,7 +94,7 @@ async fn run_model3d_job( // 大图、任务排在其他 job 之后),这时提交上去也只会立刻被 deadline 判失败, // 白花一次 provider 调用。只有还轮询得起才提交。 ensure_submit_budget(provider_deadline)?; - submit_and_checkpoint(state, caller, job, &client, &request).await? + submit_and_checkpoint(state, caller, job, &client, &request, provider_deadline).await? } }; let snapshot = poll_until_terminal(&client, &handle, provider_deadline).await?; @@ -154,6 +154,9 @@ fn existing_checkpoint(job: &ExternalGenerationJobRecord) -> Option { } /// 提交前的预算检查:本次尝试已经没有轮询预算时,不发起不可逆且计费的 provider submit。 +/// +/// 调用点有两处:进入提交流程之前,以及图生 3D 在下载 / 上传源图之后、真正 submit 之前 +/// (那两步都可能耗时到把预算用光)。 fn ensure_submit_budget(provider_deadline: Instant) -> Result<(), AppError> { if Instant::now() >= provider_deadline { return Err(provider_deadline_error()); @@ -167,12 +170,17 @@ async fn submit_and_checkpoint( job: &ExternalGenerationJobRecord, client: &TripoProviderClient, request: &Model3dJobRequest, + provider_deadline: Instant, ) -> Result { let handle = match request { Model3dJobRequest::TextToModel(request) => { + ensure_submit_budget(provider_deadline)?; client.submit_text_to_model(&request.generation).await } Model3dJobRequest::ImageToModel(request) => { + // 解析源图要先下载站内图片、再上传给 provider,这一步可能把剩下的预算用光。 + // 提交不可撤销且计费,所以真正发起之前再确认一次:宁可本次尝试判失败, + // 也不要提交上去紧接着被 deadline 判失败,白花一次外部调用。 let input = resolve_image_input( state, client, @@ -180,6 +188,7 @@ async fn submit_and_checkpoint( &request.source, ) .await?; + ensure_submit_budget(provider_deadline)?; client .submit_image_to_model(&input, &request.generation) .await