bit better error handling
This commit is contained in:
		| @@ -15,3 +15,4 @@ chrono = "0.4" | |||||||
| flate2 = "1.0.0" | flate2 = "1.0.0" | ||||||
| r2d2 = "0.8.9" | r2d2 = "0.8.9" | ||||||
| r2d2_postgres = "0.18.0" | r2d2_postgres = "0.18.0" | ||||||
|  | ansi_term = "0.12" | ||||||
|   | |||||||
| @@ -1,7 +1,9 @@ | |||||||
|  | use crate::error::Error; | ||||||
| use r2d2_postgres::postgres::NoTls; | use r2d2_postgres::postgres::NoTls; | ||||||
| use r2d2_postgres::PostgresConnectionManager; | use r2d2_postgres::PostgresConnectionManager; | ||||||
| use std::ops::Deref; | use std::ops::Deref; | ||||||
| use std::sync::{Arc, Mutex}; | use std::sync::{Arc, Mutex}; | ||||||
|  | use std::time::Duration; | ||||||
|  |  | ||||||
| pub enum Pool { | pub enum Pool { | ||||||
|     Postgres(r2d2::Pool<PostgresConnectionManager<NoTls>>), |     Postgres(r2d2::Pool<PostgresConnectionManager<NoTls>>), | ||||||
| @@ -13,16 +15,24 @@ pub enum Client { | |||||||
|  |  | ||||||
| static mut POOL: Option<Arc<Mutex<Pool>>> = None; | static mut POOL: Option<Arc<Mutex<Pool>>> = None; | ||||||
|  |  | ||||||
| pub fn init() { | pub fn init() -> Result<(), Error> { | ||||||
|     let manager = PostgresConnectionManager::new( |     let manager = PostgresConnectionManager::new( | ||||||
|         "host=localhost user=postgres dbname=test".parse().unwrap(), |         "host=localhost user=postgres dbname=test".parse().unwrap(), | ||||||
|         NoTls, |         NoTls, | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|     let pool = r2d2::Pool::new(manager).unwrap(); |     let pool = r2d2::Pool::builder() | ||||||
|  |         .max_size(64) | ||||||
|  |         .min_idle(Some(2)) | ||||||
|  |         .connection_timeout(Duration::from_secs(4)) | ||||||
|  |         .max_lifetime(Some(Duration::from_secs(3600))) | ||||||
|  |         .build(manager)?; | ||||||
|  |  | ||||||
|     unsafe { |     unsafe { | ||||||
|         POOL = Some(Arc::new(Mutex::new(Pool::Postgres(pool)))); |         POOL = Some(Arc::new(Mutex::new(Pool::Postgres(pool)))); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     Ok(()) | ||||||
| } | } | ||||||
|  |  | ||||||
| pub fn client() -> Client { | pub fn client() -> Client { | ||||||
|   | |||||||
							
								
								
									
										50
									
								
								src/error.rs
									
									
									
									
									
								
							
							
						
						
									
										50
									
								
								src/error.rs
									
									
									
									
									
								
							| @@ -1,34 +1,50 @@ | |||||||
|  |  | ||||||
| pub enum ErrorKind { | pub enum ErrorKind { | ||||||
|     InvalidEndpoint, |     InvalidEndpointError, | ||||||
|     JsonParseError, |     JsonParseError, | ||||||
|  |     DatabaseError, | ||||||
| } | } | ||||||
|  |  | ||||||
| pub struct Error { | pub struct Error { | ||||||
|     kind: ErrorKind, |     kind: ErrorKind, | ||||||
|  |     desc: Option<String>, | ||||||
| } | } | ||||||
|  |  | ||||||
| impl Error { | impl Error { | ||||||
|     pub fn new(kind: ErrorKind) -> Error { |     pub fn new(kind: ErrorKind) -> Error { | ||||||
|         Error { |         Error { kind, desc: None } | ||||||
|             kind, |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| impl From<serde_json::Error> for Error { |  | ||||||
|     fn from(_: serde_json::Error) -> Self { |  | ||||||
|         Error { |  | ||||||
|             kind: ErrorKind::JsonParseError, |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| impl ToString for Error { | impl ToString for Error { | ||||||
|     fn to_string(&self) -> String { |     fn to_string(&self) -> String { | ||||||
|         match self.kind { |         let mut error = match self.kind { | ||||||
|             ErrorKind::InvalidEndpoint => "invalid endpoint", |             ErrorKind::InvalidEndpointError => "invalid endpoint", | ||||||
|             ErrorKind::JsonParseError => "JSON parse error", |             ErrorKind::JsonParseError => "unable to parse JSON data", | ||||||
|         }.to_string() |             ErrorKind::DatabaseError => "unable to connect to database", | ||||||
|  |         } | ||||||
|  |         .to_string(); | ||||||
|  |         if let Some(desc) = &self.desc { | ||||||
|  |             error += ": "; | ||||||
|  |             error += desc; | ||||||
|  |         } | ||||||
|  |         error | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl From<serde_json::Error> for Error { | ||||||
|  |     fn from(error: serde_json::Error) -> Self { | ||||||
|  |         Error { | ||||||
|  |             kind: ErrorKind::JsonParseError, | ||||||
|  |             desc: Some(error.to_string()), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl From<r2d2::Error> for Error { | ||||||
|  |     fn from(error: r2d2::Error) -> Self { | ||||||
|  |         Error { | ||||||
|  |             kind: ErrorKind::DatabaseError, | ||||||
|  |             desc: Some(error.to_string()), | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										30
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								src/main.rs
									
									
									
									
									
								
							| @@ -3,16 +3,18 @@ use std::sync::Arc; | |||||||
| use std::sync::Mutex; | use std::sync::Mutex; | ||||||
| use std::thread; | use std::thread; | ||||||
|  |  | ||||||
|  | use ansi_term::Color; | ||||||
| use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod}; | use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod}; | ||||||
| use rusty_pool; | use rusty_pool; | ||||||
|  | use std::fmt::Formatter; | ||||||
| use std::time::Duration; | use std::time::Duration; | ||||||
|  |  | ||||||
| mod database; | mod database; | ||||||
|  | mod error; | ||||||
| mod http; | mod http; | ||||||
| mod udp; | mod udp; | ||||||
| mod usimp; | mod usimp; | ||||||
| mod websocket; | mod websocket; | ||||||
| mod error; |  | ||||||
|  |  | ||||||
| enum SocketType { | enum SocketType { | ||||||
|     Http, |     Http, | ||||||
| @@ -20,12 +22,24 @@ enum SocketType { | |||||||
|     Udp, |     Udp, | ||||||
| } | } | ||||||
|  |  | ||||||
|  | impl std::fmt::Display for SocketType { | ||||||
|  |     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||||||
|  |         write!(f, "{}", match self { | ||||||
|  |             SocketType::Http => "http+ws", | ||||||
|  |             SocketType::Https => "https+wss", | ||||||
|  |             SocketType::Udp => "udp", | ||||||
|  |         }) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| struct SocketConfig { | struct SocketConfig { | ||||||
|     address: SocketAddr, |     address: SocketAddr, | ||||||
|     socket_type: SocketType, |     socket_type: SocketType, | ||||||
| } | } | ||||||
|  |  | ||||||
| fn main() { | fn main() { | ||||||
|  |     println!("Locutus server"); | ||||||
|  |  | ||||||
|     let socket_configs: Vec<SocketConfig> = vec![ |     let socket_configs: Vec<SocketConfig> = vec![ | ||||||
|         SocketConfig { |         SocketConfig { | ||||||
|             address: "[::]:8080".parse().unwrap(), |             address: "[::]:8080".parse().unwrap(), | ||||||
| @@ -41,7 +55,13 @@ fn main() { | |||||||
|         }, |         }, | ||||||
|     ]; |     ]; | ||||||
|  |  | ||||||
|     database::init(); |     // Note: rust's stdout is line buffered! | ||||||
|  |     eprint!("Initializing database connection pool..."); | ||||||
|  |     if let Err(error) = database::init() { | ||||||
|  |         eprintln!("\n{}", Color::Red.bold().paint(error.to_string())); | ||||||
|  |         std::process::exit(1); | ||||||
|  |     } | ||||||
|  |     eprintln!(" {}", Color::Green.paint("success")); | ||||||
|  |  | ||||||
|     let thread_pool = rusty_pool::Builder::new() |     let thread_pool = rusty_pool::Builder::new() | ||||||
|         .core_size(4) |         .core_size(4) | ||||||
| @@ -55,6 +75,12 @@ fn main() { | |||||||
|     for socket_config in socket_configs { |     for socket_config in socket_configs { | ||||||
|         let thread_pool_mutex = thread_pool_mutex.clone(); |         let thread_pool_mutex = thread_pool_mutex.clone(); | ||||||
|  |  | ||||||
|  |         eprintln!( | ||||||
|  |             "Creating listening thread for {} ({})", | ||||||
|  |             ansi_term::Style::new().bold().paint(socket_config.address.to_string()), | ||||||
|  |             socket_config.socket_type | ||||||
|  |         ); | ||||||
|  |  | ||||||
|         threads.push(match socket_config.socket_type { |         threads.push(match socket_config.socket_type { | ||||||
|             SocketType::Http => thread::spawn(move || { |             SocketType::Http => thread::spawn(move || { | ||||||
|                 let mut tcp_socket = TcpListener::bind(socket_config.address).unwrap(); |                 let mut tcp_socket = TcpListener::bind(socket_config.address).unwrap(); | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ use crate::error::*; | |||||||
| pub fn endpoint(endpoint: &str, input: serde_json::Value) -> Result<serde_json::Value, Error> { | pub fn endpoint(endpoint: &str, input: serde_json::Value) -> Result<serde_json::Value, Error> { | ||||||
|     match endpoint { |     match endpoint { | ||||||
|         "echo" => Ok(serde_json::to_value(echo(serde_json::from_value(input)?))?), |         "echo" => Ok(serde_json::to_value(echo(serde_json::from_value(input)?))?), | ||||||
|         _ => Err(Error::new(ErrorKind::InvalidEndpoint)), |         _ => Err(Error::new(ErrorKind::InvalidEndpointError)), | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user