mirror of
https://github.com/storytold/artcraft.git
synced 2026-10-20 17:02:53 -04:00
make job statuses forward- and backwards- compatible (#1140)
this could have possibly been breaking older clients
This commit is contained in:
-12
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nINSERT INTO generic_inference_jobs\nSET\n token = ?,\n uuid_idempotency_token = ?,\n\n job_type = ?,\n\n maybe_external_third_party = ?,\n maybe_external_third_party_id = ?,\n\n product_category = ?,\n inference_category = ?,\n\n maybe_model_type = NULL,\n maybe_model_token = NULL,\n\n maybe_input_source_token = NULL,\n maybe_input_source_token_type = NULL,\n\n maybe_download_url = NULL,\n maybe_cover_image_media_file_token = NULL,\n \n maybe_prompt_token = ?,\n\n maybe_raw_inference_text = NULL,\n\n maybe_inference_args = ?,\n\n maybe_creator_user_token = ?,\n maybe_creator_anonymous_visitor_token = ?,\n creator_ip_address = ?,\n creator_set_visibility = ?,\n\n priority_level = 0,\n is_keepalive_required = FALSE,\n max_duration_seconds = 0,\n\n is_debug_request = FALSE,\n maybe_routing_tag = NULL,\n\n status = ?\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 14
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "002cdb3d086f3b4181e2997befa54bd8516cb1d3d3bb6e389862695318d5c299"
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nINSERT INTO generic_inference_jobs\nSET\n token = ?,\n uuid_idempotency_token = ?,\n\n job_type = ?,\n\n maybe_external_third_party = ?,\n maybe_external_third_party_id = ?,\n\n product_category = ?,\n inference_category = ?,\n\n maybe_model_type = NULL,\n maybe_model_token = NULL,\n\n maybe_input_source_token = NULL,\n maybe_input_source_token_type = NULL,\n\n maybe_download_url = NULL,\n maybe_cover_image_media_file_token = NULL,\n\n maybe_prompt_token = ?,\n\n maybe_raw_inference_text = NULL,\n\n maybe_inference_args = ?,\n\n maybe_creator_user_token = ?,\n maybe_creator_anonymous_visitor_token = ?,\n creator_ip_address = ?,\n creator_set_visibility = ?,\n\n priority_level = 0,\n is_keepalive_required = FALSE,\n max_duration_seconds = 0,\n\n is_debug_request = FALSE,\n maybe_routing_tag = NULL,\n\n frontend_failure_category = ?,\n failure_reason = ?,\n\n status = ?\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 16
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "29916e73a1784ea0b70ef4f637520b05efccc31e01840f681e9b042f82eb8f7e"
|
||||
}
|
||||
@@ -9,6 +9,8 @@ use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
|
||||
use utoipa::{IntoParams, ToSchema};
|
||||
use enums::api_safe::by_table::generic_inference_jobs::frontend_failure_category_for_api_clients::FrontendFailureCategoryForApiClients;
|
||||
use enums::api_safe::by_table::generic_inference_jobs::frontend_failure_category_for_old_clients::FrontendFailureCategoryForOldClients;
|
||||
use tokens::tokens::batch_generations::BatchGenerationToken;
|
||||
|
||||
pub const LIST_SESSION_JOBS_URL_PATH: &str = "/v1/jobs/session";
|
||||
@@ -98,9 +100,16 @@ pub struct ListSessionStatusDetailsResponse {
|
||||
/// This is typically only for non-premium users.
|
||||
pub requires_keepalive: bool,
|
||||
|
||||
/// NB: DO NOT CHANGE: Old clients can't read the new enum payload values as they are introduced.
|
||||
///
|
||||
/// An enum the frontend can use to display localized/I18N error
|
||||
/// messages. These pertain to both transient and permanent failures.
|
||||
pub maybe_failure_category: Option<FrontendFailureCategory>,
|
||||
#[deprecated(note="use maybe_failure_category_updated")]
|
||||
pub maybe_failure_category: Option<FrontendFailureCategoryForOldClients>,
|
||||
|
||||
/// An enum the frontend can use to display localized/I18N error
|
||||
/// messages. These pertain to both transient and permanent failures.
|
||||
pub maybe_failure_category_updated: Option<FrontendFailureCategoryForApiClients>,
|
||||
|
||||
/// This is an integer number between 0 and 100 (both inclusive) that
|
||||
/// reports the completeness.
|
||||
@@ -125,4 +134,3 @@ pub struct ListSessionResultDetailsResponse {
|
||||
|
||||
pub maybe_successfully_completed_at: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -63,6 +63,8 @@ pub async fn insert_generic_inference_job_for_fal_queue<'e, 'c : 'e, E>(args: In
|
||||
creator_ip_address: args.creator_ip_address,
|
||||
creator_set_visibility: args.creator_set_visibility,
|
||||
starting_job_status_override: None,
|
||||
maybe_frontend_failure_category: None,
|
||||
maybe_failure_reason: None,
|
||||
mysql_executor: args.mysql_executor,
|
||||
phantom: args.phantom,
|
||||
};
|
||||
|
||||
+6
@@ -2,6 +2,7 @@ use idempotency::uuid::generate_random_uuid;
|
||||
use sqlx::{Executor, MySql};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use enums::by_table::generic_inference_jobs::frontend_failure_category::FrontendFailureCategory;
|
||||
use enums::common::job_status_plus::JobStatusPlus;
|
||||
use enums::common::visibility::Visibility;
|
||||
use tokens::tokens::anonymous_visitor_tracking::AnonymousVisitorTrackingToken;
|
||||
@@ -37,6 +38,9 @@ pub struct InsertGenericInferenceForFalMockFailureArgs<'e, 'c, E>
|
||||
pub creator_ip_address: &'e str,
|
||||
pub creator_set_visibility: Visibility,
|
||||
|
||||
pub maybe_frontend_failure_category: Option<FrontendFailureCategory>,
|
||||
pub maybe_failure_reason: Option<&'e str>,
|
||||
|
||||
pub mysql_executor: E,
|
||||
|
||||
pub phantom: PhantomData<&'c E>,
|
||||
@@ -62,6 +66,8 @@ pub async fn insert_generic_inference_job_for_fal_queue_mock_failure<'e, 'c: 'e,
|
||||
creator_ip_address: args.creator_ip_address,
|
||||
creator_set_visibility: args.creator_set_visibility,
|
||||
starting_job_status_override: Some(JobStatusPlus::CompleteFailure),
|
||||
maybe_frontend_failure_category: args.maybe_frontend_failure_category,
|
||||
maybe_failure_reason: args.maybe_failure_reason,
|
||||
mysql_executor: args.mysql_executor,
|
||||
phantom: args.phantom,
|
||||
};
|
||||
|
||||
+25
-14
@@ -4,41 +4,38 @@ use sqlx::MySqlPool;
|
||||
use sqlx::{Executor, MySql};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use enums::by_table::generic_inference_jobs::frontend_failure_category::FrontendFailureCategory;
|
||||
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;
|
||||
use enums::common::job_status_plus::JobStatusPlus;
|
||||
use enums::common::visibility::Visibility;
|
||||
use tokens::tokens::anonymous_visitor_tracking::AnonymousVisitorTrackingToken;
|
||||
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
|
||||
use tokens::tokens::media_files::MediaFileToken;
|
||||
use tokens::tokens::prompts::PromptToken;
|
||||
use tokens::tokens::users::UserToken;
|
||||
|
||||
use crate::errors::database_query_error::DatabaseQueryError;
|
||||
use crate::payloads::generic_inference_args::generic_inference_args::GenericInferenceArgs;
|
||||
use crate::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue::FalCategory;
|
||||
use crate::queries::tts::tts_inference_jobs::kill_tts_inference_jobs::JobStatus;
|
||||
|
||||
|
||||
pub struct InsertGenericInferenceForFalWithAprioriJobTokenArgs<'e, 'c, E>
|
||||
pub struct InsertGenericInferenceForFalWithAprioriJobTokenArgs<'e, 'c, E>
|
||||
where E: 'e + Executor<'c, Database = MySql>
|
||||
{
|
||||
pub uuid_idempotency_token: &'e str,
|
||||
|
||||
|
||||
// NOTE: We'll generate this ahead of time so we can save it with billing info!
|
||||
pub apriori_job_token: &'e InferenceJobToken,
|
||||
|
||||
/// The external primary key identifier for the job.
|
||||
pub maybe_external_third_party_id: &'e str,
|
||||
|
||||
|
||||
pub fal_category: FalCategory,
|
||||
|
||||
pub maybe_inference_args: Option<GenericInferenceArgs>,
|
||||
|
||||
|
||||
pub maybe_prompt_token: Option<&'e PromptToken>,
|
||||
|
||||
pub maybe_creator_user_token: Option<&'e UserToken>,
|
||||
@@ -50,8 +47,11 @@ pub struct InsertGenericInferenceForFalWithAprioriJobTokenArgs<'e, 'c, E>
|
||||
/// Set to `Some(JobStatusPlus::CompleteFailure)` for mock/test failure jobs.
|
||||
pub starting_job_status_override: Option<JobStatusPlus>,
|
||||
|
||||
pub maybe_frontend_failure_category: Option<FrontendFailureCategory>,
|
||||
pub maybe_failure_reason: Option<&'e str>,
|
||||
|
||||
pub mysql_executor: E,
|
||||
|
||||
|
||||
// TODO: Not sure if this works to tell the compiler we need the lifetime annotation.
|
||||
// See: https://doc.rust-lang.org/std/marker/struct.PhantomData.html#unused-lifetime-parameters
|
||||
pub phantom: PhantomData<&'c E>,
|
||||
@@ -87,11 +87,16 @@ pub async fn insert_generic_inference_job_for_fal_queue_with_apriori_job_token<'
|
||||
),
|
||||
};
|
||||
|
||||
|
||||
let maybe_external_third_party = InferenceJobExternalThirdParty::Fal;
|
||||
|
||||
|
||||
let status = args.starting_job_status_override.unwrap_or(JobStatusPlus::Pending);
|
||||
|
||||
let maybe_frontend_failure_category_str = args.maybe_frontend_failure_category
|
||||
.map(|c| c.to_str());
|
||||
|
||||
let maybe_truncated_failure_reason = args.maybe_failure_reason
|
||||
.map(|s| if s.len() > 255 { &s[..255] } else { s });
|
||||
|
||||
let query = sqlx::query!(
|
||||
r#"
|
||||
INSERT INTO generic_inference_jobs
|
||||
@@ -115,7 +120,7 @@ SET
|
||||
|
||||
maybe_download_url = NULL,
|
||||
maybe_cover_image_media_file_token = NULL,
|
||||
|
||||
|
||||
maybe_prompt_token = ?,
|
||||
|
||||
maybe_raw_inference_text = NULL,
|
||||
@@ -134,19 +139,22 @@ SET
|
||||
is_debug_request = FALSE,
|
||||
maybe_routing_tag = NULL,
|
||||
|
||||
frontend_failure_category = ?,
|
||||
failure_reason = ?,
|
||||
|
||||
status = ?
|
||||
"#,
|
||||
args.apriori_job_token.as_str(),
|
||||
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(),
|
||||
|
||||
|
||||
args.maybe_prompt_token.map(|t| t.to_string()),
|
||||
|
||||
serialized_args_payload,
|
||||
@@ -156,6 +164,9 @@ SET
|
||||
args.creator_ip_address,
|
||||
args.creator_set_visibility.to_str(),
|
||||
|
||||
maybe_frontend_failure_category_str,
|
||||
maybe_truncated_failure_reason,
|
||||
|
||||
status.to_str(),
|
||||
);
|
||||
|
||||
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
use crate::by_table::generic_inference_jobs::frontend_failure_category::FrontendFailureCategory;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
/// A forward-compatible version of `FrontendFailureCategory` for API clients.
|
||||
///
|
||||
/// Contains all known variants plus an `Unknown(String)` catch-all so that
|
||||
/// newer server-side values never cause deserialization failures on the client.
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize, ToSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum FrontendFailureCategoryForApiClients {
|
||||
FaceNotDetected,
|
||||
KeepAliveElapsed,
|
||||
NotYetImplemented,
|
||||
RetryableWorkerError,
|
||||
ModelRulesViolation,
|
||||
RuleBansUserImage,
|
||||
RuleBansUserImageWithFaces,
|
||||
RuleBansUserTextPrompt,
|
||||
RuleBansUserContent,
|
||||
RuleBansGeneratedVideo,
|
||||
RuleBansGeneratedAudio,
|
||||
RuleBansGeneratedContent,
|
||||
GenerationFailed,
|
||||
|
||||
/// Catch-all for values the client doesn't yet know about.
|
||||
/// The contained string is the raw serialized value from the server.
|
||||
#[serde(untagged)]
|
||||
Unknown(String),
|
||||
}
|
||||
|
||||
impl FrontendFailureCategoryForApiClients {
|
||||
pub fn from_db_enum(value: FrontendFailureCategory) -> Self {
|
||||
match value {
|
||||
FrontendFailureCategory::FaceNotDetected => Self::FaceNotDetected,
|
||||
FrontendFailureCategory::KeepAliveElapsed => Self::KeepAliveElapsed,
|
||||
FrontendFailureCategory::NotYetImplemented => Self::NotYetImplemented,
|
||||
FrontendFailureCategory::RetryableWorkerError => Self::RetryableWorkerError,
|
||||
FrontendFailureCategory::ModelRulesViolation => Self::ModelRulesViolation,
|
||||
FrontendFailureCategory::RuleBansUserImage => Self::RuleBansUserImage,
|
||||
FrontendFailureCategory::RuleBansUserImageWithFaces => Self::RuleBansUserImageWithFaces,
|
||||
FrontendFailureCategory::RuleBansUserTextPrompt => Self::RuleBansUserTextPrompt,
|
||||
FrontendFailureCategory::RuleBansUserContent => Self::RuleBansUserContent,
|
||||
FrontendFailureCategory::RuleBansGeneratedVideo => Self::RuleBansGeneratedVideo,
|
||||
FrontendFailureCategory::RuleBansGeneratedAudio => Self::RuleBansGeneratedAudio,
|
||||
FrontendFailureCategory::RuleBansGeneratedContent => Self::RuleBansGeneratedContent,
|
||||
FrontendFailureCategory::GenerationFailed => Self::GenerationFailed,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_deserialize_known_variants() {
|
||||
let cases = vec![
|
||||
("\"face_not_detected\"", FrontendFailureCategoryForApiClients::FaceNotDetected),
|
||||
("\"keep_alive_elapsed\"", FrontendFailureCategoryForApiClients::KeepAliveElapsed),
|
||||
("\"not_yet_implemented\"", FrontendFailureCategoryForApiClients::NotYetImplemented),
|
||||
("\"retryable_worker_error\"", FrontendFailureCategoryForApiClients::RetryableWorkerError),
|
||||
("\"model_rules_violation\"", FrontendFailureCategoryForApiClients::ModelRulesViolation),
|
||||
("\"rule_bans_user_image\"", FrontendFailureCategoryForApiClients::RuleBansUserImage),
|
||||
("\"rule_bans_user_image_with_faces\"", FrontendFailureCategoryForApiClients::RuleBansUserImageWithFaces),
|
||||
("\"rule_bans_user_text_prompt\"", FrontendFailureCategoryForApiClients::RuleBansUserTextPrompt),
|
||||
("\"rule_bans_user_content\"", FrontendFailureCategoryForApiClients::RuleBansUserContent),
|
||||
("\"rule_bans_generated_video\"", FrontendFailureCategoryForApiClients::RuleBansGeneratedVideo),
|
||||
("\"rule_bans_generated_audio\"", FrontendFailureCategoryForApiClients::RuleBansGeneratedAudio),
|
||||
("\"rule_bans_generated_content\"", FrontendFailureCategoryForApiClients::RuleBansGeneratedContent),
|
||||
("\"generation_failed\"", FrontendFailureCategoryForApiClients::GenerationFailed),
|
||||
];
|
||||
|
||||
for (json, expected) in cases {
|
||||
let parsed: FrontendFailureCategoryForApiClients = serde_json::from_str(json)
|
||||
.unwrap_or_else(|e| panic!("failed to parse {}: {}", json, e));
|
||||
assert_eq!(parsed, expected, "mismatch for {}", json);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deserialize_unknown_variant() {
|
||||
let json = "\"some_future_category\"";
|
||||
let parsed: FrontendFailureCategoryForApiClients = serde_json::from_str(json).unwrap();
|
||||
assert_eq!(parsed, FrontendFailureCategoryForApiClients::Unknown("some_future_category".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deserialize_another_unknown_variant() {
|
||||
let json = "\"totally_new_thing\"";
|
||||
let parsed: FrontendFailureCategoryForApiClients = serde_json::from_str(json).unwrap();
|
||||
assert_eq!(parsed, FrontendFailureCategoryForApiClients::Unknown("totally_new_thing".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serialize_known_variants() {
|
||||
assert_eq!(serde_json::to_string(&FrontendFailureCategoryForApiClients::FaceNotDetected).unwrap(), "\"face_not_detected\"");
|
||||
assert_eq!(serde_json::to_string(&FrontendFailureCategoryForApiClients::ModelRulesViolation).unwrap(), "\"model_rules_violation\"");
|
||||
assert_eq!(serde_json::to_string(&FrontendFailureCategoryForApiClients::GenerationFailed).unwrap(), "\"generation_failed\"");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serialize_unknown_variant() {
|
||||
let unknown = FrontendFailureCategoryForApiClients::Unknown("some_future_category".to_string());
|
||||
assert_eq!(serde_json::to_string(&unknown).unwrap(), "\"some_future_category\"");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_db_enum() {
|
||||
assert_eq!(
|
||||
FrontendFailureCategoryForApiClients::from_db_enum(FrontendFailureCategory::FaceNotDetected),
|
||||
FrontendFailureCategoryForApiClients::FaceNotDetected
|
||||
);
|
||||
assert_eq!(
|
||||
FrontendFailureCategoryForApiClients::from_db_enum(FrontendFailureCategory::GenerationFailed),
|
||||
FrontendFailureCategoryForApiClients::GenerationFailed
|
||||
);
|
||||
assert_eq!(
|
||||
FrontendFailureCategoryForApiClients::from_db_enum(FrontendFailureCategory::RuleBansGeneratedContent),
|
||||
FrontendFailureCategoryForApiClients::RuleBansGeneratedContent
|
||||
);
|
||||
}
|
||||
}
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
use crate::by_table::generic_inference_jobs::frontend_failure_category::FrontendFailureCategory;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
/// A restricted subset of `FrontendFailureCategory` that only includes values
|
||||
/// known to old deployed clients. New failure categories are omitted so that
|
||||
/// old clients never receive an enum value they cannot deserialize.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Deserialize, Serialize, ToSchema)]
|
||||
pub enum FrontendFailureCategoryForOldClients {
|
||||
#[serde(rename = "face_not_detected")]
|
||||
FaceNotDetected,
|
||||
|
||||
#[serde(rename = "keep_alive_elapsed")]
|
||||
KeepAliveElapsed,
|
||||
|
||||
#[serde(rename = "not_yet_implemented")]
|
||||
NotYetImplemented,
|
||||
|
||||
#[serde(rename = "retryable_worker_error")]
|
||||
RetryableWorkerError,
|
||||
}
|
||||
|
||||
impl FrontendFailureCategoryForOldClients {
|
||||
/// Attempts to convert a database-level `FrontendFailureCategory` into the
|
||||
/// restricted old-client enum. Returns `None` for categories that old
|
||||
/// clients do not understand.
|
||||
pub fn try_from_db_enum(value: FrontendFailureCategory) -> Option<Self> {
|
||||
match value {
|
||||
FrontendFailureCategory::FaceNotDetected => Some(Self::FaceNotDetected),
|
||||
FrontendFailureCategory::KeepAliveElapsed => Some(Self::KeepAliveElapsed),
|
||||
FrontendFailureCategory::NotYetImplemented => Some(Self::NotYetImplemented),
|
||||
FrontendFailureCategory::RetryableWorkerError => Some(Self::RetryableWorkerError),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_known_variants_convert() {
|
||||
assert_eq!(
|
||||
FrontendFailureCategoryForOldClients::try_from_db_enum(FrontendFailureCategory::FaceNotDetected),
|
||||
Some(FrontendFailureCategoryForOldClients::FaceNotDetected)
|
||||
);
|
||||
assert_eq!(
|
||||
FrontendFailureCategoryForOldClients::try_from_db_enum(FrontendFailureCategory::KeepAliveElapsed),
|
||||
Some(FrontendFailureCategoryForOldClients::KeepAliveElapsed)
|
||||
);
|
||||
assert_eq!(
|
||||
FrontendFailureCategoryForOldClients::try_from_db_enum(FrontendFailureCategory::NotYetImplemented),
|
||||
Some(FrontendFailureCategoryForOldClients::NotYetImplemented)
|
||||
);
|
||||
assert_eq!(
|
||||
FrontendFailureCategoryForOldClients::try_from_db_enum(FrontendFailureCategory::RetryableWorkerError),
|
||||
Some(FrontendFailureCategoryForOldClients::RetryableWorkerError)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_new_variants_return_none() {
|
||||
assert_eq!(FrontendFailureCategoryForOldClients::try_from_db_enum(FrontendFailureCategory::ModelRulesViolation), None);
|
||||
assert_eq!(FrontendFailureCategoryForOldClients::try_from_db_enum(FrontendFailureCategory::RuleBansUserImage), None);
|
||||
assert_eq!(FrontendFailureCategoryForOldClients::try_from_db_enum(FrontendFailureCategory::RuleBansUserImageWithFaces), None);
|
||||
assert_eq!(FrontendFailureCategoryForOldClients::try_from_db_enum(FrontendFailureCategory::RuleBansUserTextPrompt), None);
|
||||
assert_eq!(FrontendFailureCategoryForOldClients::try_from_db_enum(FrontendFailureCategory::RuleBansUserContent), None);
|
||||
assert_eq!(FrontendFailureCategoryForOldClients::try_from_db_enum(FrontendFailureCategory::RuleBansGeneratedVideo), None);
|
||||
assert_eq!(FrontendFailureCategoryForOldClients::try_from_db_enum(FrontendFailureCategory::RuleBansGeneratedAudio), None);
|
||||
assert_eq!(FrontendFailureCategoryForOldClients::try_from_db_enum(FrontendFailureCategory::RuleBansGeneratedContent), None);
|
||||
assert_eq!(FrontendFailureCategoryForOldClients::try_from_db_enum(FrontendFailureCategory::GenerationFailed), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serialization() {
|
||||
assert_eq!(serde_json::to_string(&FrontendFailureCategoryForOldClients::FaceNotDetected).unwrap(), "\"face_not_detected\"");
|
||||
assert_eq!(serde_json::to_string(&FrontendFailureCategoryForOldClients::KeepAliveElapsed).unwrap(), "\"keep_alive_elapsed\"");
|
||||
assert_eq!(serde_json::to_string(&FrontendFailureCategoryForOldClients::NotYetImplemented).unwrap(), "\"not_yet_implemented\"");
|
||||
assert_eq!(serde_json::to_string(&FrontendFailureCategoryForOldClients::RetryableWorkerError).unwrap(), "\"retryable_worker_error\"");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
pub mod frontend_failure_category_for_old_clients;
|
||||
pub mod frontend_failure_category_for_api_clients;
|
||||
@@ -0,0 +1 @@
|
||||
pub mod generic_inference_jobs;
|
||||
@@ -0,0 +1 @@
|
||||
pub mod by_table;
|
||||
@@ -37,3 +37,4 @@ pub mod error;
|
||||
pub mod no_table;
|
||||
pub mod tauri;
|
||||
pub mod traits;
|
||||
pub mod api_safe;
|
||||
|
||||
+82
@@ -1,3 +1,31 @@
|
||||
use enums::by_table::generic_inference_jobs::frontend_failure_category::FrontendFailureCategory;
|
||||
|
||||
pub struct SyntheticFailure {
|
||||
pub frontend_failure_category: FrontendFailureCategory,
|
||||
pub frontend_failure_message: Option<String>,
|
||||
}
|
||||
|
||||
/// If the prompt contains a trigger phrase, parse a `FrontendFailureCategory`
|
||||
/// from the remaining words (falling back to `GenerationFailed`) and return a
|
||||
/// `SyntheticFailure`. Returns `None` when the trigger phrase is absent.
|
||||
pub fn test_synthetic_failure_reason(prompt: &str) -> Option<SyntheticFailure> {
|
||||
let lower = prompt.to_ascii_lowercase();
|
||||
if !lower.contains("simulate_artcraft_failure") && !lower.contains("test_artcraft_failure") {
|
||||
return None;
|
||||
}
|
||||
|
||||
let maybe_category = prompt
|
||||
.split_whitespace()
|
||||
.find_map(|word| FrontendFailureCategory::from_str(word).ok());
|
||||
|
||||
let category = maybe_category.unwrap_or(FrontendFailureCategory::GenerationFailed);
|
||||
|
||||
Some(SyntheticFailure {
|
||||
frontend_failure_category: category,
|
||||
frontend_failure_message: Some("This was a simulated failure".to_string()),
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns `true` if the prompt contains the secret test phrase that triggers
|
||||
/// a synthetic job failure. The job record is inserted with
|
||||
/// `JobStatusPlus::CompleteFailure` immediately, without calling any external
|
||||
@@ -5,3 +33,57 @@
|
||||
pub fn is_job_failure_test(prompt: &str) -> bool {
|
||||
prompt.to_ascii_lowercase().contains("artcraft_test_job_failure")
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn no_trigger_returns_none() {
|
||||
assert!(test_synthetic_failure_reason("a normal prompt").is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trigger_simulate_with_no_category_defaults_to_generation_failed() {
|
||||
let result = test_synthetic_failure_reason("simulate_artcraft_failure").unwrap();
|
||||
assert_eq!(result.frontend_failure_category, FrontendFailureCategory::GenerationFailed);
|
||||
assert_eq!(result.frontend_failure_message.as_deref(), Some("This was a simulated failure"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trigger_test_with_no_category_defaults_to_generation_failed() {
|
||||
let result = test_synthetic_failure_reason("test_artcraft_failure").unwrap();
|
||||
assert_eq!(result.frontend_failure_category, FrontendFailureCategory::GenerationFailed);
|
||||
assert_eq!(result.frontend_failure_message.as_deref(), Some("This was a simulated failure"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trigger_with_known_category() {
|
||||
let result = test_synthetic_failure_reason("simulate_artcraft_failure face_not_detected").unwrap();
|
||||
assert_eq!(result.frontend_failure_category, FrontendFailureCategory::FaceNotDetected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trigger_with_category_before_keyword() {
|
||||
let result = test_synthetic_failure_reason("rule_bans_user_image simulate_artcraft_failure").unwrap();
|
||||
assert_eq!(result.frontend_failure_category, FrontendFailureCategory::RuleBansUserImage);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trigger_with_model_rules_violation() {
|
||||
let result = test_synthetic_failure_reason("test_artcraft_failure model_rules_violation please").unwrap();
|
||||
assert_eq!(result.frontend_failure_category, FrontendFailureCategory::ModelRulesViolation);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trigger_is_case_insensitive() {
|
||||
let result = test_synthetic_failure_reason("SIMULATE_ARTCRAFT_FAILURE").unwrap();
|
||||
assert_eq!(result.frontend_failure_category, FrontendFailureCategory::GenerationFailed);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trigger_embedded_in_text() {
|
||||
let result = test_synthetic_failure_reason("hello world simulate_artcraft_failure keep_alive_elapsed goodbye").unwrap();
|
||||
assert_eq!(result.frontend_failure_category, FrontendFailureCategory::KeepAliveElapsed);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
pub mod job_failure_test;
|
||||
pub mod payments_error_test;
|
||||
pub mod payments_error_test;
|
||||
mod test_synthetic_failure_reason;
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
use enums::by_table::generic_inference_jobs::frontend_failure_category::FrontendFailureCategory;
|
||||
|
||||
pub struct SyntheticFailure {
|
||||
pub frontend_failure_category: FrontendFailureCategory,
|
||||
pub frontend_failure_message: Option<String>,
|
||||
}
|
||||
|
||||
/// If the prompt contains the secret trigger phrase, parse a
|
||||
/// `FrontendFailureCategory` from the remaining words (falling back to
|
||||
/// `GenerationFailed`) and return a `SyntheticFailure`.
|
||||
///
|
||||
/// Returns `None` when the trigger phrase is absent.
|
||||
pub fn test_synthetic_failure_reason(prompt: &str) -> Option<SyntheticFailure> {
|
||||
let lower = prompt.to_ascii_lowercase();
|
||||
if !lower.contains("simulate_artcraft_failure") && !lower.contains("test_artcraft_failure") {
|
||||
return None;
|
||||
}
|
||||
|
||||
let maybe_category = prompt
|
||||
.split_whitespace()
|
||||
.find_map(|word| FrontendFailureCategory::from_str(word).ok());
|
||||
|
||||
let category = maybe_category.unwrap_or(FrontendFailureCategory::GenerationFailed);
|
||||
|
||||
Some(SyntheticFailure {
|
||||
frontend_failure_category: category,
|
||||
frontend_failure_message: Some("This was a simulated failure".to_string()),
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn no_trigger_returns_none() {
|
||||
assert!(test_synthetic_failure_reason("a normal prompt").is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trigger_simulate_with_no_category_defaults_to_generation_failed() {
|
||||
let result = test_synthetic_failure_reason("simulate_artcraft_failure").unwrap();
|
||||
assert_eq!(result.frontend_failure_category, FrontendFailureCategory::GenerationFailed);
|
||||
assert_eq!(result.frontend_failure_message.as_deref(), Some("This was a simulated failure"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trigger_test_with_no_category_defaults_to_generation_failed() {
|
||||
let result = test_synthetic_failure_reason("test_artcraft_failure").unwrap();
|
||||
assert_eq!(result.frontend_failure_category, FrontendFailureCategory::GenerationFailed);
|
||||
assert_eq!(result.frontend_failure_message.as_deref(), Some("This was a simulated failure"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trigger_with_known_category() {
|
||||
let result = test_synthetic_failure_reason("simulate_artcraft_failure face_not_detected").unwrap();
|
||||
assert_eq!(result.frontend_failure_category, FrontendFailureCategory::FaceNotDetected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trigger_with_category_before_keyword() {
|
||||
let result = test_synthetic_failure_reason("rule_bans_user_image simulate_artcraft_failure").unwrap();
|
||||
assert_eq!(result.frontend_failure_category, FrontendFailureCategory::RuleBansUserImage);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trigger_with_model_rules_violation() {
|
||||
let result = test_synthetic_failure_reason("test_artcraft_failure model_rules_violation please").unwrap();
|
||||
assert_eq!(result.frontend_failure_category, FrontendFailureCategory::ModelRulesViolation);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trigger_is_case_insensitive() {
|
||||
let result = test_synthetic_failure_reason("SIMULATE_ARTCRAFT_FAILURE").unwrap();
|
||||
assert_eq!(result.frontend_failure_category, FrontendFailureCategory::GenerationFailed);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trigger_embedded_in_text() {
|
||||
let result = test_synthetic_failure_reason("hello world simulate_artcraft_failure keep_alive_elapsed goodbye").unwrap();
|
||||
assert_eq!(result.frontend_failure_category, FrontendFailureCategory::KeepAliveElapsed);
|
||||
}
|
||||
}
|
||||
+2
@@ -216,6 +216,8 @@ pub async fn flux_2_lora_edit_image_angle_handler(
|
||||
creator_set_visibility: Visibility::Public,
|
||||
mysql_executor: &mut *transaction,
|
||||
starting_job_status_override: None,
|
||||
maybe_frontend_failure_category: None,
|
||||
maybe_failure_reason: None,
|
||||
phantom: Default::default(),
|
||||
}).await;
|
||||
|
||||
|
||||
+2
@@ -217,6 +217,8 @@ pub async fn qwen_edit_2511_edit_image_angle_handler(
|
||||
creator_set_visibility: Visibility::Public,
|
||||
mysql_executor: &mut *transaction,
|
||||
starting_job_status_override: None,
|
||||
maybe_frontend_failure_category: None,
|
||||
maybe_failure_reason: None,
|
||||
phantom: Default::default(),
|
||||
}).await;
|
||||
|
||||
|
||||
+2
@@ -279,6 +279,8 @@ pub async fn gemini_25_flash_edit_image_handler(
|
||||
creator_set_visibility: Visibility::Public,
|
||||
mysql_executor: &mut *transaction,
|
||||
starting_job_status_override: None,
|
||||
maybe_frontend_failure_category: None,
|
||||
maybe_failure_reason: None,
|
||||
phantom: Default::default(),
|
||||
}).await;
|
||||
|
||||
|
||||
+2
@@ -301,6 +301,8 @@ pub async fn gpt_image_1_edit_image_handler(
|
||||
creator_set_visibility: Visibility::Public,
|
||||
mysql_executor: &mut *transaction,
|
||||
starting_job_status_override: None,
|
||||
maybe_frontend_failure_category: None,
|
||||
maybe_failure_reason: None,
|
||||
phantom: Default::default(),
|
||||
}).await;
|
||||
|
||||
|
||||
+2
@@ -253,6 +253,8 @@ pub async fn qwen_edit_image_handler(
|
||||
creator_set_visibility: Visibility::Public,
|
||||
mysql_executor: &mut *transaction,
|
||||
starting_job_status_override: None,
|
||||
maybe_frontend_failure_category: None,
|
||||
maybe_failure_reason: None,
|
||||
phantom: Default::default(),
|
||||
}).await;
|
||||
|
||||
|
||||
+9
-2
@@ -2,7 +2,7 @@ use std::sync::Arc;
|
||||
|
||||
use crate::billing::wallets::temporary_test_wallet_deduction::temporary_test_wallet_deduction;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::endpoints::generate::common::job_failure_test::is_job_failure_test;
|
||||
use crate::http_server::endpoints::generate::common::job_failure_test::test_synthetic_failure_reason;
|
||||
use crate::http_server::endpoints::generate::common::payments_error_test::payments_error_test;
|
||||
use crate::http_server::validations::validate_idempotency_token_format::validate_idempotency_token_format;
|
||||
use crate::state::server_state::ServerState;
|
||||
@@ -10,6 +10,7 @@ use actix_web::web::Json;
|
||||
use actix_web::{web, HttpRequest};
|
||||
use artcraft_api_defs::generate::image::edit::flux_pro_kontext_max_edit_image::FluxProKontextMaxEditImageNumImages;
|
||||
use artcraft_api_defs::generate::image::text::generate_flux_1_dev_text_to_image::{GenerateFlux1DevTextToImageAspectRatio, GenerateFlux1DevTextToImageNumImages, GenerateFlux1DevTextToImageRequest, GenerateFlux1DevTextToImageResponse};
|
||||
use enums::by_table::generic_inference_jobs::frontend_failure_category::FrontendFailureCategory;
|
||||
use enums::by_table::prompts::prompt_type::PromptType;
|
||||
use enums::common::generation_provider::GenerationProvider;
|
||||
use enums::common::model_type::ModelType;
|
||||
@@ -95,13 +96,15 @@ pub async fn generate_flux_1_dev_text_to_image_handler(
|
||||
})?;
|
||||
|
||||
// Secret test hook: insert a synthetic "complete_failure" job without calling Fal.
|
||||
if is_job_failure_test(request.prompt.as_deref().unwrap_or("")) {
|
||||
if let Some(synthetic_failure) = test_synthetic_failure_reason(request.prompt.as_deref().unwrap_or("")) {
|
||||
return insert_mock_failure_job(
|
||||
&http_request,
|
||||
request.prompt.as_deref(),
|
||||
&request.uuid_idempotency_token,
|
||||
maybe_user_session.as_ref().map(|s| &s.user_token),
|
||||
maybe_avt_token.as_ref(),
|
||||
Some(synthetic_failure.frontend_failure_category),
|
||||
synthetic_failure.frontend_failure_message.as_deref(),
|
||||
&mut mysql_connection,
|
||||
).await;
|
||||
}
|
||||
@@ -252,6 +255,8 @@ async fn insert_mock_failure_job(
|
||||
uuid_idempotency_token: &str,
|
||||
maybe_creator_user_token: Option<&UserToken>,
|
||||
maybe_avt_token: Option<&AnonymousVisitorTrackingToken>,
|
||||
maybe_frontend_failure_category: Option<FrontendFailureCategory>,
|
||||
maybe_failure_reason: Option<&str>,
|
||||
mysql_connection: &mut sqlx::pool::PoolConnection<sqlx::MySql>,
|
||||
) -> Result<Json<GenerateFlux1DevTextToImageResponse>, CommonWebError> {
|
||||
let ip_address = get_request_ip(http_request);
|
||||
@@ -295,6 +300,8 @@ async fn insert_mock_failure_job(
|
||||
maybe_avt_token,
|
||||
creator_ip_address: &ip_address,
|
||||
creator_set_visibility: Visibility::Public,
|
||||
maybe_frontend_failure_category,
|
||||
maybe_failure_reason,
|
||||
mysql_executor: &mut *transaction,
|
||||
phantom: Default::default(),
|
||||
}).await;
|
||||
|
||||
+2
@@ -188,6 +188,8 @@ pub async fn generate_flux_pro_11_text_to_image_handler(
|
||||
creator_set_visibility: Visibility::Public,
|
||||
mysql_executor: &mut *transaction,
|
||||
starting_job_status_override: None,
|
||||
maybe_frontend_failure_category: None,
|
||||
maybe_failure_reason: None,
|
||||
phantom: Default::default(),
|
||||
}).await;
|
||||
|
||||
|
||||
+2
@@ -192,6 +192,8 @@ pub async fn generate_flux_pro_11_ultra_text_to_image_handler(
|
||||
creator_set_visibility: Visibility::Public,
|
||||
mysql_executor: &mut *transaction,
|
||||
starting_job_status_override: None,
|
||||
maybe_frontend_failure_category: None,
|
||||
maybe_failure_reason: None,
|
||||
phantom: Default::default(),
|
||||
}).await;
|
||||
|
||||
|
||||
+3
-1
@@ -235,6 +235,8 @@ pub async fn generate_gpt_image_1_text_to_image_handler(
|
||||
creator_set_visibility: Visibility::Public,
|
||||
mysql_executor: &mut *transaction,
|
||||
starting_job_status_override: None,
|
||||
maybe_frontend_failure_category: None,
|
||||
maybe_failure_reason: None,
|
||||
phantom: Default::default(),
|
||||
}).await;
|
||||
|
||||
@@ -245,7 +247,7 @@ pub async fn generate_gpt_image_1_text_to_image_handler(
|
||||
return Err(CommonWebError::ServerError);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
let _r = transaction
|
||||
.commit()
|
||||
.await
|
||||
|
||||
+2
@@ -275,6 +275,8 @@ pub async fn bytedance_seedream_5_lite_multi_function_image_gen_handler(
|
||||
creator_set_visibility: Visibility::Public,
|
||||
mysql_executor: &mut *transaction,
|
||||
starting_job_status_override: None,
|
||||
maybe_frontend_failure_category: None,
|
||||
maybe_failure_reason: None,
|
||||
phantom: Default::default(),
|
||||
}).await;
|
||||
|
||||
|
||||
+2
@@ -300,6 +300,8 @@ pub async fn bytedance_seedream_v4_multi_function_image_gen_handler(
|
||||
creator_set_visibility: Visibility::Public,
|
||||
mysql_executor: &mut *transaction,
|
||||
starting_job_status_override: None,
|
||||
maybe_frontend_failure_category: None,
|
||||
maybe_failure_reason: None,
|
||||
phantom: Default::default(),
|
||||
}).await;
|
||||
|
||||
|
||||
+2
@@ -298,6 +298,8 @@ pub async fn bytedance_seedream_v4p5_multi_function_image_gen_handler(
|
||||
creator_set_visibility: Visibility::Public,
|
||||
mysql_executor: &mut *transaction,
|
||||
starting_job_status_override: None,
|
||||
maybe_frontend_failure_category: None,
|
||||
maybe_failure_reason: None,
|
||||
phantom: Default::default(),
|
||||
}).await;
|
||||
|
||||
|
||||
+2
@@ -388,6 +388,8 @@ pub async fn gpt_image_1p5_multi_function_image_gen_handler(
|
||||
creator_set_visibility: Visibility::Public,
|
||||
mysql_executor: &mut *transaction,
|
||||
starting_job_status_override: None,
|
||||
maybe_frontend_failure_category: None,
|
||||
maybe_failure_reason: None,
|
||||
phantom: Default::default(),
|
||||
}).await;
|
||||
|
||||
|
||||
+2
@@ -298,6 +298,8 @@ pub async fn nano_banana_2_multi_function_image_gen_handler(
|
||||
creator_set_visibility: Visibility::Public,
|
||||
mysql_executor: &mut *transaction,
|
||||
starting_job_status_override: None,
|
||||
maybe_frontend_failure_category: None,
|
||||
maybe_failure_reason: None,
|
||||
phantom: Default::default(),
|
||||
}).await;
|
||||
|
||||
|
||||
+2
@@ -331,6 +331,8 @@ pub async fn nano_banana_multi_function_image_gen_handler(
|
||||
creator_set_visibility: Visibility::Public,
|
||||
mysql_executor: &mut *transaction,
|
||||
starting_job_status_override: None,
|
||||
maybe_frontend_failure_category: None,
|
||||
maybe_failure_reason: None,
|
||||
phantom: Default::default(),
|
||||
}).await;
|
||||
|
||||
|
||||
+2
@@ -346,6 +346,8 @@ pub async fn nano_banana_pro_multi_function_image_gen_handler(
|
||||
creator_set_visibility: Visibility::Public,
|
||||
mysql_executor: &mut *transaction,
|
||||
starting_job_status_override: None,
|
||||
maybe_frontend_failure_category: None,
|
||||
maybe_failure_reason: None,
|
||||
phantom: Default::default(),
|
||||
}).await;
|
||||
|
||||
|
||||
+2
@@ -249,6 +249,8 @@ pub async fn generate_kling_1_6_pro_video_handler(
|
||||
creator_set_visibility: Visibility::Public,
|
||||
mysql_executor: &mut *transaction,
|
||||
starting_job_status_override: None,
|
||||
maybe_frontend_failure_category: None,
|
||||
maybe_failure_reason: None,
|
||||
phantom: Default::default(),
|
||||
}).await;
|
||||
|
||||
|
||||
+2
@@ -234,6 +234,8 @@ pub async fn generate_kling_2_1_master_video_handler(
|
||||
creator_set_visibility: Visibility::Public,
|
||||
mysql_executor: &mut *transaction,
|
||||
starting_job_status_override: None,
|
||||
maybe_frontend_failure_category: None,
|
||||
maybe_failure_reason: None,
|
||||
phantom: Default::default(),
|
||||
}).await;
|
||||
|
||||
|
||||
+2
@@ -249,6 +249,8 @@ pub async fn generate_kling_2_1_pro_video_handler(
|
||||
creator_set_visibility: Visibility::Public,
|
||||
mysql_executor: &mut *transaction,
|
||||
starting_job_status_override: None,
|
||||
maybe_frontend_failure_category: None,
|
||||
maybe_failure_reason: None,
|
||||
phantom: Default::default(),
|
||||
}).await;
|
||||
|
||||
|
||||
+2
@@ -264,6 +264,8 @@ pub async fn generate_seedance_1_0_lite_image_to_video_handler(
|
||||
creator_set_visibility: Visibility::Public,
|
||||
mysql_executor: &mut *transaction,
|
||||
starting_job_status_override: None,
|
||||
maybe_frontend_failure_category: None,
|
||||
maybe_failure_reason: None,
|
||||
phantom: Default::default(),
|
||||
}).await;
|
||||
|
||||
|
||||
+3
-1
@@ -241,6 +241,8 @@ pub async fn generate_seedance_1_0_pro_image_to_video_handler(
|
||||
creator_set_visibility: Visibility::Public,
|
||||
mysql_executor: &mut *transaction,
|
||||
starting_job_status_override: None,
|
||||
maybe_frontend_failure_category: None,
|
||||
maybe_failure_reason: None,
|
||||
phantom: Default::default(),
|
||||
}).await;
|
||||
|
||||
@@ -251,7 +253,7 @@ pub async fn generate_seedance_1_0_pro_image_to_video_handler(
|
||||
return Err(CommonWebError::ServerError);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
let _r = transaction
|
||||
.commit()
|
||||
.await
|
||||
|
||||
+2
@@ -247,6 +247,8 @@ pub async fn generate_veo_2_image_to_video_handler(
|
||||
creator_set_visibility: Visibility::Public,
|
||||
mysql_executor: &mut *transaction,
|
||||
starting_job_status_override: None,
|
||||
maybe_frontend_failure_category: None,
|
||||
maybe_failure_reason: None,
|
||||
phantom: Default::default(),
|
||||
}).await;
|
||||
|
||||
|
||||
+2
@@ -240,6 +240,8 @@ pub async fn generate_veo_3_fast_image_to_video_handler(
|
||||
creator_set_visibility: Visibility::Public,
|
||||
mysql_executor: &mut *transaction,
|
||||
starting_job_status_override: None,
|
||||
maybe_frontend_failure_category: None,
|
||||
maybe_failure_reason: None,
|
||||
phantom: Default::default(),
|
||||
}).await;
|
||||
|
||||
|
||||
+2
@@ -248,6 +248,8 @@ pub async fn generate_veo_3_image_to_video_handler(
|
||||
creator_set_visibility: Visibility::Public,
|
||||
mysql_executor: &mut *transaction,
|
||||
starting_job_status_override: None,
|
||||
maybe_frontend_failure_category: None,
|
||||
maybe_failure_reason: None,
|
||||
phantom: Default::default(),
|
||||
}).await;
|
||||
|
||||
|
||||
+2
@@ -318,6 +318,8 @@ pub async fn kling_2p5_turbo_pro_multi_function_video_gen_handler(
|
||||
creator_set_visibility: Visibility::Public,
|
||||
mysql_executor: &mut *transaction,
|
||||
starting_job_status_override: None,
|
||||
maybe_frontend_failure_category: None,
|
||||
maybe_failure_reason: None,
|
||||
phantom: Default::default(),
|
||||
}).await;
|
||||
|
||||
|
||||
+2
@@ -317,6 +317,8 @@ pub async fn kling_2p6_pro_multi_function_video_gen_handler(
|
||||
creator_set_visibility: Visibility::Public,
|
||||
mysql_executor: &mut *transaction,
|
||||
starting_job_status_override: None,
|
||||
maybe_frontend_failure_category: None,
|
||||
maybe_failure_reason: None,
|
||||
phantom: Default::default(),
|
||||
}).await;
|
||||
|
||||
|
||||
+2
@@ -366,6 +366,8 @@ pub async fn kling_3p0_pro_multi_function_video_gen_handler(
|
||||
creator_set_visibility: Visibility::Public,
|
||||
mysql_executor: &mut *transaction,
|
||||
starting_job_status_override: None,
|
||||
maybe_frontend_failure_category: None,
|
||||
maybe_failure_reason: None,
|
||||
phantom: Default::default(),
|
||||
}).await;
|
||||
|
||||
|
||||
+2
@@ -366,6 +366,8 @@ pub async fn kling_3p0_standard_multi_function_video_gen_handler(
|
||||
creator_set_visibility: Visibility::Public,
|
||||
mysql_executor: &mut *transaction,
|
||||
starting_job_status_override: None,
|
||||
maybe_frontend_failure_category: None,
|
||||
maybe_failure_reason: None,
|
||||
phantom: Default::default(),
|
||||
}).await;
|
||||
|
||||
|
||||
+2
@@ -371,6 +371,8 @@ pub async fn seedance_1p5_pro_multi_function_video_gen_handler(
|
||||
creator_set_visibility: Visibility::Public,
|
||||
mysql_executor: &mut *transaction,
|
||||
starting_job_status_override: None,
|
||||
maybe_frontend_failure_category: None,
|
||||
maybe_failure_reason: None,
|
||||
phantom: Default::default(),
|
||||
}).await;
|
||||
|
||||
|
||||
+2
@@ -337,6 +337,8 @@ pub async fn sora_2_multi_function_video_gen_handler(
|
||||
creator_set_visibility: Visibility::Public,
|
||||
mysql_executor: &mut *transaction,
|
||||
starting_job_status_override: None,
|
||||
maybe_frontend_failure_category: None,
|
||||
maybe_failure_reason: None,
|
||||
phantom: Default::default(),
|
||||
}).await;
|
||||
|
||||
|
||||
+2
@@ -339,6 +339,8 @@ pub async fn sora_2_pro_multi_function_video_gen_handler(
|
||||
creator_set_visibility: Visibility::Public,
|
||||
mysql_executor: &mut *transaction,
|
||||
starting_job_status_override: None,
|
||||
maybe_frontend_failure_category: None,
|
||||
maybe_failure_reason: None,
|
||||
phantom: Default::default(),
|
||||
}).await;
|
||||
|
||||
|
||||
+3
-1
@@ -402,6 +402,8 @@ pub async fn veo_3p1_fast_multi_function_video_gen_handler(
|
||||
creator_set_visibility: Visibility::Public,
|
||||
mysql_executor: &mut *transaction,
|
||||
starting_job_status_override: None,
|
||||
maybe_frontend_failure_category: None,
|
||||
maybe_failure_reason: None,
|
||||
phantom: Default::default(),
|
||||
}).await;
|
||||
|
||||
@@ -412,7 +414,7 @@ pub async fn veo_3p1_fast_multi_function_video_gen_handler(
|
||||
return Err(CommonWebError::ServerError);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
let _r = transaction
|
||||
.commit()
|
||||
.await
|
||||
|
||||
+3
-1
@@ -402,6 +402,8 @@ pub async fn veo_3p1_multi_function_video_gen_handler(
|
||||
creator_set_visibility: Visibility::Public,
|
||||
mysql_executor: &mut *transaction,
|
||||
starting_job_status_override: None,
|
||||
maybe_frontend_failure_category: None,
|
||||
maybe_failure_reason: None,
|
||||
phantom: Default::default(),
|
||||
}).await;
|
||||
|
||||
@@ -412,7 +414,7 @@ pub async fn veo_3p1_multi_function_video_gen_handler(
|
||||
return Err(CommonWebError::ServerError);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
let _r = transaction
|
||||
.commit()
|
||||
.await
|
||||
|
||||
+8
-1
@@ -21,6 +21,8 @@ use artcraft_api_defs::jobs::list_session_jobs::{ListSessionJobsItem, ListSessio
|
||||
use bucket_paths::legacy::typified_paths::public::media_files::bucket_file_path::MediaFileBucketPath;
|
||||
use bucket_paths::legacy::typified_paths::public::voice_conversion_results::bucket_file_path::VoiceConversionResultOriginalFilePath;
|
||||
use chrono::{DateTime, Utc};
|
||||
use enums::api_safe::by_table::generic_inference_jobs::frontend_failure_category_for_api_clients::FrontendFailureCategoryForApiClients;
|
||||
use enums::api_safe::by_table::generic_inference_jobs::frontend_failure_category_for_old_clients::FrontendFailureCategoryForOldClients;
|
||||
use enums::by_table::generic_inference_jobs::frontend_failure_category::FrontendFailureCategory;
|
||||
use enums::by_table::generic_inference_jobs::inference_category::InferenceCategory;
|
||||
use enums::common::job_status_plus::JobStatusPlus;
|
||||
@@ -290,7 +292,12 @@ fn db_record_to_response_payload(
|
||||
maybe_first_started_at: record.maybe_first_started_at,
|
||||
attempt_count: record.attempt_count as u8,
|
||||
requires_keepalive: record.is_keepalive_required,
|
||||
maybe_failure_category: record.maybe_frontend_failure_category,
|
||||
maybe_failure_category: record
|
||||
.maybe_frontend_failure_category
|
||||
.and_then(|val| FrontendFailureCategoryForOldClients::try_from_db_enum(val)),
|
||||
maybe_failure_category_updated: record
|
||||
.maybe_frontend_failure_category
|
||||
.map(|val| FrontendFailureCategoryForApiClients::from_db_enum(val)),
|
||||
progress_percentage,
|
||||
maybe_current_execution_duration_seconds,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user