diff --git a/Cargo.lock b/Cargo.lock index 5f63adb7..e76c7cf1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2100,6 +2100,17 @@ dependencies = [ "rand_core 0.3.1", ] +[[package]] +name = "realis-macros" +version = "0.1.0" +dependencies = [ + "convert_case", + "proc-macro2 1.0.40", + "quote 1.0.20", + "schemas", + "syn 1.0.98", +] + [[package]] name = "redox_syscall" version = "0.1.57" diff --git a/Cargo.toml b/Cargo.toml index 4b05b701..ad89f160 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,4 +4,5 @@ members = [ "error_registry", "schemas", "transport", + "macros" ] diff --git a/app/src/app.rs b/app/src/app.rs index af74cebe..34f34568 100644 --- a/app/src/app.rs +++ b/app/src/app.rs @@ -7,7 +7,6 @@ pub trait Runnable: Send + Sync { async fn run(&mut self); } - pub struct App { services: Vec>>, } @@ -31,8 +30,7 @@ impl App { } pub fn init_logger(self) -> Self { - env_logger::Builder::from_env(env_logger::Env::new() - .filter_or("LOGGER_LEVEL", "debug")) + env_logger::Builder::from_env(env_logger::Env::new().filter_or("LOGGER_LEVEL", "debug")) .init(); self } diff --git a/app/src/service_app.rs b/app/src/service_app.rs index dba309a0..270f1b5e 100644 --- a/app/src/service_app.rs +++ b/app/src/service_app.rs @@ -152,11 +152,13 @@ impl, N: Transport + Sync + Send> ServiceA Some(topic) => Ok(topic .as_str() - .ok_or_else(||BaseError::::new( - "Unexpected type".to_string(), - GeneratedError::Common(Common::Unknown).into(), - None, - ))? + .ok_or_else(|| { + BaseError::::new( + "Unexpected type".to_string(), + GeneratedError::Common(Common::Unknown).into(), + None, + ) + })? .to_string()), }; log::debug!("request {:#?} : ", request); diff --git a/error_registry/src/lib.rs b/error_registry/src/lib.rs index ce1457d9..917aa66d 100644 --- a/error_registry/src/lib.rs +++ b/error_registry/src/lib.rs @@ -2,19 +2,19 @@ //! `BaseError` its custom error data structure. //! `ErrorType` its enum of possible errors //! what need to be traced for Realis microservices. -use serde::{Deserialize, Serialize}; -use std::{ - fmt, - fmt::{Debug, Display, Formatter}, -}; -use backtrace::Backtrace; -use serde_json::Value; +use crate::generated_errors::{Critical, Db}; use crate::{ custom_errors::{CustomErrorType, EnvLoadedError, Nats as CustomNats}, generated_errors::Common, }; +use backtrace::Backtrace; use generated_errors::GeneratedError; -use crate::generated_errors::{Critical, Db}; +use serde::{Deserialize, Serialize}; +use serde_json::Value; +use std::{ + fmt, + fmt::{Debug, Display, Formatter}, +}; pub mod custom_errors; pub mod generated_errors; @@ -33,7 +33,10 @@ pub struct BaseError { impl BaseError { pub fn is_critical(&self) -> bool { - matches!(self.error_type, ErrorType::Generated(GeneratedError::Critical(_))) + matches!( + self.error_type, + ErrorType::Generated(GeneratedError::Critical(_)) + ) } } @@ -93,7 +96,7 @@ impl Display for BaseError { } } -impl From for BaseError { +impl From for BaseError { fn from(error: tokio::sync::oneshot::error::RecvError) -> Self { let trace = Backtrace::new(); let msg = error.to_string(); @@ -108,7 +111,7 @@ impl From for BaseError { } } -impl From for BaseError { +impl From for BaseError { fn from(error: tokio::time::error::Elapsed) -> Self { let trace = Backtrace::new(); let msg = error.to_string(); @@ -123,7 +126,7 @@ impl From for BaseError { } } -impl From for BaseError { +impl From for BaseError { fn from(error: ratsio::RatsioError) -> Self { let trace = Backtrace::new(); let msg = error.to_string(); @@ -138,7 +141,7 @@ impl From for BaseError { } } -impl From for BaseError { +impl From for BaseError { fn from(error: tokio::task::JoinError) -> Self { let trace = Backtrace::new(); let msg = error.to_string(); @@ -153,7 +156,7 @@ impl From for BaseError { } } -impl From for BaseError { +impl From for BaseError { fn from(error: tokio_postgres::Error) -> Self { let trace = Backtrace::new(); let msg = error.to_string(); @@ -168,7 +171,7 @@ impl From for BaseError { } } -impl From> for BaseError { +impl From> for BaseError { fn from(error: deadpool::managed::PoolError) -> Self { let trace = Backtrace::new(); let msg = error.to_string(); @@ -183,7 +186,7 @@ impl From> for Base } } -impl From for BaseError { +impl From for BaseError { fn from(error: std::net::AddrParseError) -> Self { let trace = Backtrace::new(); let msg = error.to_string(); @@ -198,7 +201,7 @@ impl From for BaseError { } } -impl From for BaseError { +impl From for BaseError { fn from(error: std::num::ParseIntError) -> Self { let trace = Backtrace::new(); let msg = error.to_string(); @@ -213,7 +216,7 @@ impl From for BaseError { } } -impl From for BaseError { +impl From for BaseError { fn from(error: hex::FromHexError) -> Self { let trace = Backtrace::new(); let msg = error.to_string(); @@ -228,7 +231,7 @@ impl From for BaseError { } } -impl From for BaseError { +impl From for BaseError { fn from(error: openssl::error::ErrorStack) -> Self { let trace = Backtrace::new(); let msg = error.to_string(); @@ -243,7 +246,7 @@ impl From for BaseError { } } -impl From for BaseError { +impl From for BaseError { fn from(error: dotenv::Error) -> Self { let trace = Backtrace::new(); let msg = error.to_string(); @@ -258,7 +261,7 @@ impl From for BaseError { } } -impl From for BaseError { +impl From for BaseError { fn from(error: sqlx::error::Error) -> Self { let trace = Backtrace::new(); let msg = error.to_string(); @@ -273,7 +276,7 @@ impl From for BaseError { } } -impl From for BaseError { +impl From for BaseError { fn from(error: deadpool_postgres::CreatePoolError) -> Self { let trace = Backtrace::new(); let msg = error.to_string(); @@ -288,6 +291,21 @@ impl From for BaseError { } } +impl From for BaseError { + fn from(error: std::str::ParseBoolError) -> Self { + let trace = Backtrace::new(); + let msg = error.to_string(); + let error_type = ErrorType::from(error); + BaseError { + msg, + trace: format!("{:?}", trace), + status: error_type.clone().into(), + error_type, + data: None, + } + } +} + impl Default for BaseError { /// Default BaseError. /// @@ -418,7 +436,8 @@ impl From> for ErrorType { // Custom DB: ConnectionError ErrorType::Generated(GeneratedError::Critical(Critical::Db)) } -}impl From for ErrorType { +} +impl From for ErrorType { fn from(_: tokio_postgres::Error) -> Self { // Custom DB: ConnectionError ErrorType::Generated(GeneratedError::Critical(Critical::Db)) @@ -448,7 +467,9 @@ impl From for ErrorType { | sqlx::error::Error::PoolTimedOut | sqlx::error::Error::Configuration(_) | sqlx::error::Error::Tls(_) - | sqlx::error::Error::WorkerCrashed => ErrorType::Generated(GeneratedError::Critical(Critical::Db)), + | sqlx::error::Error::WorkerCrashed => { + ErrorType::Generated(GeneratedError::Critical(Critical::Db)) + } // Generated DB: Invalid Transaction sqlx::error::Error::Database(_) | sqlx::error::Error::ColumnDecode { .. } @@ -457,11 +478,15 @@ impl From for ErrorType { | sqlx::error::Error::ColumnNotFound(_) | sqlx::error::Error::ColumnIndexOutOfBounds { .. } | sqlx::error::Error::Decode(_) - | sqlx::error::Error::Migrate(_) => ErrorType::Generated(GeneratedError::Db(Db::InvalidTransaction)), + | sqlx::error::Error::Migrate(_) => { + ErrorType::Generated(GeneratedError::Db(Db::InvalidTransaction)) + } // Generated DB: Not Found - sqlx::error::Error::RowNotFound => ErrorType::Generated(GeneratedError::Db(Db::NotFound)), + sqlx::error::Error::RowNotFound => { + ErrorType::Generated(GeneratedError::Db(Db::NotFound)) + } // Custom: Default - _ => ErrorType::Custom(CustomErrorType::Default) + _ => ErrorType::Custom(CustomErrorType::Default), } } } @@ -487,15 +512,15 @@ impl From for ErrorType { } } -impl From for ErrorType { - fn from(_: std::net::AddrParseError) -> Self { +impl From for ErrorType { + fn from(_: std::str::ParseBoolError) -> Self { // Custom EnvLoadedError: Convert ErrorType::Custom(CustomErrorType::EnvLoadedError(EnvLoadedError::Convert)) } } -impl From for ErrorType { - fn from(_: std::str::ParseBoolError) -> Self { +impl From for ErrorType { + fn from(_: std::net::AddrParseError) -> Self { // Custom EnvLoadedError: Convert ErrorType::Custom(CustomErrorType::EnvLoadedError(EnvLoadedError::Convert)) } diff --git a/macros/Cargo.toml b/macros/Cargo.toml index 2c34a778..e833a3fa 100644 --- a/macros/Cargo.toml +++ b/macros/Cargo.toml @@ -9,5 +9,6 @@ proc-macro = true [dependencies] proc-macro2 = "1.0.36" quote = "1.0" +schemas = { path = "../schemas" } syn = { version = "1.0", features = ["full", "extra-traits"] } convert_case = "0.5.0" diff --git a/macros/src/env/env.rs b/macros/src/env/env.rs index 1dc67ab1..2165dbbb 100644 --- a/macros/src/env/env.rs +++ b/macros/src/env/env.rs @@ -28,15 +28,27 @@ pub fn impl_env_macros(item: TokenStream) -> TokenStream { // .map(|attr| symbol::get_env_meta_items(&attr)) // .flatten() .for_each(|meta| match meta { - Meta(NameValue(m)) if m.path == symbol::RENAME => field_attributes.field_name = EnvNameAttrs::Rename(m.lit), - Meta(Path(path)) if path == symbol::FLATTEN => field_attributes.field_name = EnvNameAttrs::Flatten, - Meta(NameValue(m)) if m.path == symbol::RENAME_ABS => field_attributes.field_name = EnvNameAttrs::RenameAbs(m.lit), - Meta(Path(path)) if path == symbol::DEFAULT => field_attributes.default_type = EnvDefaultAttrs::Default, - Meta(NameValue(m)) if m.path == symbol::DEFAULT_PATH => field_attributes.default_type = EnvDefaultAttrs::DefaultPath(m.lit), + Meta(NameValue(m)) if m.path == symbol::RENAME => { + field_attributes.field_name = EnvNameAttrs::Rename(m.lit) + } + Meta(Path(path)) if path == symbol::FLATTEN => { + field_attributes.field_name = EnvNameAttrs::Flatten + } + Meta(NameValue(m)) if m.path == symbol::RENAME_ABS => { + field_attributes.field_name = EnvNameAttrs::RenameAbs(m.lit) + } + Meta(Path(path)) if path == symbol::DEFAULT => { + field_attributes.default_type = EnvDefaultAttrs::Default + } + Meta(NameValue(m)) if m.path == symbol::DEFAULT_PATH => { + field_attributes.default_type = EnvDefaultAttrs::DefaultPath(m.lit) + } _ => {} }); - let env_name = field_attributes.field_name.name(&struct_name.to_string(), &field_name.to_string()); + let env_name = field_attributes + .field_name + .name(&struct_name.to_string(), &field_name.to_string()); let postfix = field_attributes.default_type.postfix(); match field.ty { diff --git a/macros/src/env/field_attributes/name.rs b/macros/src/env/field_attributes/name.rs index 224bf121..e71048fc 100644 --- a/macros/src/env/field_attributes/name.rs +++ b/macros/src/env/field_attributes/name.rs @@ -13,7 +13,9 @@ impl EnvNameAttrs { match self { EnvNameAttrs::Flatten => field_name.to_string(), EnvNameAttrs::RenameAbs(Str(str)) => str.value().to_string(), - EnvNameAttrs::Rename(Str(str)) => format!("{}_{}", struct_name.to_string(), str.value()), + EnvNameAttrs::Rename(Str(str)) => { + format!("{}_{}", struct_name.to_string(), str.value()) + } _ => format!("{}_{}", struct_name.to_string(), field_name.to_string()), } .to_case(Case::UpperSnake) diff --git a/macros/src/env/symbol.rs b/macros/src/env/symbol.rs index 76106965..c7f91cc2 100644 --- a/macros/src/env/symbol.rs +++ b/macros/src/env/symbol.rs @@ -57,7 +57,10 @@ fn spanned_tokens(s: &syn::LitStr) -> parse::Result { } fn respan(stream: TokenStream, span: Span) -> TokenStream { - stream.into_iter().map(|token| respan_token(token, span)).collect() + stream + .into_iter() + .map(|token| respan_token(token, span)) + .collect() } fn respan_token(mut token: TokenTree, span: Span) -> TokenTree { diff --git a/macros/src/lib.rs b/macros/src/lib.rs index ba2f5811..3a0953f0 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -5,14 +5,17 @@ mod env; mod gettable; mod gettable_errors; mod retry; +mod schema; mod to_json; use proc_macro::TokenStream; +use crate::schema::schema_macros; use crate::{ - byte_decode::impl_byte_decode_macros, byte_encode::impl_byte_encode_macros, deserialize_errors::impl_deserialize_errors_macros, - env::env::impl_env_macros, gettable::impl_gettable_macros, gettable_errors::impl_gettable_errors_macros, retry::impl_retry_macros, - to_json::impl_to_json_macros, + byte_decode::impl_byte_decode_macros, byte_encode::impl_byte_encode_macros, + deserialize_errors::impl_deserialize_errors_macros, env::env::impl_env_macros, + gettable::impl_gettable_macros, gettable_errors::impl_gettable_errors_macros, + retry::impl_retry_macros, to_json::impl_to_json_macros, }; /// # Panics @@ -136,3 +139,8 @@ pub fn byte_decode_macro_derive(item: TokenStream) -> TokenStream { pub fn config_macro_derive(item: TokenStream) -> TokenStream { impl_env_macros(item) } + +#[proc_macro_derive(Schema)] +pub fn impl_schema_macro(item: TokenStream) -> TokenStream { + schema_macros(item) +} diff --git a/macros/src/retry.rs b/macros/src/retry.rs index 4a2eea55..a443d699 100644 --- a/macros/src/retry.rs +++ b/macros/src/retry.rs @@ -5,7 +5,10 @@ use syn::{self, FnArg, Ident, ItemFn, __private::Span}; pub fn impl_retry_macros(item: TokenStream) -> TokenStream { let item_fn = syn::parse::(item).unwrap(); let original_fn_ident = item_fn.sig.ident.clone(); - let helper_fn_ident = Ident::new(&format!("{}_helper", item_fn.sig.ident.to_string()), Span::call_site()); + let helper_fn_ident = Ident::new( + &format!("{}_helper", item_fn.sig.ident.to_string()), + Span::call_site(), + ); let params = item_fn.sig.inputs; let pats = params .clone() diff --git a/macros/src/schema.rs b/macros/src/schema.rs new file mode 100644 index 00000000..baa02486 --- /dev/null +++ b/macros/src/schema.rs @@ -0,0 +1,12 @@ +use proc_macro::TokenStream; +use quote::quote; +use syn::{ItemFn, ItemStruct}; + +pub fn schema_macros(item: TokenStream) -> TokenStream { + let item_fn = syn::parse::(item).unwrap(); + let ident = item_fn.ident; + let result = quote! { + impl schemas::Schema for #ident {} + }; + result.into() +} diff --git a/schemas/Cargo.toml b/schemas/Cargo.toml index f5809e32..88b8150d 100644 --- a/schemas/Cargo.toml +++ b/schemas/Cargo.toml @@ -7,6 +7,5 @@ edition = "2021" [dependencies] error_registry = { path = "../error_registry" } - serde_json = "1.0.82" serde = "1.0.138" diff --git a/transport/src/subscription/stan.rs b/transport/src/subscription/stan.rs index fecc4702..2d7f6a3d 100644 --- a/transport/src/subscription/stan.rs +++ b/transport/src/subscription/stan.rs @@ -18,9 +18,7 @@ impl Subscription for StanSubscription { self.subscription .next() .map(|message| message.into()) - .ok_or_else(|| BaseError::::from(GeneratedError::Nats( - Nats::Receive, - ))) + .ok_or_else(|| BaseError::::from(GeneratedError::Nats(Nats::Receive))) }) }