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