diff --git a/crates/service/web/dummy_service/src/endpoints/dummy_queue_stats_handler.rs b/crates/service/web/dummy_service/src/endpoints/dummy_queue_stats_handler.rs new file mode 100644 index 0000000000..48ad6e6944 --- /dev/null +++ b/crates/service/web/dummy_service/src/endpoints/dummy_queue_stats_handler.rs @@ -0,0 +1,78 @@ +use std::time::Duration; + +use actix_web::HttpResponse; +use chrono::{NaiveDateTime, Utc}; +use serde_derive::Serialize; + +/// How often the client should poll +const REFRESH_INTERVAL: Duration = Duration::from_secs(60); + +#[derive(Serialize)] +pub struct GetUnifiedQueueStatsSuccessResponse { + pub success: bool, + pub cache_time: NaiveDateTime, + + /// Tell the frontend client how fast to refresh their view of this list. + /// During an attack, we may want this to go extremely slow. + pub refresh_interval_millis: u64, + + pub inference: ModernInferenceQueueStats, + pub legacy_tts: LegacyQueueDetails, +} + +#[derive(Serialize)] +pub struct LegacyQueueDetails { + pub pending_job_count: u64, +} + +#[derive(Serialize)] +pub struct ModernInferenceQueueStats { + pub total_pending_job_count: u64, + + #[deprecated(note="the frontend uses this field, but we should switch to total_pending_job_count")] + pub pending_job_count: u64, + + pub by_queue: ByQueueStats, +} + +#[derive(Serialize)] +pub struct ByQueueStats { + pub pending_face_animation_jobs: u64, + pub pending_rvc_jobs: u64, + pub pending_svc_jobs: u64, + pub pending_tacotron2_jobs: u64, + pub pending_voice_designer: u64, + pub pending_stable_diffusion: u64, +} + +pub async fn dummy_queue_stats_handler() -> HttpResponse { + let response = GetUnifiedQueueStatsSuccessResponse { + success: true, + cache_time: Utc::now().naive_utc(), + refresh_interval_millis: REFRESH_INTERVAL.as_millis() as u64, + inference: ModernInferenceQueueStats { + total_pending_job_count: 12_345, + pending_job_count: 12_345, + by_queue: ByQueueStats { + pending_face_animation_jobs: 12_345, + pending_rvc_jobs: 12_345, + pending_svc_jobs: 12_345, + pending_tacotron2_jobs: 12_345, + pending_voice_designer: 12_345, + pending_stable_diffusion: 12_345, + } + }, + legacy_tts: LegacyQueueDetails { + pending_job_count: 12_345, + }, + }; + + match serde_json::to_string(&response) { + Ok(body) => HttpResponse::Ok() + .content_type("application/json") + .body(body), + Err(_err) => HttpResponse::Ok() + .content_type("application/json") + .body("{\"success\": false}"), + } +} diff --git a/crates/service/web/dummy_service/src/endpoints/mod.rs b/crates/service/web/dummy_service/src/endpoints/mod.rs index b3973a4f38..aa0485d8b8 100644 --- a/crates/service/web/dummy_service/src/endpoints/mod.rs +++ b/crates/service/web/dummy_service/src/endpoints/mod.rs @@ -1,3 +1,5 @@ pub mod dummy_health_check_handler; -pub mod simple_handler; +pub mod dummy_queue_stats_handler; +pub mod root_handler; +pub mod simple_pushback_handler; pub mod status_alert_handler; \ No newline at end of file diff --git a/crates/service/web/dummy_service/src/endpoints/root_handler.rs b/crates/service/web/dummy_service/src/endpoints/root_handler.rs new file mode 100644 index 0000000000..c6bd79adb3 --- /dev/null +++ b/crates/service/web/dummy_service/src/endpoints/root_handler.rs @@ -0,0 +1,19 @@ +use std::sync::Arc; + +use actix_web::http::StatusCode; +use actix_web::HttpResponse; +use actix_web::web::Data; + +use crate::server_state::ServerState; + +pub async fn root_handler(server_state: Data>) -> HttpResponse { + let body = format!(" \ +

We're Sorry! We appear to be having an outage!

\ +

Wondering what's up? Join our Discord to find out!

\ +

Maybe you want to work with us? We can pay! Get in touch!

\ +

storyteller-web instance: {}

