this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

refactor: further size optimisations

+124 -38
+2 -2
server/src/database.rs
··· 19 19 * You should have received a copy of the GNU Affero General Public License 20 20 * along with this program. If not, see <https://www.gnu.org/licenses/>. 21 21 */ 22 - 22 + use crate::EnvVar::*; 23 23 use crate::errors::LuminaError::{self}; 24 24 use crate::helpers::events::EventLogger; 25 25 use crate::timeline; ··· 84 84 // Parse the port as u16, if it fails, return an error 85 85 pg_config.port(port.parse::<u16>().map_err(|_| { 86 86 LuminaError::ConfInvalid( 87 - "LUMINA_POSTGRES_PORT is not a valid integer number".to_string(), 87 + LUMINA_POSTGRES_PORT, 88 88 ) 89 89 })?); 90 90 match std::env::var("LUMINA_POSTGRES_HOST") {
+25 -11
server/src/errors.rs
··· 22 22 23 23 #[derive(Debug)] 24 24 pub(crate) enum LuminaError { 25 - ConfInvalid(String), 25 + ConfInvalid(crate::EnvVar), 26 26 DbError(LuminaDbError), 27 27 Bb8RunErrorPg(bb8::RunError<crate::postgres::Error>), 28 - Bb8RunErrorRedis(bb8::RunError<redis::RedisError>), 28 + Bb8RunErrorRedis(Box<bb8::RunError<redis::RedisError>>), 29 29 Unknown, 30 30 RocketFaillure(Box<rocket::Error>), 31 31 BcryptError, 32 32 RegisterEmailInUse, 33 33 RegisterUsernameInUse, 34 34 RegisterEmailNotValid, 35 - RegisterUsernameInvalid(String), 36 - RegisterPasswordNotValid(String), 35 + RegisterUsernameInvalid(crate::user::OnRegisterUsernameInvalid), 36 + RegisterPasswordNotValid(crate::user::OnRegisterPasswordNotValid), 37 37 AuthenticationWrongPassword, 38 38 UUidError, 39 39 RegexError, 40 - SerializationError(String), 40 + SerializationError(serde_json::Error), 41 41 JoinFaillure, 42 42 } 43 43 ··· 49 49 50 50 #[derive(Debug)] 51 51 pub(crate) enum LuminaDbError { 52 - Redis(redis::RedisError), 52 + Redis(Box<redis::RedisError>), 53 53 Postgres(crate::postgres::Error), 54 54 } 55 55 56 56 impl From<rocket::Error> for LuminaError { 57 57 fn from(err: rocket::Error) -> Self { 58 58 LuminaError::RocketFaillure(Box::new(err)) 59 + } 60 + } 61 + 62 + impl From<serde_json::Error> for LuminaError { 63 + fn from(err: serde_json::Error) -> Self { 64 + LuminaError::SerializationError(err) 59 65 } 60 66 } 61 67 ··· 67 73 68 74 impl From<redis::RedisError> for LuminaError { 69 75 fn from(err: redis::RedisError) -> Self { 70 - LuminaError::DbError(LuminaDbError::Redis(err)) 76 + LuminaError::DbError(LuminaDbError::Redis(Box::new(err))) 71 77 } 72 78 } 73 79 impl From<bb8::RunError<crate::postgres::Error>> for LuminaError { ··· 77 83 } 78 84 impl From<bb8::RunError<redis::RedisError>> for LuminaError { 79 85 fn from(err: bb8::RunError<redis::RedisError>) -> Self { 80 - LuminaError::Bb8RunErrorRedis(err) 86 + LuminaError::Bb8RunErrorRedis(Box::new(err)) 81 87 } 82 88 } 83 - impl ToString for LuminaError { 84 - fn to_string(&self) -> String { 89 + 90 + impl std::fmt::Display for LuminaError { 91 + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 92 + write!(f, "{}", 85 93 match self { 86 - LuminaError::ConfInvalid(s) => format!("Configuration invalid: {}", s), 94 + LuminaError::ConfInvalid(s) => match s { 95 + crate::EnvVar::LUMINA_SERVER_ADDR => "LUMINA_SERVER_ADDR is an invalid address".to_string(), 96 + crate::EnvVar::LUMINA_SERVER_PORT => "LUMINA_SERVER_PORT is not a valid port number".to_string(), 97 + crate::EnvVar::LUMINA_POSTGRES_PORT => "LUMINA_POSTGRES_PORT is not a valid port number".to_string(), 98 + }, 99 + 87 100 LuminaError::DbError(e) => match e { 88 101 LuminaDbError::Redis(re) => format!("Redis error: {}", re), 89 102 LuminaDbError::Postgres(pe) => format!("Postgres error: {}", pe), ··· 104 117 LuminaError::JoinFaillure => "Process join failure".to_string(), 105 118 LuminaError::Unknown => "Unknown error".to_string(), 106 119 } 120 + ) 107 121 } 108 122 }
+24 -5
server/src/main.rs
··· 12 12 * it under the terms of the GNU Affero General Public License as published 13 13 * by the Free Software Foundation, either version 3 of the License, or 14 14 * (at your option) any later version. 15 - * 15 + *w 16 16 * This program is distributed in the hope that it will be useful, 17 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ··· 56 56 port: u16, 57 57 host: IpAddr, 58 58 } 59 + 60 + #[allow(non_camel_case_types)] 61 + #[derive(Debug, Clone, Copy)] 62 + enum EnvVar { 63 + LUMINA_SERVER_ADDR, 64 + LUMINA_SERVER_PORT, 65 + LUMINA_POSTGRES_PORT, 66 + } 67 + impl std::fmt::Display for EnvVar { 68 + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 69 + write!(f, "{}", 70 + match self { 71 + EnvVar::LUMINA_SERVER_ADDR => "LUMINA_SERVER_ADDR", 72 + EnvVar::LUMINA_SERVER_PORT => "LUMINA_SERVER_PORT", 73 + EnvVar::LUMINA_POSTGRES_PORT => "LUMINA_POSTGRES_PORT", 74 + } 75 + ) 76 + }} 77 + use crate::EnvVar::*; 59 78 use crate::database::{DatabaseConnections, PgConn}; 60 79 use crate::errors::LuminaError; 61 80 use cynthia_con::{CynthiaColors, CynthiaStyles}; ··· 66 85 let addr = { 67 86 let s = std::env::var("LUMINA_SERVER_ADDR").unwrap_or(String::from("127.0.0.1")); 68 87 s.parse::<IpAddr>() 69 - .map_err(|_| LuminaError::ConfInvalid("LUMINA_SERVER_ADDR".to_string()))? 88 + .map_err(|_| LuminaError::ConfInvalid(LUMINA_SERVER_ADDR))? 70 89 }; 71 90 let port = { 72 91 let s = std::env::var("LUMINA_SERVER_PORT").unwrap_or(String::from("8085")); 73 92 s.parse::<u16>() 74 - .map_err(|_| LuminaError::ConfInvalid("LUMINA_SERVER_PORT".to_string()))? 93 + .map_err(|_| LuminaError::ConfInvalid(LUMINA_SERVER_PORT))? 75 94 }; 76 95 Ok(ServerConfig { port, host: addr }) 77 96 } ··· 123 142 error_elog!( 124 143 ev_log, 125 144 "Invalid environment variable: {}", 126 - a.color_bright_orange() 145 + a.to_string().color_bright_orange() 127 146 ); 128 147 None 129 148 } ··· 427 446 error_elog!( 428 447 ev_log, 429 448 "Invalid environment variable: {}", 430 - a.color_bright_orange() 449 + a.to_string().color_bright_orange() 431 450 ); 432 451 process::exit(1); 433 452 }
+18 -7
server/src/tests.rs
··· 97 97 #[test] 98 98 fn print_sizes() { 99 99 println!("Size of LuminaError: {} bytes", mem::size_of::<LuminaError>()); 100 - println!("Size of Rocket Error: {} bytes", mem::size_of::<rocket::Error>()); 101 - println!("Size of Postgres Error: {} bytes", mem::size_of::<crate::postgres::Error>()); 102 - println!("Size of Redis Error: {} bytes", mem::size_of::<redis::RedisError>()); 103 - println!("Size of DbError: {} bytes", mem::size_of::<crate::errors::LuminaDbError>()); 104 - println!("Size of bb8 RunError Postgres: {} bytes", mem::size_of::<bb8::RunError<crate::postgres::Error>>()); 105 - println!("Size of bb8 RunError Redis: {} bytes", mem::size_of::<bb8::RunError<redis::RedisError>>()); 106 - println!("Size of String: {} bytes", mem::size_of::<String>()); 100 + println!("Size of errors::LuminaDbError: {} bytes", mem::size_of::<crate::errors::LuminaDbError>()); 101 + println!("Size of EnvVar: {} bytes", mem::size_of::<crate::EnvVar>()); 102 + println!("Size of InnerAppState: {} bytes", mem::size_of::<crate::InnerAppState>()); 103 + } 104 + 105 + #[test] 106 + fn test_error_sizes() { 107 + // We want to keep our error types small to minimize overhead when passing them around. 108 + assert!(mem::size_of::<LuminaError>() <= 16, "LuminaError should be 16 bytes or less"); 109 + assert!(mem::size_of::<crate::errors::LuminaDbError>() <= 16, "LuminaDbError should be 16 bytes or less"); 107 110 } 111 + 112 + #[test] 113 + fn test_appstate_size() { 114 + // Appstate is moved around a lot, so we want to keep it small, which is pretty easy since it just holds a single Arc pointer to a InnerAppState. 115 + assert!(mem::size_of::<crate::AppState>() <= 8, "AppState should be 8 bytes or less"); 116 + // This constraint should lower over time as we optimize InnerAppState 117 + assert!(mem::size_of::<crate::InnerAppState>() <= 88, "InnerAppState should be 88 bytes or less"); 118 + }
+2 -3
server/src/timeline.rs
··· 93 93 94 94 let cache_key = get_cache_key(timeline_id, page); 95 95 let serialized = serde_json::to_string(&cached_page) 96 - .map_err(|e| LuminaError::SerializationError(e.to_string()))?; 96 + ?; 97 97 98 98 let _: () = redis::cmd("SETEX") 99 99 .arg(cache_key) ··· 132 132 133 133 match cached_data { 134 134 Some(data) => { 135 - let cached_page: CachedTimelinePage = serde_json::from_str(&data) 136 - .map_err(|e| LuminaError::SerializationError(e.to_string()))?; 135 + let cached_page: CachedTimelinePage = serde_json::from_str(&data)?; 137 136 Ok(Some(cached_page)) 138 137 } 139 138 None => Ok(None),
+53 -10
server/src/user.rs
··· 352 352 .all(char::is_alphanumeric) 353 353 { 354 354 return Err(LuminaError::RegisterUsernameInvalid( 355 - "Invalid characters in username".to_string(), 355 + OnRegisterUsernameInvalid::InvalidCharacters, 356 356 )); 357 357 } 358 358 // Check if the username is too long 359 359 if username.len() > 20 { 360 360 return Err(LuminaError::RegisterUsernameInvalid( 361 - "Username too long".to_string(), 361 + OnRegisterUsernameInvalid::TooLong, 362 362 )); 363 363 } 364 364 // Check if the username is too short 365 365 if username.len() < 4 { 366 366 return Err(LuminaError::RegisterUsernameInvalid( 367 - "Username too short".to_string(), 367 + OnRegisterUsernameInvalid::TooShort, 368 368 )); 369 369 } 370 370 } ··· 376 376 { 377 377 if password.len() < 8 { 378 378 return Err(LuminaError::RegisterPasswordNotValid( 379 - "Password too short".to_string(), 379 + OnRegisterPasswordNotValid::TooShort, 380 380 )); 381 381 } 382 382 if password.len() > 100 { 383 383 return Err(LuminaError::RegisterPasswordNotValid( 384 - "Password too long".to_string(), 384 + OnRegisterPasswordNotValid::TooLong 385 385 )); 386 386 } 387 387 if !password.chars().any(char::is_uppercase) { 388 - return Err(LuminaError::RegisterPasswordNotValid( 389 - "Password must contain at least one uppercase letter".to_string(), 388 + return Err(LuminaError::RegisterPasswordNotValid( 389 + OnRegisterPasswordNotValid::MissingUppercase 390 390 )); 391 391 } 392 392 if !password.chars().any(char::is_lowercase) { 393 393 return Err(LuminaError::RegisterPasswordNotValid( 394 - "Password must contain at least one lowercase letter".to_string(), 394 + OnRegisterPasswordNotValid::MissingLowercase 395 395 )); 396 396 } 397 397 if !password.chars().any(char::is_numeric) { 398 - return Err(LuminaError::RegisterPasswordNotValid( 399 - "Password must contain at least one number".to_string(), 398 + return Err(LuminaError::RegisterPasswordNotValid(OnRegisterPasswordNotValid::MissingNumber 400 399 )); 401 400 } 402 401 } 403 402 Ok(()) 404 403 } 404 + 405 + 406 + #[derive(Debug)] 407 + pub(crate) enum OnRegisterUsernameInvalid { 408 + TooLong, 409 + TooShort, 410 + InvalidCharacters 411 + } 412 + impl std::fmt::Display for OnRegisterUsernameInvalid { 413 + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 414 + write!(f, "{}", match self { 415 + OnRegisterUsernameInvalid::TooLong => "Username too long", 416 + OnRegisterUsernameInvalid::TooShort => "Username too short", 417 + OnRegisterUsernameInvalid::InvalidCharacters => { 418 + "Username contains invalid characters" 419 + } 420 + }) 421 + } 422 + } 423 + #[derive(Debug)] 424 + pub(crate) enum OnRegisterPasswordNotValid { 425 + TooShort, 426 + TooLong, 427 + MissingUppercase, 428 + MissingLowercase, 429 + MissingNumber, 430 + } 431 + impl std::fmt::Display for OnRegisterPasswordNotValid { 432 + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 433 + write!(f, "{}", match self { 434 + OnRegisterPasswordNotValid::TooShort => "Password too short", 435 + OnRegisterPasswordNotValid::TooLong => "Password too long", 436 + OnRegisterPasswordNotValid::MissingUppercase => { 437 + "Password must contain at least one uppercase letter" 438 + } 439 + OnRegisterPasswordNotValid::MissingLowercase => { 440 + "Password must contain at least one lowercase letter" 441 + } 442 + OnRegisterPasswordNotValid::MissingNumber => { 443 + "Password must contain at least one number" 444 + } 445 + }) 446 + } 447 + }