Hopefully Fix Server getting stuck when main thread dies
All checks were successful
Run Tests on Code / run-tests (push) Successful in 0s
Build and Release Binary File / run-tests (push) Successful in 0s
Build and Release Binary File / build (push) Successful in 1m8s
Build and Release Binary File / upload-release (push) Successful in 13s

This commit is contained in:
Neshura 2023-12-12 20:39:34 +01:00
parent b3347a6e53
commit 75eefab02c
Signed by: Neshura
GPG key ID: B6983AAA6B9A7A6C

View file

@ -6,16 +6,18 @@ use dotenvy::dotenv;
use tokio::time::sleep; use tokio::time::sleep;
use std::{env, fs, net::Ipv4Addr, net::Ipv6Addr, time::Duration, sync::{Arc, atomic::{AtomicBool, Ordering}}}; use std::{env, fs, net::Ipv4Addr, net::Ipv6Addr, time::Duration, sync::{Arc, atomic::{AtomicBool, Ordering}}};
use std::process::abort;
use chrono::Local; use chrono::Local;
use actix_web::{middleware::Logger, web, App, HttpServer, Result}; use actix_web::{middleware::Logger, web, App, HttpServer};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use sqlx::{PgPool, Pool, Postgres, Connection}; use sqlx::{PgPool, Pool, Postgres, Connection};
use utoipa::{OpenApi, openapi::security::{SecurityScheme, ApiKey, ApiKeyValue}, Modify}; use utoipa::{OpenApi, openapi::security::{SecurityScheme, ApiKey, ApiKeyValue}, Modify};
use utoipa_swagger_ui::{Config, SwaggerUi, Url}; use utoipa_swagger_ui::{Config, SwaggerUi, Url};
mod db; mod db;
mod v1;
mod v2; mod v2;
mod v3; mod v3;
@ -65,8 +67,8 @@ pub struct AppState {
auth_tokens: AuthenticationTokens, auth_tokens: AuthenticationTokens,
} }
async fn postgres_watchdog(pool: PgPool, is_alive: Arc<AtomicBool>, shutdown: Arc<AtomicBool>) { async fn postgres_watchdog(pool: PgPool, shutdown: Arc<AtomicBool>) {
loop { while !shutdown.load(Ordering::Relaxed) {
let start = Local::now(); let start = Local::now();
let mut conn = match pool.acquire().await { let mut conn = match pool.acquire().await {
@ -94,31 +96,17 @@ async fn postgres_watchdog(pool: PgPool, is_alive: Arc<AtomicBool>, shutdown: Ar
while Local::now() - start < chrono::Duration::seconds(15) { while Local::now() - start < chrono::Duration::seconds(15) {
sleep(Duration::from_millis(100)).await; sleep(Duration::from_millis(100)).await;
if shutdown.load(Ordering::Relaxed) {
break;
}
}
if shutdown.load(Ordering::Relaxed) {
break;
} }
} }
is_alive.store(false, Ordering::Relaxed);
} }
#[actix_web::main] #[actix_web::main]
async fn main() -> Result<()> { async fn main() {
env_logger::init(); env_logger::init();
dotenv().ok(); dotenv().ok();
let shutdown: Arc<AtomicBool> = Arc::new(AtomicBool::new(false)); let shutdown: Arc<AtomicBool> = Arc::new(AtomicBool::new(false));
let shutdown_clone = Arc::clone(&shutdown);
ctrlc::set_handler(move || {
eprintln!("Ctrl-C received");
shutdown_clone.store(true, Ordering::Relaxed)
})
.expect("Error setting Ctrl-C handler");
let toml_str = fs::read_to_string("config.toml").expect("Failed to read config.toml"); let toml_str = fs::read_to_string("config.toml").expect("Failed to read config.toml");
let config: ConfigToml = toml::from_str(&toml_str).expect("Failed to parse config.toml"); let config: ConfigToml = toml::from_str(&toml_str).expect("Failed to parse config.toml");
@ -322,36 +310,16 @@ async fn main() -> Result<()> {
.config(swagger_config.clone()), .config(swagger_config.clone()),
) )
}) })
.bind((Ipv6Addr::UNSPECIFIED, config.port.default)).expect("Port or IP already occupied") .bind((Ipv6Addr::UNSPECIFIED, config.port.default)).expect("Port or IP already occupied")
.run(); .run()
.await;
let server_thread = tokio::spawn(async { watchdog_thread.abort();
println!("Awaiting server");
let _ = server.await;
println!("Stopped awaiting server");
});
println!("Started Serving API on: "); sleep(Duration::from_secs(10)).await;
println!(" -> http://[{}]:{}", Ipv6Addr::UNSPECIFIED, 8080);
println!(" -> http://{}:{}", Ipv4Addr::UNSPECIFIED, 8080);
let is_alive_clone = Arc::clone(&is_alive); println!("Service crashed due to unexpected Error, restarting thread after wait...");
let shutdown_clone = Arc::clone(&shutdown);
let _ = tokio::spawn(async move { postgres_watchdog(pool_copy, is_alive_clone, shutdown_clone).await });
//watchdog_thread.await; sleep(Duration::from_secs(10)).await;
while is_alive.load(Ordering::Relaxed) {
sleep(Duration::from_millis(200)).await;
}
if shutdown.load(Ordering::Relaxed) {
break;
}
eprintln!("Connection died, restarting Server");
server_thread.abort();
} }
Ok(())
} }