new enums

This commit is contained in:
Brandon Thomas committed 2026-03-13 09:47:55 -04:00
1 parent b7770d5566
commit 2af19432c9
7 files changed
+293 -215

No files matched your search

@@ -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
);
}
}
@@ -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;
+1
View File
@@ -37,3 +37,4 @@ pub mod error;
pub mod no_table;
pub mod tauri;
pub mod traits;
pub mod api_safe;
+85 -215
View File
File diff suppressed because it is too large. Load diff