From f14a93501273c5a6dec9d42e080c1b1635c4eb7d Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Fri, 4 Jun 2021 02:46:18 -0400 Subject: [PATCH] new endpoint to report w2l inference status --- .../w2l/get_w2l_inference_job_status.rs | 188 ++++++++++++++++++ src/http_server/endpoints/w2l/mod.rs | 1 + src/main.rs | 6 + 3 files changed, 195 insertions(+) create mode 100644 src/http_server/endpoints/w2l/get_w2l_inference_job_status.rs diff --git a/src/http_server/endpoints/w2l/get_w2l_inference_job_status.rs b/src/http_server/endpoints/w2l/get_w2l_inference_job_status.rs new file mode 100644 index 0000000000..621e6240a4 --- /dev/null +++ b/src/http_server/endpoints/w2l/get_w2l_inference_job_status.rs @@ -0,0 +1,188 @@ +use actix_http::Error; +use actix_http::http::header; +use actix_web::cookie::Cookie; +use actix_web::dev::HttpResponseBuilder; +use actix_web::error::ResponseError; +use actix_web::http::StatusCode; +use actix_web::web::Path; +use actix_web::{Responder, web, HttpResponse, error, HttpRequest, HttpMessage}; +use chrono::{DateTime, Utc}; +use crate::AnyhowResult; +use crate::common_queries::sessions::create_session_for_user; +use crate::http_server::endpoints::users::create_account::CreateAccountError::{BadInput, ServerError, UsernameTaken, EmailTaken}; +use crate::http_server::endpoints::users::login::LoginSuccessResponse; +use crate::http_server::web_utils::ip_address::get_request_ip; +use crate::http_server::web_utils::session_checker::SessionRecord; +use crate::server_state::ServerState; +use crate::util::random_crockford_token::random_crockford_token; +use crate::validations::passwords::validate_passwords; +use crate::validations::username::validate_username; +use derive_more::{Display, Error}; +use log::{info, warn, log}; +use regex::Regex; +use sqlx::MySqlPool; +use sqlx::error::DatabaseError; +use sqlx::error::Error::Database; +use sqlx::mysql::MySqlDatabaseError; +use std::sync::Arc; + +/// For the URL PathInfo +#[derive(Deserialize)] +pub struct GetW2lInferenceStatusPathInfo { + token: String, +} + +#[derive(Serialize)] +pub struct W2lInferenceJobStatusForResponse { + pub job_token: String, + + pub status: String, + pub maybe_result_token: Option, + pub maybe_public_bucket_video_path: Option, + + pub maybe_w2l_template_token: Option, + pub w2l_template_type: String, + pub title: String, + + pub created_at: DateTime, + pub updated_at: DateTime, +} + +#[derive(Serialize)] +pub struct GetW2lInferenceStatusSuccessResponse { + pub success: bool, + pub state: W2lInferenceJobStatusForResponse, +} + +#[derive(Serialize)] +pub struct ErrorResponse { + pub success: bool, + pub error_reason: String, +} + +#[derive(Debug, Display)] +pub enum GetW2lInferenceStatusError { + ServerError, +} + +#[derive(Serialize)] +pub struct W2lInferenceJobStatusRecord { + pub job_token: String, + + pub status: String, + pub maybe_result_token: Option, + pub maybe_public_bucket_video_path: Option, + + pub maybe_w2l_template_token: Option, + pub w2l_template_type: String, + + pub title: String, + + pub created_at: DateTime, + pub updated_at: DateTime, +} + +impl ResponseError for GetW2lInferenceStatusError { + fn status_code(&self) -> StatusCode { + match *self { + GetW2lInferenceStatusError::ServerError=> StatusCode::INTERNAL_SERVER_ERROR, + } + } + + fn error_response(&self) -> HttpResponse { + let error_reason = match self { + GetW2lInferenceStatusError::ServerError => "server error".to_string(), + }; + + let response = ErrorResponse { + success: false, + error_reason, + }; + + let body = match serde_json::to_string(&response) { + Ok(json) => json, + Err(_) => "{}".to_string(), + }; + + HttpResponseBuilder::new(self.status_code()) + .set_header(header::CONTENT_TYPE, "application/json") + .body(body) + } +} + +pub async fn get_w2l_inference_job_status_handler( + http_request: HttpRequest, + path: Path, + server_state: web::Data>) -> Result +{ + // NB: Lookup failure is Err(RowNotFound). + // NB: Since this is publicly exposed, we don't query sensitive data. + let maybe_status = sqlx::query_as!( + W2lInferenceJobStatusRecord, + r#" +SELECT + jobs.token as job_token, + + jobs.status, + jobs.on_success_result_token as maybe_result_token, + results.public_bucket_video_path as maybe_public_bucket_video_path, + + jobs.maybe_w2l_template_token, + w2l.template_type as w2l_template_type, + w2l.title, + + jobs.created_at, + jobs.updated_at + +FROM w2l_inference_jobs as jobs +JOIN w2l_templates as w2l + ON w2l.token = jobs.maybe_w2l_template_token +LEFT OUTER JOIN w2l_results as results + ON jobs.on_success_result_token = results.token + +WHERE jobs.token = ? + "#, + &path.token + ) + .fetch_one(&server_state.mysql_pool) + .await; // TODO: This will return error if it doesn't exist + + let record : W2lInferenceJobStatusRecord = match maybe_status { + Ok(record) => record, + Err(err) => { + match err { + RowNotFound => { + return Err(GetW2lInferenceStatusError::ServerError); + }, + _ => { + warn!("w2l template query error: {:?}", err); + return Err(GetW2lInferenceStatusError::ServerError); + } + } + } + }; + + let template_for_response = W2lInferenceJobStatusForResponse { + job_token: record.job_token.clone(), + status: record.status.clone(), + maybe_result_token: record.maybe_result_token.clone(), + maybe_public_bucket_video_path: record.maybe_public_bucket_video_path.clone(), + maybe_w2l_template_token: record.maybe_w2l_template_token.clone(), + w2l_template_type: record.w2l_template_type.clone(), + title: record.title.clone(), + created_at: record.created_at.clone(), + updated_at: record.updated_at.clone(), + }; + + let response = GetW2lInferenceStatusSuccessResponse { + success: true, + state: template_for_response, + }; + + let body = serde_json::to_string(&response) + .map_err(|e| GetW2lInferenceStatusError::ServerError)?; + + Ok(HttpResponse::Ok() + .content_type("application/json") + .body(body)) +} diff --git a/src/http_server/endpoints/w2l/mod.rs b/src/http_server/endpoints/w2l/mod.rs index eded8523e8..7003d06b14 100644 --- a/src/http_server/endpoints/w2l/mod.rs +++ b/src/http_server/endpoints/w2l/mod.rs @@ -1,6 +1,7 @@ pub mod enqueue_infer_w2l; pub mod enqueue_infer_w2l_with_uploads; pub mod enqueue_upload_w2l_template; +pub mod get_w2l_inference_job_status; pub mod get_w2l_result; pub mod get_w2l_template; pub mod list_w2l_templates; \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 5b44cb9f7a..2c13864646 100644 --- a/src/main.rs +++ b/src/main.rs @@ -62,6 +62,7 @@ use crate::http_server::endpoints::users::list_user_tts_models::list_user_tts_mo use crate::http_server::endpoints::tts::get_tts_result::get_tts_inference_result_handler; use crate::http_server::endpoints::tts::get_tts_model::get_tts_model_handler; use crate::http_server::endpoints::tts::get_tts_inference_job_status::get_tts_inference_job_status_handler; +use crate::http_server::endpoints::w2l::get_w2l_inference_job_status::get_w2l_inference_job_status_handler; // TODO TODO TODO TODO // TODO TODO TODO TODO @@ -320,6 +321,11 @@ pub async fn serve(server_state: ServerState) -> AnyhowResult<()> .route(web::get().to(get_w2l_inference_result_handler)) .route(web::head().to(|| HttpResponse::Ok())) ) + .service( + web::resource("/job/{token}") + .route(web::get().to(get_w2l_inference_job_status_handler)) + .route(web::head().to(|| HttpResponse::Ok())) + ) ) .service( web::resource("/profile/{username}")