mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-03 00:47:53 +00:00
enqueue fbx to gltf
This commit is contained in:
1 parent
57ca10f23d
commit
eeb6d486e1
5 files changed
+231
-5
No files matched your search
+216
@@ -0,0 +1,216 @@
|
||||
#![forbid(unused_mut)]
|
||||
|
||||
use std::fmt::Debug;
|
||||
use std::sync::Arc;
|
||||
|
||||
use actix_web::{HttpRequest, HttpResponse, web};
|
||||
use actix_web::error::ResponseError;
|
||||
use actix_web::http::StatusCode;
|
||||
use log::warn;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
use enums::by_table::generic_inference_jobs::inference_category::InferenceCategory;
|
||||
use enums::by_table::generic_inference_jobs::inference_model_type::InferenceModelType;
|
||||
use enums::common::visibility::Visibility;
|
||||
use http_server_common::request::get_request_header_optional::get_request_header_optional;
|
||||
use http_server_common::request::get_request_ip::get_request_ip;
|
||||
use mysql_queries::payloads::generic_inference_args::generic_inference_args::{
|
||||
GenericInferenceArgs,
|
||||
InferenceCategoryAbbreviated,
|
||||
};
|
||||
use mysql_queries::queries::generic_inference::web::insert_generic_inference_job::{
|
||||
insert_generic_inference_job,
|
||||
InsertGenericInferenceArgs,
|
||||
};
|
||||
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
|
||||
use tokens::tokens::media_files::MediaFileToken;
|
||||
use tokens::tokens::users::UserToken;
|
||||
|
||||
use crate::configs::plans::get_correct_plan_for_session::get_correct_plan_for_session;
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::server_state::ServerState;
|
||||
|
||||
/// Debug requests can get routed to special "debug-only" workers, which can
|
||||
/// be used to trial new code, run debugging, etc.
|
||||
const DEBUG_HEADER_NAME: &str = "enable-debug-mode";
|
||||
|
||||
/// The routing tag header can send workloads to particular k8s hosts.
|
||||
/// This is useful for catching the live logs or intercepting the job.
|
||||
const ROUTING_TAG_HEADER_NAME: &str = "routing-tag";
|
||||
|
||||
#[derive(Deserialize, ToSchema)]
|
||||
pub struct EnqueueFbxToGltfRequest {
|
||||
// Entropy for idempotency
|
||||
uuid_idempotency_token: String,
|
||||
// The existing FBX media file token
|
||||
media_file_token: MediaFileToken,
|
||||
}
|
||||
|
||||
#[derive(Serialize, ToSchema)]
|
||||
pub struct EnqueueFbxToGltfRequestSuccessResponse {
|
||||
pub success: bool,
|
||||
pub inference_job_token: InferenceJobToken,
|
||||
}
|
||||
|
||||
#[derive(Debug, ToSchema)]
|
||||
pub enum EnqueueFbxToGltfRequestError {
|
||||
BadInput(String),
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
RateLimited,
|
||||
}
|
||||
|
||||
impl ResponseError for EnqueueFbxToGltfRequestError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
EnqueueFbxToGltfRequestError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
EnqueueFbxToGltfRequestError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
EnqueueFbxToGltfRequestError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
EnqueueFbxToGltfRequestError::RateLimited => StatusCode::TOO_MANY_REQUESTS,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
EnqueueFbxToGltfRequestError::BadInput(reason) => reason.to_string(),
|
||||
EnqueueFbxToGltfRequestError::NotAuthorized => "unauthorized".to_string(),
|
||||
EnqueueFbxToGltfRequestError::ServerError => "server error".to_string(),
|
||||
EnqueueFbxToGltfRequestError::RateLimited => "rate limited".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for EnqueueFbxToGltfRequestError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/v1/conversion/enqueue_fbx_to_gltf",
|
||||
responses(
|
||||
(
|
||||
status = 200,
|
||||
description = "Enqueue FBX to GLTF",
|
||||
body = EnqueueFbxToGltfRequestSuccessResponse,
|
||||
),
|
||||
(status = 400, description = "Bad input", body = EnqueueFbxToGltfRequestError),
|
||||
(status = 401, description = "Not authorized", body = EnqueueFbxToGltfRequestError),
|
||||
(status = 429, description = "Rate limited", body = EnqueueFbxToGltfRequestError),
|
||||
(status = 500, description = "Server error", body = EnqueueFbxToGltfRequestError)
|
||||
),
|
||||
params(("request" = EnqueueFbxToGltfRequest, description = "Payload for FBX to GLTF Request"))
|
||||
)]
|
||||
pub async fn enqueue_fbx_to_gltf_handler(
|
||||
http_request: HttpRequest,
|
||||
request: web::Json<EnqueueFbxToGltfRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<HttpResponse, EnqueueFbxToGltfRequestError> {
|
||||
let mut maybe_user_token: Option<UserToken> = None;
|
||||
|
||||
let mut mysql_connection = server_state.mysql_pool.acquire().await.map_err(|err| {
|
||||
warn!("MySql pool error: {:?}", err);
|
||||
EnqueueFbxToGltfRequestError::ServerError
|
||||
})?;
|
||||
|
||||
// ==================== USER SESSION ==================== //
|
||||
|
||||
let maybe_user_session = server_state.session_checker
|
||||
.maybe_get_user_session_extended_from_connection(&http_request, &mut mysql_connection).await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
EnqueueFbxToGltfRequestError::ServerError
|
||||
})?;
|
||||
|
||||
if let Some(user_session) = maybe_user_session.as_ref() {
|
||||
maybe_user_token = Some(UserToken::new_from_str(&user_session.user_token));
|
||||
}
|
||||
|
||||
// Plan should handle "first anonymous use" and "investor" cases.
|
||||
let plan = get_correct_plan_for_session(
|
||||
server_state.server_environment,
|
||||
maybe_user_session.as_ref()
|
||||
);
|
||||
|
||||
// Separate priority for animation.
|
||||
let priority_level = plan.web_vc_base_priority_level();
|
||||
|
||||
// ==================== DEBUG MODE + ROUTING TAG ==================== //
|
||||
|
||||
let is_debug_request = get_request_header_optional(&http_request, DEBUG_HEADER_NAME).is_some();
|
||||
|
||||
let maybe_routing_tag = get_request_header_optional(&http_request, ROUTING_TAG_HEADER_NAME).map(
|
||||
|routing_tag| routing_tag.trim().to_string()
|
||||
);
|
||||
|
||||
// ==================== BANNED USERS ==================== //
|
||||
|
||||
if let Some(ref user) = maybe_user_session {
|
||||
if user.role.is_banned {
|
||||
return Err(EnqueueFbxToGltfRequestError::NotAuthorized);
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== RATE LIMIT ==================== //
|
||||
|
||||
let rate_limiter = match maybe_user_session {
|
||||
None => &server_state.redis_rate_limiters.logged_out,
|
||||
Some(ref _user) => &server_state.redis_rate_limiters.logged_in,
|
||||
};
|
||||
|
||||
if let Err(_err) = rate_limiter.rate_limit_request(&http_request) {
|
||||
return Err(EnqueueFbxToGltfRequestError::RateLimited);
|
||||
}
|
||||
|
||||
let ip_address = get_request_ip(&http_request);
|
||||
|
||||
let maybe_avt_token = server_state.avt_cookie_manager
|
||||
.get_avt_token_from_request(&http_request);
|
||||
|
||||
let query_result = insert_generic_inference_job(InsertGenericInferenceArgs {
|
||||
uuid_idempotency_token: &request.uuid_idempotency_token,
|
||||
inference_category: InferenceCategory::ImageGeneration,
|
||||
maybe_model_type: Some(InferenceModelType::ConvertFbxToGltf),
|
||||
maybe_model_token: None,
|
||||
maybe_input_source_token: Some(&request.media_file_token.as_str()),
|
||||
maybe_input_source_token_type: None,
|
||||
maybe_raw_inference_text: None,
|
||||
maybe_max_duration_seconds: None,
|
||||
maybe_inference_args: Some(GenericInferenceArgs {
|
||||
inference_category: Some(InferenceCategoryAbbreviated::FormatConversion),
|
||||
args: None, // NB: no format conversion args for now
|
||||
}),
|
||||
maybe_creator_user_token: maybe_user_token.as_ref(),
|
||||
maybe_avt_token: maybe_avt_token.as_ref(),
|
||||
creator_ip_address: &ip_address,
|
||||
creator_set_visibility: Visibility::Public,
|
||||
priority_level,
|
||||
requires_keepalive: true,
|
||||
is_debug_request,
|
||||
maybe_routing_tag: maybe_routing_tag.as_deref(),
|
||||
mysql_pool: &server_state.mysql_pool,
|
||||
}).await;
|
||||
|
||||
let job_token = match query_result {
|
||||
Ok((job_token, _id)) => job_token,
|
||||
Err(err) => {
|
||||
warn!("New generic inference job creation DB error: {:?}", err);
|
||||
return Err(EnqueueFbxToGltfRequestError::ServerError);
|
||||
}
|
||||
};
|
||||
|
||||
let response: EnqueueFbxToGltfRequestSuccessResponse = EnqueueFbxToGltfRequestSuccessResponse {
|
||||
success: true,
|
||||
inference_job_token: job_token,
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|_e| EnqueueFbxToGltfRequestError::ServerError)?;
|
||||
|
||||
Ok(HttpResponse::Ok().content_type("application/json").body(body))
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
pub mod enqueue_fbx_to_gltf_handler;
|
||||
@@ -2,9 +2,11 @@ pub mod animation;
|
||||
pub mod api_tokens;
|
||||
pub mod categories;
|
||||
pub mod comments;
|
||||
pub mod conversion;
|
||||
pub mod download_job;
|
||||
pub mod events;
|
||||
pub mod flags;
|
||||
pub mod image_gen;
|
||||
pub mod inference_job;
|
||||
pub mod investor_demo;
|
||||
pub mod leaderboard;
|
||||
@@ -19,14 +21,13 @@ pub mod subscriptions;
|
||||
pub mod trending;
|
||||
pub mod tts;
|
||||
pub mod twitch;
|
||||
pub mod user_bookmarks;
|
||||
pub mod user_ratings;
|
||||
pub mod vocoders;
|
||||
pub mod voice_clone_requests;
|
||||
pub mod voice_conversion;
|
||||
pub mod voice_designer;
|
||||
pub mod w2l;
|
||||
pub mod user_bookmarks;
|
||||
pub mod weights;
|
||||
pub mod image_gen;
|
||||
pub(crate) mod mocap;
|
||||
pub(crate) mod workflows;
|
||||
+2
-1
@@ -15,6 +15,7 @@ use utoipa::ToSchema;
|
||||
|
||||
use enums::by_table::generic_inference_jobs::inference_category::InferenceCategory;
|
||||
use enums::by_table::generic_inference_jobs::inference_model_type::InferenceModelType;
|
||||
use enums::common::visibility::Visibility;
|
||||
use http_server_common::request::get_request_header_optional::get_request_header_optional;
|
||||
use http_server_common::request::get_request_ip::get_request_ip;
|
||||
use mysql_queries::payloads::generic_inference_args::generic_inference_args::{
|
||||
@@ -202,7 +203,7 @@ pub async fn enqueue_tts_request(
|
||||
maybe_creator_user_token: maybe_user_token.as_ref(),
|
||||
maybe_avt_token: maybe_avt_token.as_ref(),
|
||||
creator_ip_address: &ip_address,
|
||||
creator_set_visibility: enums::common::visibility::Visibility::Public,
|
||||
creator_set_visibility: Visibility::Public,
|
||||
priority_level,
|
||||
requires_keepalive: true, // do we need this? I think so
|
||||
is_debug_request,
|
||||
|
||||
@@ -26,11 +26,13 @@ use crate::http_server::endpoints::categories::tts::list_tts_model_assigned_cate
|
||||
use crate::http_server::endpoints::comments::create_comment_handler::create_comment_handler;
|
||||
use crate::http_server::endpoints::comments::delete_comment_handler::delete_comment_handler;
|
||||
use crate::http_server::endpoints::comments::list_comments_handler::list_comments_handler;
|
||||
use crate::http_server::endpoints::conversion::enqueue_fbx_to_gltf_handler::enqueue_fbx_to_gltf_handler;
|
||||
use crate::http_server::endpoints::download_job::enqueue_generic_download::enqueue_generic_download_handler;
|
||||
use crate::http_server::endpoints::download_job::get_generic_upload_job_status::get_generic_download_job_status_handler;
|
||||
use crate::http_server::endpoints::events::list_events::list_events_handler;
|
||||
use crate::http_server::endpoints::flags::design_refresh_flag::disable_design_refresh_flag_handler::disable_design_refresh_flag_handler;
|
||||
use crate::http_server::endpoints::flags::design_refresh_flag::enable_design_refresh_flag_handler::enable_design_refresh_flag_handler;
|
||||
use crate::http_server::endpoints::image_gen::enqueue_image_generation::enqueue_image_generation_request;
|
||||
use crate::http_server::endpoints::inference_job::get_inference_job_status::get_inference_job_status_handler;
|
||||
use crate::http_server::endpoints::inference_job::get_pending_inference_job_count::get_pending_inference_job_count_handler;
|
||||
use crate::http_server::endpoints::inference_job::kill_inference_jobs::kill_generic_inference_jobs_handler;
|
||||
@@ -55,7 +57,6 @@ use crate::http_server::endpoints::misc::enable_alpha_easy_handler::enable_alpha
|
||||
use crate::http_server::endpoints::misc::enable_alpha_handler::enable_alpha_handler;
|
||||
use crate::http_server::endpoints::misc::root_index::get_root_index;
|
||||
use crate::http_server::endpoints::mocap::enqueue_mocapnet::enqueue_mocapnet_handler;
|
||||
use crate::http_server::endpoints::workflows::enqueue_comfy_ui::enqueue_comfy_ui_handler;
|
||||
use crate::http_server::endpoints::moderation::approval::pending_w2l_templates::get_pending_w2l_templates_handler;
|
||||
use crate::http_server::endpoints::moderation::categories::delete_category::delete_category_handler;
|
||||
use crate::http_server::endpoints::moderation::categories::edit_category::edit_category_handler;
|
||||
@@ -167,7 +168,7 @@ use crate::http_server::endpoints::weights::list_weights_by_user::list_weights_b
|
||||
use crate::http_server::endpoints::weights::search_model_weights_handler::search_model_weights_handler;
|
||||
use crate::http_server::endpoints::weights::set_model_weight_cover_image::set_model_weight_cover_image_handler;
|
||||
use crate::http_server::endpoints::weights::update_weight::update_weight_handler;
|
||||
use crate::http_server::endpoints::image_gen::enqueue_image_generation::enqueue_image_generation_request;
|
||||
use crate::http_server::endpoints::workflows::enqueue_comfy_ui::enqueue_comfy_ui_handler;
|
||||
|
||||
pub fn add_routes<T, B> (app: App<T>, server_environment: ServerEnvironment) -> App<T>
|
||||
where
|
||||
@@ -250,6 +251,12 @@ pub fn add_routes<T, B> (app: App<T>, server_environment: ServerEnvironment) ->
|
||||
.add_get("/v1/model_inference/queue_length", get_pending_inference_job_count_handler)
|
||||
.into_app();
|
||||
|
||||
// ==================== Format Conversion ====================
|
||||
|
||||
let mut app = RouteBuilder::from_app(app)
|
||||
.add_post("/v1/conversion/enqueue_fbx_to_gltf", enqueue_fbx_to_gltf_handler)
|
||||
.into_app();
|
||||
|
||||
// ==================== Stats ====================
|
||||
|
||||
let mut app = RouteBuilder::from_app(app)
|
||||
|
||||
Reference in new issue
Block a user