From a840e3c97e342c12efea5cb1d174679fe377a3da Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Fri, 27 Sep 2024 00:51:36 -0400 Subject: [PATCH] make sure dummy-service can continue serving during outages --- .../src/endpoints/dummy_app_state_handler.rs | 158 ++++++++++++++++++ .../web/dummy_service/src/endpoints/mod.rs | 1 + crates/service/web/dummy_service/src/main.rs | 3 +- 3 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 crates/service/web/dummy_service/src/endpoints/dummy_app_state_handler.rs diff --git a/crates/service/web/dummy_service/src/endpoints/dummy_app_state_handler.rs b/crates/service/web/dummy_service/src/endpoints/dummy_app_state_handler.rs new file mode 100644 index 0000000000..aba4a5cef9 --- /dev/null +++ b/crates/service/web/dummy_service/src/endpoints/dummy_app_state_handler.rs @@ -0,0 +1,158 @@ +use crate::server_state::ServerState; +use actix_web::web; +use actix_web::web::Json; +use serde_derive::Serialize; +use std::collections::BTreeSet; +use std::sync::Arc; +use std::time::Duration; + +/// How often the client should poll +const REFRESH_INTERVAL: Duration = Duration::from_secs(60); +#[derive(Serialize)] +pub struct AppStateResponse { + pub success: bool, + pub refresh_interval_millis: u128, + pub server_info: AppStateServerInfo, + pub maybe_alert: Option, + pub locale: AppStateUserLocale, + pub is_logged_in: bool, + pub is_banned: bool, + pub maybe_user_info: Option<()>, // Option, + pub permissions: AppStatePermissions, + pub maybe_premium: Option<()>, // Option, +} + +#[derive(Serialize)] +pub struct AppStateServerInfo { + pub build_sha: String, + pub build_sha_short: String, + pub hostname: String, +} + +#[derive(Serialize)] +pub struct AppStateStatusAlertInfo { + pub maybe_category: Option, + pub maybe_message: Option, +} + +#[derive(Serialize)] +pub enum AppStateStatusAlertCategory { + DownForMaintenance, +} + +#[derive(Serialize)] +pub struct AppStateUserLocale { + pub full_language_tags: Vec, + pub language_codes: Vec, +} + +#[derive(Serialize)] +pub struct AppStatePermissions { + pub is_moderator: bool, + pub feature_flags: BTreeSet, // pub feature_flags: BTreeSet, + pub legacy_permission_flags: AppStateLegacyPermissionFlags, +} + +#[derive(Serialize)] +pub struct AppStateLegacyPermissionFlags { + // Usage permissions: + pub can_use_tts: bool, + pub can_use_w2l: bool, + pub can_delete_own_tts_results: bool, + pub can_delete_own_w2l_results: bool, + pub can_delete_own_account: bool, + // Contribution permissions: + pub can_upload_tts_models: bool, + pub can_upload_w2l_templates: bool, + pub can_delete_own_tts_models: bool, + pub can_delete_own_w2l_templates: bool, + // Moderation permissions: + pub can_approve_w2l_templates: bool, + pub can_edit_other_users_profiles: bool, + pub can_edit_other_users_tts_models: bool, + pub can_edit_other_users_w2l_templates: bool, + pub can_delete_other_users_tts_models: bool, + pub can_delete_other_users_tts_results: bool, + pub can_delete_other_users_w2l_templates: bool, + pub can_delete_other_users_w2l_results: bool, + pub can_ban_users: bool, + pub can_delete_users: bool, +} + +pub async fn dummy_app_state_handler( + server_state: web::Data> +) -> Json { + + let maybe_category = server_state + .flags + .maybe_status_alert_category + .as_deref() + .map(|category| category_to_enum(&category)) + .flatten(); + + let maybe_message = server_state + .flags + .maybe_status_alert_custom_message + .as_deref() + .map(|message| message.trim().to_string()); + + let maybe_alert = match (maybe_category, maybe_message) { + (None, None) => None, + (category, message) => Some(AppStateStatusAlertInfo { + maybe_category: category, + maybe_message: message, + }), + }; + + Json(AppStateResponse { + success: true, + refresh_interval_millis: REFRESH_INTERVAL.as_millis(), + maybe_alert, + server_info: AppStateServerInfo { + build_sha: "aabbcc".to_string(), + build_sha_short: "aabbcc".to_string(), + hostname: "hostname".to_string(), + }, + locale: AppStateUserLocale { + full_language_tags: vec!["en-US".to_string()], + language_codes: vec!["en".to_string()], + }, + is_logged_in: false, + is_banned: false, + maybe_user_info: None, + maybe_premium: None, + permissions: AppStatePermissions { + is_moderator: false, + feature_flags: BTreeSet::new(), + legacy_permission_flags: AppStateLegacyPermissionFlags { + can_use_tts: false, + can_use_w2l: false, + can_delete_own_tts_results: false, + can_delete_own_w2l_results: false, + can_delete_own_account: false, + can_upload_tts_models: false, + can_upload_w2l_templates: false, + can_delete_own_tts_models: false, + can_delete_own_w2l_templates: false, + can_approve_w2l_templates: false, + can_edit_other_users_profiles: false, + can_edit_other_users_tts_models: false, + can_edit_other_users_w2l_templates: false, + can_delete_other_users_tts_models: false, + can_delete_other_users_tts_results: false, + can_delete_other_users_w2l_templates: false, + can_delete_other_users_w2l_results: false, + can_ban_users: false, + can_delete_users: false, + }, + }, + }) +} + +fn category_to_enum(category: &str) -> Option { + let key = category.trim(); + match key { + "down_for_maintenance" => Some(AppStateStatusAlertCategory::DownForMaintenance), + _ => None, + } +} diff --git a/crates/service/web/dummy_service/src/endpoints/mod.rs b/crates/service/web/dummy_service/src/endpoints/mod.rs index aa0485d8b8..81b00d5a9d 100644 --- a/crates/service/web/dummy_service/src/endpoints/mod.rs +++ b/crates/service/web/dummy_service/src/endpoints/mod.rs @@ -1,3 +1,4 @@ +pub mod dummy_app_state_handler; pub mod dummy_health_check_handler; pub mod dummy_queue_stats_handler; pub mod root_handler; diff --git a/crates/service/web/dummy_service/src/main.rs b/crates/service/web/dummy_service/src/main.rs index 60e10a1423..1bf1b9cba7 100644 --- a/crates/service/web/dummy_service/src/main.rs +++ b/crates/service/web/dummy_service/src/main.rs @@ -12,7 +12,7 @@ use actix_web::web::Data; use actix_cors_configs::cors::build_cors_config; use actix_helpers::route_builder::RouteBuilder; use errors::AnyhowResult; - +use crate::endpoints::dummy_app_state_handler::dummy_app_state_handler; use crate::endpoints::dummy_health_check_handler::dummy_health_check_handler; use crate::endpoints::dummy_queue_stats_handler::dummy_queue_stats_handler; use crate::endpoints::root_handler::root_handler; @@ -101,6 +101,7 @@ fn build_routes (app: App) -> App RouteBuilder::from_app(app) .add_get("/", root_handler) .add_get("/_status", dummy_health_check_handler) + .add_get("/v1/app_state", dummy_app_state_handler) .add_get("/v1/stats/queues", dummy_queue_stats_handler) .add_get("/v1/status_alert_check", status_alert_handler) .into_app()