#![allow(unused)] #![allow(warnings)] use crate::database_control::*; use crate::time_checking_team::UserTime; use rand::*; use reqwest::{Client, ClientBuilder, Response}; use tokio::join; use tokio::time::*; use log; #[derive(Debug)] pub struct ServerHealth { pub server_on: bool, // the total status of server. Its value is decided by AND operation of ping_on and wallet_system_on // through is_server_on method. pub ping_on: bool, // ping test to server. pub wallet_system_on: bool, // check wallet system of server. pub waiting_maximum: u32, // maximum time for timer to wait until server works on again. the value will be null when the server works on. } impl ServerHealth { pub fn new() -> ServerHealth { // make an instance and initialize fields ServerHealth { server_on: false, ping_on: false, wallet_system_on: false, waiting_maximum: 0, } } } // to check the current server health and store data into database. pub async fn execute_server_health_check( usertime: &mut UserTime, serverhealth: &mut ServerHealth, client: &Client, ) -> Result<(), Box> { let mut rng = rand::rngs::OsRng; let mut waiting_time: u32; loop { update(serverhealth, usertime, &client).await?; if serverhealth.server_on == true { serverhealth.waiting_maximum = 0; // update_database(&serverhealth).await; break; } else { usertime.update_last_server().await; // whenever server is off, waiting_maximum increases a second // and thread sleeps for uniform distribution random number between 1sec and waiting_maximum. serverhealth.waiting_maximum += 1; waiting_time = rng.gen_range(1..=serverhealth.waiting_maximum); // update_database(&serverhealth).await; if waiting_time > 2 { log::warn!(">>> retry connection after {} second(s).", waiting_time); } sleep(Duration::from_secs(waiting_time as u64)).await; } } // println!("server health 완료"); Ok(()) } // check the server on or off async fn update( serverHealth: &mut ServerHealth, usertime: &mut UserTime, client: &Client, ) -> Result<(), Box> { let (r1, r2) = join!(check_ping(usertime, &client), check_wallet_system(&client)); serverHealth.ping_on = r1?; serverHealth.wallet_system_on = r2?; serverHealth.server_on = serverHealth.ping_on && serverHealth.wallet_system_on; Ok(()) } // test ping to server and record the last running time of server (/api, Weight 1) async fn check_ping( usertime: &mut UserTime, client: &Client, ) -> Result> { let response = client .get("https://api.binance.com/api/v3/ping") .send() .await; match response { Ok(T) => { let body = T.text_with_charset("utf-8").await?; if body.contains("{}") { Ok(true) } else { Ok(false) } } Err(e) => Ok(false), } } // check wallet system status (/sapi, Weight 1) async fn check_wallet_system( client: &Client, ) -> Result> { let response = client .get("https://api.binance.com/sapi/v1/system/status") .send() .await; match response { Ok(T) => { let body = T.text_with_charset("utf-8").await?; if body.contains("0") { Ok(true) } else { Ok(false) } } Err(E) => Ok(false), } } async fn update_database(serverhealth: &ServerHealth) { let table_name = String::from("serverhealth"); let mut record: Vec<(&str, &str)> = Vec::new(); let condition = vec![("id", "1")]; let mut server_on = serverhealth.server_on.to_string(); let mut ping_on = serverhealth.ping_on.to_string(); let mut wallet_system_on = serverhealth.wallet_system_on.to_string(); let mut waiting_maximum = serverhealth.waiting_maximum.to_string(); record.push(("server_on", server_on.as_str())); record.push(("ping_on", ping_on.as_str())); record.push(("wallet_system_on", wallet_system_on.as_str())); record.push(("waiting_maximum", waiting_maximum.as_str())); let mut delete_query_result = update_record(&table_name, &record, &condition).await; if delete_query_result.is_err() { loop { delete_query_result = update_record(&table_name, &record, &condition).await; if delete_query_result.is_ok() { break; } sleep(Duration::from_millis(10)).await; } } }