summaryrefslogtreecommitdiff
path: root/exes/all-in-one/src
diff options
context:
space:
mode:
authorMatthieuCoder <matthieu@matthieu-dev.xyz>2023-01-16 15:43:10 +0400
committerMatthieuCoder <matthieu@matthieu-dev.xyz>2023-01-16 15:43:10 +0400
commit0f90d0f3d30a728457e6bc5c4d1d933a8014e099 (patch)
treeb1468081a32546e8d01fba622f978cdd326cf6fd /exes/all-in-one/src
parent277f38bbe89e4db57b73a4e28bf1be2f5c50ce27 (diff)
new build system
Diffstat (limited to 'exes/all-in-one/src')
-rw-r--r--exes/all-in-one/src/errors.rs53
-rw-r--r--exes/all-in-one/src/ffi.rs143
-rw-r--r--exes/all-in-one/src/lib.rs14
-rw-r--r--exes/all-in-one/src/main.rs19
-rw-r--r--exes/all-in-one/src/utils.rs82
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)
-}