From bd059643f07d60f5ab4ffd16867272813379ebbd Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Tue, 3 Jun 2025 01:16:44 -0400 Subject: [PATCH] enum type, wip --- ...ert_generic_inference_job_for_fal_queue.rs | 14 +++ .../inference_job_external_third_party.rs | 113 ++++++++++++++++++ .../by_table/generic_inference_jobs/mod.rs | 1 + .../image/remove_image_background_handler.rs | 21 ++-- 4 files changed, 139 insertions(+), 10 deletions(-) create mode 100644 crates/schema/public/enums/src/by_table/generic_inference_jobs/inference_job_external_third_party.rs diff --git a/crates/schema/database/mysql_queries/src/queries/generic_inference/web/insert_generic_inference_job_for_fal_queue.rs b/crates/schema/database/mysql_queries/src/queries/generic_inference/web/insert_generic_inference_job_for_fal_queue.rs index 6d48cbb29a..a43a6cdfd4 100644 --- a/crates/schema/database/mysql_queries/src/queries/generic_inference/web/insert_generic_inference_job_for_fal_queue.rs +++ b/crates/schema/database/mysql_queries/src/queries/generic_inference/web/insert_generic_inference_job_for_fal_queue.rs @@ -4,6 +4,7 @@ use sqlx::MySqlPool; use enums::by_table::generic_inference_jobs::inference_category::InferenceCategory; use enums::by_table::generic_inference_jobs::inference_input_source_token_type::InferenceInputSourceTokenType; +use enums::by_table::generic_inference_jobs::inference_job_external_third_party::InferenceJobExternalThirdParty; use enums::by_table::generic_inference_jobs::inference_job_product_category::InferenceJobProductCategory; use enums::by_table::generic_inference_jobs::inference_job_type::InferenceJobType; use enums::by_table::generic_inference_jobs::inference_model_type::InferenceModelType; @@ -28,6 +29,9 @@ pub enum FalCategory { pub struct InsertGenericInferenceForFalArgs<'a> { pub uuid_idempotency_token: &'a str, + /// The external primary key identifier for the job. + pub maybe_external_third_party_id: &'a str, + pub fal_category: FalCategory, pub maybe_inference_args: Option, @@ -67,6 +71,10 @@ pub async fn insert_generic_inference_job_for_fal_queue(args: InsertGenericInfer ), }; + + let maybe_external_third_party = InferenceJobExternalThirdParty::Fal; + + let maybe_external_third_party_id = ""; const STATUS : JobStatusPlus = JobStatusPlus::Pending; let query = sqlx::query!( @@ -78,6 +86,9 @@ SET job_type = ?, + maybe_external_third_party = ?, + maybe_external_third_party_id = ?, + product_category = ?, inference_category = ?, @@ -112,6 +123,9 @@ SET args.uuid_idempotency_token, JOB_TYPE.to_str(), + + maybe_external_third_party.to_str(), + args.maybe_external_third_party_id, product_category.to_str(), inference_category.to_str(), diff --git a/crates/schema/public/enums/src/by_table/generic_inference_jobs/inference_job_external_third_party.rs b/crates/schema/public/enums/src/by_table/generic_inference_jobs/inference_job_external_third_party.rs new file mode 100644 index 0000000000..6036f181cf --- /dev/null +++ b/crates/schema/public/enums/src/by_table/generic_inference_jobs/inference_job_external_third_party.rs @@ -0,0 +1,113 @@ +use std::collections::BTreeSet; + +#[cfg(test)] +use strum::EnumCount; +#[cfg(test)] +use strum::EnumIter; + +/// Used in the `generic_inference_jobs` table in `VARCHAR(16)` field `maybe_external_third_party`. +/// +/// YOU CAN ADD NEW VALUES, BUT DO NOT CHANGE EXISTING VALUES WITHOUT A MIGRATION STRATEGY. +#[cfg_attr(test, derive(EnumIter, EnumCount))] +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize)] +#[serde(rename_all = "snake_case")] +pub enum InferenceJobExternalThirdParty { + /// Fal jobs + #[serde(rename = "fal")] + Fal, +} + +// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(InferenceJobExternalThirdParty); +impl_mysql_enum_coders!(InferenceJobExternalThirdParty); + +/// NB: Legacy API for older code. +impl InferenceJobExternalThirdParty { + pub fn to_str(&self) -> &'static str { + match self { + Self::Fal => "fal", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "fal" => Ok(Self::Fal), + _ => Err(format!("invalid value: {:?}", value)), + } + } + + pub fn all_variants() -> BTreeSet { + // NB: BTreeSet is sorted + // NB: BTreeSet::from() isn't const, but not worth using LazyStatic, etc. + BTreeSet::from([ + Self::Fal, + ]) + } +} + +#[cfg(test)] +mod tests { + use crate::by_table::generic_inference_jobs::inference_job_external_third_party::InferenceJobExternalThirdParty; + use crate::test_helpers::assert_serialization; + + mod explicit_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(InferenceJobExternalThirdParty::Fal, "fal"); + } + + #[test] + fn to_str() { + assert_eq!(InferenceJobExternalThirdParty::Fal.to_str(), "fal"); + } + + #[test] + fn from_str() { + assert_eq!(InferenceJobExternalThirdParty::from_str("fal").unwrap(), InferenceJobExternalThirdParty::Fal); + } + + #[test] + fn all_variants() { + // Static check + const EXPECTED_COUNT : usize = 1; + + assert_eq!(InferenceJobExternalThirdParty::all_variants().len(), EXPECTED_COUNT); + assert_eq!(InferenceJobExternalThirdParty::iter().len(), EXPECTED_COUNT); + + // Generated check + use strum::IntoEnumIterator; + assert_eq!(InferenceJobExternalThirdParty::all_variants().len(), InferenceJobExternalThirdParty::iter().len()); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn variant_length() { + use strum::IntoEnumIterator; + assert_eq!(InferenceJobExternalThirdParty::all_variants().len(), InferenceJobExternalThirdParty::iter().len()); + } + + #[test] + fn round_trip() { + for variant in InferenceJobExternalThirdParty::all_variants() { + assert_eq!(variant, InferenceJobExternalThirdParty::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, InferenceJobExternalThirdParty::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, InferenceJobExternalThirdParty::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH : usize = 32; + for variant in InferenceJobExternalThirdParty::all_variants() { + let serialized = variant.to_str(); + assert!(serialized.len() > 0, "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums/src/by_table/generic_inference_jobs/mod.rs b/crates/schema/public/enums/src/by_table/generic_inference_jobs/mod.rs index a813e8aafd..ab12b4e367 100644 --- a/crates/schema/public/enums/src/by_table/generic_inference_jobs/mod.rs +++ b/crates/schema/public/enums/src/by_table/generic_inference_jobs/mod.rs @@ -1,6 +1,7 @@ pub mod frontend_failure_category; pub mod inference_category; pub mod inference_input_source_token_type; +pub mod inference_job_external_third_party; pub mod inference_job_product_category; pub mod inference_job_type; pub mod inference_model_type; diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/generate/image/remove_image_background_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/generate/image/remove_image_background_handler.rs index 78728eedc8..3d1df9589b 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/generate/image/remove_image_background_handler.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/generate/image/remove_image_background_handler.rs @@ -26,6 +26,7 @@ use mysql_queries::queries::media_files::get::get_media_file::{get_media_file, M use tokens::tokens::media_files::MediaFileToken; use utoipa::ToSchema; use http_server_common::request::get_request_ip::get_request_ip; +use idempotency::uuid::generate_random_uuid; // =============== Error Response =============== #[derive(Debug, Serialize, ToSchema)] @@ -160,19 +161,19 @@ pub async fn remove_image_background_handler( RemoveImageBackgroundError::ServerError })?; + let external_job_id = fal_result.request_id + .ok_or_else(|| { + warn!("Fal request_id is None"); + RemoveImageBackgroundError::ServerError + })?; + let ip_address = get_request_ip(&http_request); - //match fal_result { - // Ok(response) => { - // response - // }, - // Err(err) => { - // warn!("Error removing background: {:?}", err); - // return Err(RemoveImageBackgroundError::ServerError) - // } - //} + let uuid_idempotency_token = generate_random_uuid(); + let db_result = insert_generic_inference_job_for_fal_queue(InsertGenericInferenceForFalArgs { - uuid_idempotency_token: "", + uuid_idempotency_token: &uuid_idempotency_token, + maybe_external_third_party_id: &external_job_id, fal_category: FalCategory::BackgroundRemoval, maybe_inference_args: None, maybe_creator_user_token: maybe_user_session.as_ref().map(|s| &s.user_token),