\ + ", &server_state.hostname); + HttpResponse::build(StatusCode::OK) + .content_type("text/html; charset=utf-8") + .body(body) +} diff --git a/crates/service/web/dummy_service/src/endpoints/simple_handler.rs b/crates/service/web/dummy_service/src/endpoints/simple_handler.rs deleted file mode 100644 index e320ae0841..0000000000 --- a/crates/service/web/dummy_service/src/endpoints/simple_handler.rs +++ /dev/null @@ -1,8 +0,0 @@ -use actix_http::StatusCode; -use actix_web::HttpResponse; - -pub async fn simple_handler() -> HttpResponse { - HttpResponse::build(StatusCode::OK) - .content_type("application/json; charset=utf-8") - .body("{\"success\": true}") -} diff --git a/crates/service/web/dummy_service/src/endpoints/simple_pushback_handler.rs b/crates/service/web/dummy_service/src/endpoints/simple_pushback_handler.rs new file mode 100644 index 0000000000..b40278f14c --- /dev/null +++ b/crates/service/web/dummy_service/src/endpoints/simple_pushback_handler.rs @@ -0,0 +1,9 @@ +use actix_http::StatusCode; +use actix_web::HttpResponse; + +/// Send clients 429 Too Many Requests responses so that they back off. +pub async fn simple_pushback_handler() -> HttpResponse { + HttpResponse::build(StatusCode::TOO_MANY_REQUESTS) + .content_type("application/json; charset=utf-8") + .body("{\"success\": false}") +} diff --git a/crates/service/web/dummy_service/src/main.rs b/crates/service/web/dummy_service/src/main.rs index 595935f66d..55bc8e2bba 100644 --- a/crates/service/web/dummy_service/src/main.rs +++ b/crates/service/web/dummy_service/src/main.rs @@ -1,6 +1,7 @@ //! This service is meant to help with debugging. use std::sync::Arc; + use actix_http::body::MessageBody; use actix_service::ServiceFactory; use actix_web::{App, Error, HttpServer, web}; @@ -13,7 +14,9 @@ use actix_helpers::route_builder::RouteBuilder; use errors::AnyhowResult; use crate::endpoints::dummy_health_check_handler::dummy_health_check_handler; -use crate::endpoints::simple_handler::simple_handler; +use crate::endpoints::dummy_queue_stats_handler::dummy_queue_stats_handler; +use crate::endpoints::root_handler::root_handler; +use crate::endpoints::simple_pushback_handler::simple_pushback_handler; use crate::endpoints::status_alert_handler::status_alert_handler; use crate::env_args::env_args; use crate::server_state::ServerState; @@ -29,21 +32,19 @@ pub const DEFAULT_RUST_LOG: &str = concat!( "http_server_common::request::get_request_ip=info," // Debug spams Rust logs ); +pub const LOG_FORMAT : &str = + "[dummy-service] [%{HOSTNAME}e] %{X-Forwarded-For}i \"%r\" %s %b \"%{Referer}i\" \"%{User-Agent}i\" %T"; + #[actix_web::main] async fn main() -> AnyhowResult<()> { easyenv::init_all_with_default_logging(Some(DEFAULT_RUST_LOG)); //let log_format = "[%{HOSTNAME}e] %a \"%r\" %s %b \"%{Referer}i\" \"%{User-Agent}i\" %T"; - let log_format = "[dummy-service] [%{HOSTNAME}e] %{X-Forwarded-For}i \"%r\" %s %b \"%{Referer}i\" \"%{User-Agent}i\" %T"; let env_args = env_args()?; - let server_hostname = hostname::get() - .ok() - .and_then(|h| h.into_string().ok()) - .unwrap_or("hostname-unknown".to_string()); - let server_state = ServerState::build(&env_args); + let server_hostname = server_state.hostname.clone(); // NB(bt,2024-03-24): This type is supposed to be deprecated. let old_server_environment = env_args.server_environment.clone(); @@ -55,7 +56,7 @@ async fn main() -> AnyhowResult<()> { let app = App::new() .app_data(Data::new(Arc::new(server_state.clone()))) .wrap(build_cors_config(old_server_environment)) - .wrap(Logger::new(&log_format)) + .wrap(Logger::new(LOG_FORMAT)) .wrap(DefaultHeaders::new() .add(("X-Backend-Hostname", server_hostname.as_str()))) .wrap(Compress::default()); @@ -71,7 +72,7 @@ async fn main() -> AnyhowResult<()> { let app = App::new() .app_data(Data::new(Arc::new(server_state.clone()))) .wrap(build_cors_config(old_server_environment)) - .wrap(Logger::new(&log_format)) + .wrap(Logger::new(LOG_FORMAT)) .wrap(DefaultHeaders::new() .add(("X-Backend-Hostname", server_hostname.as_str()))); @@ -98,9 +99,10 @@ fn build_routes (app: App) -> App >, { RouteBuilder::from_app(app) - .add_get("/", simple_handler) + .add_get("/", root_handler) .add_get("/_status", dummy_health_check_handler) + .add_get("/v1/stats/queues", dummy_queue_stats_handler) .add_get("/v1/status_alert_check", status_alert_handler) .into_app() - .default_service(web::route().to(simple_handler)) + .default_service(web::route().to(simple_pushback_handler)) } \ No newline at end of file diff --git a/crates/service/web/dummy_service/src/server_state.rs b/crates/service/web/dummy_service/src/server_state.rs index beb1638c6e..28e84f6c4a 100644 --- a/crates/service/web/dummy_service/src/server_state.rs +++ b/crates/service/web/dummy_service/src/server_state.rs @@ -2,6 +2,7 @@ use crate::env_args::EnvArgs; #[derive(Clone)] pub struct ServerState { + pub hostname: String, pub flags: StaticFeatureFlags, } @@ -16,7 +17,13 @@ pub struct StaticFeatureFlags { impl ServerState { pub fn build(args: &EnvArgs) -> Self { + let server_hostname = hostname::get() + .ok() + .and_then(|h| h.into_string().ok()) + .unwrap_or("hostname-unknown".to_string()); + Self { + hostname: server_hostname, flags: StaticFeatureFlags { maybe_status_alert_category: args.maybe_status_alert_category.clone(), maybe_status_alert_custom_message: args.maybe_status_alert_custom_message.clone(),