diff options
| author | MatthieuCoder <matthieu@matthieu-dev.xyz> | 2023-01-16 15:43:10 +0400 |
|---|---|---|
| committer | MatthieuCoder <matthieu@matthieu-dev.xyz> | 2023-01-16 15:43:10 +0400 |
| commit | 0f90d0f3d30a728457e6bc5c4d1d933a8014e099 (patch) | |
| tree | b1468081a32546e8d01fba622f978cdd326cf6fd /exes/all-in-one/src | |
| parent | 277f38bbe89e4db57b73a4e28bf1be2f5c50ce27 (diff) | |
new build system
Diffstat (limited to 'exes/all-in-one/src')
| -rw-r--r-- | exes/all-in-one/src/errors.rs | 53 | ||||
| -rw-r--r-- | exes/all-in-one/src/ffi.rs | 143 | ||||
| -rw-r--r-- | exes/all-in-one/src/lib.rs | 14 | ||||
| -rw-r--r-- | exes/all-in-one/src/main.rs | 19 | ||||
| -rw-r--r-- | exes/all-in-one/src/utils.rs | 82 |
5 files changed, 0 insertions, 311 deletions
diff --git a/exes/all-in-one/src/errors.rs b/exes/all-in-one/src/errors.rs deleted file mode 100644 index d2c7444..0000000 --- a/exes/all-in-one/src/errors.rs +++ /dev/null @@ -1,53 +0,0 @@ -use std::cell::RefCell; - -use anyhow::Result; -use tracing::error; - -thread_local! { - pub static ERROR_HANDLER: std::cell::RefCell<Option<unsafe extern "C" fn(libc::c_int, *mut libc::c_char)>> = RefCell::new(None); -} - -/// Update the most recent error, clearing whatever may have been there before. -#[must_use] pub fn stacktrace(err: &anyhow::Error) -> String { - format!("{err}") -} - -pub fn wrap_result<T, F>(func: F) -> Option<T> -where - F: Fn() -> Result<T>, -{ - let result = func(); - - match result { - Ok(ok) => Some(ok), - Err(error) => { - // Call the handler - handle_error(&error); - None - } - } -} - -/// # Panics -/// Panics if the stacktrace size is > than an i32 -pub fn handle_error(error: &anyhow::Error) { - ERROR_HANDLER.with(|val| { - let mut stacktrace = stacktrace(error); - - error!("Error emitted: {}", stacktrace); - if let Some(func) = *val.borrow() { - // Call the error handler - unsafe { - func( - (stacktrace.len() + 1).try_into().unwrap(), - stacktrace.as_mut_ptr().cast::<libc::c_char>(), - ); - } - } - }); -} - -#[cfg(test)] -mod tests { - // todo -} diff --git a/exes/all-in-one/src/ffi.rs b/exes/all-in-one/src/ffi.rs deleted file mode 100644 index b4c853d..0000000 --- a/exes/all-in-one/src/ffi.rs +++ /dev/null @@ -1,143 +0,0 @@ -#![allow(clippy::missing_safety_doc)] -use std::{ - ffi::{c_char, c_int, CString}, - mem::take, - ptr, - str::FromStr, - time::Duration, -}; - -use gateway::GatewayServer; -use opentelemetry::{global::set_text_map_propagator, sdk::propagation::TraceContextPropagator}; -use ratelimit::RatelimiterServerComponent; -use rest::ReverseProxyServer; -use tokio::{runtime::Runtime, sync::mpsc}; -use tracing::{debug, error}; -use tracing_subscriber::{ - filter::Directive, fmt, prelude::__tracing_subscriber_SubscriberExt, util::SubscriberInitExt, - EnvFilter, -}; -use webhook::WebhookServer; - -use crate::{ - errors::{handle_error, wrap_result, ERROR_HANDLER}, - utils::{load_config_file, start_component, AllInOneInstance}, -}; - -#[no_mangle] -pub unsafe extern "C" fn set_error_handler(func: unsafe extern "C" fn(c_int, *mut c_char)) { - debug!("Setting error handler"); - ERROR_HANDLER.with(|prev| { - *prev.borrow_mut() = Some(func); - }); -} - -#[no_mangle] -/// Loads the config json using the nova shared config loader -pub extern "C" fn load_config() -> *mut c_char { - wrap_result(move || { - let config = serde_json::to_string(&load_config_file()?)?; - let c_str_song = CString::new(config)?; - Ok(c_str_song.into_raw()) - }) - .or(Some(ptr::null::<c_char>() as *mut c_char)) - .expect("something has gone terribly wrong") -} - -#[no_mangle] -pub unsafe extern "C" fn stop_instance(instance: *mut AllInOneInstance) { - wrap_result(move || { - let mut instance = Box::from_raw(instance); - let handles = take(&mut instance.handles); - instance.runtime.block_on(async move { - for (name, sender, join) in handles { - debug!("Halting component {}", name); - let _ = sender - .send(()) - .map_err(|_| error!("Component {} is not online", name)); - match join.await { - Ok(_) => {} - Err(error) => error!("Task for component {} panic'ed {}", name, error), - }; - debug!("Component {} halted", name); - } - }); - - instance.runtime.shutdown_timeout(Duration::from_secs(5)); - - Ok(()) - }); -} - -/// # Panics -/// Panics if an incorrect `RUST_LOG` variables is specified. -#[no_mangle] -pub unsafe extern "C" fn create_instance(config: *mut c_char) -> *mut AllInOneInstance { - // Returning a null pointer (unaligned) is expected. - #[allow(clippy::cast_ptr_alignment)] - wrap_result(move || { - let value = CString::from_raw(config); - let json = value.to_str()?; - - // Main stop signal for this instance - let (error_sender, mut errors) = mpsc::channel(50); - let mut handles = vec![]; - - let runtime = Runtime::new()?; - - // Setup the tracing system - set_text_map_propagator(TraceContextPropagator::new()); - tracing_subscriber::registry() - .with(fmt::layer()) - .with( - EnvFilter::builder() - .with_default_directive(Directive::from_str("info").expect("")) - .from_env() - .unwrap(), - ) - .init(); - - // Error handling task - runtime.spawn(async move { - while let Some(error) = errors.recv().await { - handle_error(&error); - } - }); - - handles.push(start_component::<GatewayServer>( - json, - error_sender.clone(), - &runtime, - )?); - - std::thread::sleep(Duration::from_secs(1)); - - handles.push(start_component::<RatelimiterServerComponent>( - json, - error_sender.clone(), - &runtime, - )?); - - std::thread::sleep(Duration::from_secs(1)); - - handles.push(start_component::<ReverseProxyServer>( - json, - error_sender.clone(), - &runtime, - )?); - - std::thread::sleep(Duration::from_secs(1)); - - handles.push(start_component::<WebhookServer>( - json, - error_sender, - &runtime, - )?); - - let all_in_one = Box::into_raw(Box::new(AllInOneInstance { runtime, handles })); - - Ok(all_in_one) - }) - .or(Some(ptr::null::<AllInOneInstance>() as *mut AllInOneInstance)) - .expect("something has gone terribly wrong") -} diff --git a/exes/all-in-one/src/lib.rs b/exes/all-in-one/src/lib.rs deleted file mode 100644 index 493bf46..0000000 --- a/exes/all-in-one/src/lib.rs +++ /dev/null @@ -1,14 +0,0 @@ -#![deny( - clippy::all, - clippy::correctness, - clippy::suspicious, - clippy::style, - clippy::complexity, - clippy::perf, - clippy::pedantic, - clippy::nursery, -)] - -pub mod errors; -pub mod ffi; -pub mod utils; diff --git a/exes/all-in-one/src/main.rs b/exes/all-in-one/src/main.rs deleted file mode 100644 index 1e65883..0000000 --- a/exes/all-in-one/src/main.rs +++ /dev/null @@ -1,19 +0,0 @@ -use all_in_one::ffi::{create_instance, load_config, stop_instance}; -use std::sync::mpsc::channel; - -fn main() { - let c = load_config(); - let comp = unsafe { create_instance(c) }; - - // wait for signal - let (tx, rx) = channel(); - - ctrlc::set_handler(move || tx.send(()).expect("Could not send signal on channel.")) - .expect("Error setting Ctrl-C handler"); - - rx.recv().unwrap(); - - println!("Exiting."); - - unsafe { stop_instance(comp) }; -} diff --git a/exes/all-in-one/src/utils.rs b/exes/all-in-one/src/utils.rs deleted file mode 100644 index 159d98d..0000000 --- a/exes/all-in-one/src/utils.rs +++ /dev/null @@ -1,82 +0,0 @@ -use anyhow::Result; -use config::{Config, Environment, File}; -use leash::Component; -use serde::de::DeserializeOwned; -use serde_json::Value; -use shared::config::Settings; -use tokio::{ - runtime::Runtime, - sync::{mpsc, oneshot::Sender}, - task::JoinHandle, -}; -use tracing::{ - debug, - log::{error, info}, -}; - -/// Represents a all in one instance -pub struct AllInOneInstance { - pub runtime: Runtime, - pub(crate) handles: Vec<(&'static str, Sender<()>, JoinHandle<()>)>, -} - -/// Loads the settings from a component using a string -fn load_settings_for<T: Default + DeserializeOwned + Clone>( - settings: &str, - name: &str, -) -> Result<Settings<T>> { - let value: Value = serde_json::from_str(settings)?; - let section: T = serde_json::from_value(value.get(name).unwrap().clone())?; - let mut settings: Settings<T> = serde_json::from_value(value)?; - settings.config = section; - - Ok(settings) -} - -pub(crate) fn start_component<T: Component>( - json: &str, - error_sender: mpsc::Sender<anyhow::Error>, - runtime: &Runtime, -) -> Result<(&'static str, Sender<()>, JoinHandle<()>)> { - let name = T::SERVICE_NAME; - let instance = T::new(); - - // We setup stop signals - let (stop, signal) = tokio::sync::oneshot::channel(); - let settings = load_settings_for(json, name)?; - - let handle = runtime.spawn(async move { - debug!("starting component {}", name); - match instance.start(settings, signal).await { - Ok(_) => info!("Component {} gracefully exited", name), - Err(error) => { - error!("Component {} exited with error {}", name, error); - error_sender - .send(error) - .await - .expect("Couldn't send the error notification to the error mpsc"); - } - } - }); - - Ok((name, stop, handle)) -} - -pub(crate) fn load_config_file() -> Result<Value> { - let mut builder = Config::builder(); - - builder = builder.add_source(File::with_name("config/default")); - let mode = std::env::var("ENV").unwrap_or_else(|_| "development".into()); - info!("Configuration Environment: {}", mode); - - builder = builder.add_source(File::with_name(&format!("config/{mode}")).required(false)); - builder = builder.add_source(File::with_name("config/local").required(false)); - - let env = Environment::with_prefix("NOVA").separator("__"); - // we can configure each component using environment variables - builder = builder.add_source(env); - - let config: Value = builder.build()?.try_deserialize()?; - - Ok(config) -} |
