diff --git a/server-rs/crates/api-server/src/asset_billing.rs b/server-rs/crates/api-server/src/asset_billing.rs index 975a45b91..11e7369eb 100644 --- a/server-rs/crates/api-server/src/asset_billing.rs +++ b/server-rs/crates/api-server/src/asset_billing.rs @@ -928,21 +928,45 @@ mod tests { #[test] fn every_provider_inline_route_defers_billing_until_durable_completion() { for (source, expected_calls) in [ - (include_str!("editor_project.rs"), 3), - (include_str!("editor_project_icon.rs"), 1), + (include_str!("editor_project.rs"), 4), + (include_str!("editor_project_icon.rs"), 2), (include_str!("character_animation_assets.rs"), 2), ( include_str!("vector_engine_audio_generation/generation.rs"), 2, ), ] { + let production_source = source + .rsplit_once("\n#[cfg(test)]\nmod tests") + .map(|(production_source, _)| production_source) + .unwrap_or(source); assert_eq!( - source + production_source .matches("with_editor_generation_durable_billing_boundary(") .count(), expected_calls, ); } + + let editor_source = include_str!("editor_project.rs"); + let scene_route = editor_source + .split_once("pub async fn generate_editor_scene(") + .and_then(|(_, tail)| { + tail.split_once("pub async fn generate_editor_image(") + .map(|(body, _)| body) + }) + .expect("scene route"); + let inline_operation = scene_route + .find(".with_inline_operation(") + .expect("scene inline operation"); + let billing_boundary = scene_route + .find("with_editor_generation_durable_billing_boundary(") + .expect("scene durable billing boundary"); + let provider_execution = scene_route + .rfind("generate_editor_image_for_owner(") + .expect("scene provider execution"); + assert!(inline_operation < billing_boundary); + assert!(billing_boundary < provider_execution); } #[test] diff --git a/server-rs/crates/api-server/src/editor_project.rs b/server-rs/crates/api-server/src/editor_project.rs index a2d1ce0b4..406c87e9f 100644 --- a/server-rs/crates/api-server/src/editor_project.rs +++ b/server-rs/crates/api-server/src/editor_project.rs @@ -2559,7 +2559,18 @@ pub async fn generate_editor_scene( }, )); } - generate_editor_image_for_owner(&state, &request_context, caller, image_payload).await + let caller = caller.with_inline_operation( + &request_context, + EDITOR_IMAGE_GENERATION_JOB_KIND, + &image_payload, + )?; + with_editor_generation_durable_billing_boundary(generate_editor_image_for_owner( + &state, + &request_context, + caller, + image_payload, + )) + .await } pub async fn generate_editor_image(