diff options
| author | MatthieuCoder <matthieu@matthieu-dev.xyz> | 2023-01-02 18:59:03 +0400 |
|---|---|---|
| committer | MatthieuCoder <matthieu@matthieu-dev.xyz> | 2023-01-02 18:59:03 +0400 |
| commit | f8c2a144e2f3e47371f5e8352e7a7a0b6707bf88 (patch) | |
| tree | 8c1e6bd157ac599429c806f9aa9bc9dbc28140ed /libs | |
| parent | 46fd26962ef55f8b557f7e36d3aee915a819c88c (diff) | |
restructure project
Diffstat (limited to 'libs')
| -rw-r--r-- | libs/leash/Cargo.toml | 13 | ||||
| -rw-r--r-- | libs/leash/src/lib.rs | 70 | ||||
| -rw-r--r-- | libs/proto/Cargo.toml | 6 | ||||
| -rw-r--r-- | libs/proto/build.rs | 11 | ||||
| -rw-r--r-- | libs/proto/src/lib.rs | 1 | ||||
| -rw-r--r-- | libs/shared/Cargo.toml | 1 | ||||
| -rw-r--r-- | libs/shared/src/config.rs | 37 | ||||
| -rw-r--r-- | libs/shared/src/nats.rs | 15 | ||||
| -rw-r--r-- | libs/shared/src/redis.rs | 19 |
9 files changed, 137 insertions, 36 deletions
diff --git a/libs/leash/Cargo.toml b/libs/leash/Cargo.toml new file mode 100644 index 0000000..5cd54a5 --- /dev/null +++ b/libs/leash/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "leash" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +shared = { path = "../shared" } +anyhow = "1.0.68" +tokio = { version = "1.23.0", features = ["full"] } + +serde = "1.0.152"
\ No newline at end of file diff --git a/libs/leash/src/lib.rs b/libs/leash/src/lib.rs new file mode 100644 index 0000000..360db12 --- /dev/null +++ b/libs/leash/src/lib.rs @@ -0,0 +1,70 @@ +use anyhow::Result; +use serde::de::DeserializeOwned; +use shared::config::Settings; +use std::{future::Future, pin::Pin}; + +pub type AnyhowResultFuture<T> = Pin<Box<dyn Future<Output = Result<T>>>>; +pub trait Component: Send + Sync + 'static + Sized { + type Config: Default + Clone + DeserializeOwned; + + const SERVICE_NAME: &'static str; + fn start(&self, settings: Settings<Self::Config>) -> AnyhowResultFuture<()>; + fn new() -> Self; + + fn _internal_start(self) -> AnyhowResultFuture<()> { + Box::pin(async move { + let settings = Settings::<Self::Config>::new(Self::SERVICE_NAME); + + // Start the grpc healthcheck + tokio::spawn(async move {}); + + // Start the prometheus monitoring job + tokio::spawn(async move {}); + + self.start(settings?).await + }) + } +} + +#[macro_export] +macro_rules! ignite { + ($c:ty) => { + #[allow(dead_code)] + fn main() -> anyhow::Result<()> { + let rt = tokio::runtime::Runtime::new()?; + rt.block_on(Box::new(<$c as Component>::new())._internal_start())?; + Ok(()) + } + }; +} + +#[cfg(test)] +mod test { + use serde::Deserialize; + + use crate::Component; + + #[derive(Clone, Copy)] + struct TestComponent {} + + #[derive(Default, Clone, Deserialize, Copy)] + struct TestComponentConfig {} + + impl Component for TestComponent { + type Config = TestComponentConfig; + const SERVICE_NAME: &'static str = "test_component"; + + fn start( + &self, + _settings: shared::config::Settings<Self::Config>, + ) -> crate::AnyhowResultFuture<()> { + Box::pin(async move { Ok(()) }) + } + + fn new() -> Self { + Self {} + } + } + + ignite!(TestComponent); +} diff --git a/libs/proto/Cargo.toml b/libs/proto/Cargo.toml index c4f2f2a..2556dfe 100644 --- a/libs/proto/Cargo.toml +++ b/libs/proto/Cargo.toml @@ -4,3 +4,9 @@ version = "0.1.0" edition = "2018" [dependencies] +tonic = "0.8.3" +prost = "0.11.5" + +[build-dependencies] +tonic-build = "0.8.4" +glob = "0.3.0"
\ No newline at end of file diff --git a/libs/proto/build.rs b/libs/proto/build.rs new file mode 100644 index 0000000..80c3a55 --- /dev/null +++ b/libs/proto/build.rs @@ -0,0 +1,11 @@ +fn main() -> Result<(), Box<dyn std::error::Error>> { + let paths: Vec<String> = glob::glob("../../proto/nova/**/*.proto")? + .map(|f| f.unwrap().to_str().unwrap().to_string()) + .collect(); + + tonic_build::configure() + .include_file("genproto.rs") + .compile(&paths, &["../../proto"])?; + + Ok(()) +} diff --git a/libs/proto/src/lib.rs b/libs/proto/src/lib.rs index e69de29..01dc7bc 100644 --- a/libs/proto/src/lib.rs +++ b/libs/proto/src/lib.rs @@ -0,0 +1 @@ +include!(concat!(env!("OUT_DIR"), concat!("/", "genproto.rs"))); diff --git a/libs/shared/Cargo.toml b/libs/shared/Cargo.toml index 6d6b6f6..ab19ce8 100644 --- a/libs/shared/Cargo.toml +++ b/libs/shared/Cargo.toml @@ -19,6 +19,7 @@ twilight-model = "0.14" serde_json = { version = "1.0" } thiserror = "1.0.38" inner = "0.1.1" +anyhow = "1.0.68" [dependencies.redis] version = "*" diff --git a/libs/shared/src/config.rs b/libs/shared/src/config.rs index 52137a3..4387dfb 100644 --- a/libs/shared/src/config.rs +++ b/libs/shared/src/config.rs @@ -1,17 +1,11 @@ -use std::env; +use std::{env, ops::Deref}; use config::{Config, Environment, File}; use log::info; -use serde::Deserialize; +use serde::{Deserialize, de::DeserializeOwned}; use crate::error::GenericError; - -/// Settings<T> is the base structure for all the nova's component config -/// you can specify a type T and the name of the component. the "config" -/// field will be equals to the key named after the given component name -/// and will be of type T #[derive(Debug, Deserialize, Clone)] -#[serde(bound(deserialize = "T: Deserialize<'de> + std::default::Default + Clone"))] -pub struct Settings<T> { +pub struct Settings<T: Clone + DeserializeOwned + Default> { #[serde(skip_deserializing)] pub config: T, pub monitoring: crate::monitoring::MonitoringConfiguration, @@ -19,20 +13,11 @@ pub struct Settings<T> { pub redis: crate::redis::RedisConfiguration, } -/// -impl<T> Settings<T> -where - T: Deserialize<'static> + std::default::Default + Clone, +impl<'de, T: Clone + DeserializeOwned + Default> Settings<T> { - - /// Initializes a new configuration like the other components of nova - /// And starts the prometheus metrics server if needed. pub fn new(service_name: &str) -> Result<Settings<T>, GenericError> { - pretty_env_logger::init(); - let mut builder = Config::builder(); - // this file my be shared with all the components builder = builder.add_source(File::with_name("config/default")); let mode = env::var("ENV").unwrap_or_else(|_| "development".into()); info!("Configuration Environment: {}", mode); @@ -49,13 +34,15 @@ where // try to load the config settings.config = config.get::<T>(service_name)?; - - // start the monitoring system if needed - crate::monitoring::start_monitoring(&settings.monitoring); + Ok(settings) } } -pub fn test_init() { - pretty_env_logger::init(); -} +impl<T: Clone + DeserializeOwned + Default> Deref for Settings<T> { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.config + } +}
\ No newline at end of file diff --git a/libs/shared/src/nats.rs b/libs/shared/src/nats.rs index 05953cc..dc922d5 100644 --- a/libs/shared/src/nats.rs +++ b/libs/shared/src/nats.rs @@ -1,8 +1,7 @@ +use std::{future::Future, pin::Pin}; + use async_nats::Client; use serde::Deserialize; -use std::future::Future; - -use crate::error::GenericError; #[derive(Clone, Debug, Deserialize)] pub struct NatsConfigurationClientCert { @@ -20,10 +19,8 @@ pub struct NatsConfiguration { pub host: String, } -// todo: Prefer From since it automatically gives a free Into implementation -// Allows the configuration to directly create a nats connection -impl NatsConfiguration { - pub async fn to_client(self) -> Result<Client, GenericError> { - Ok(async_nats::connect(self.host).await?) +impl From<NatsConfiguration> for Pin<Box<dyn Future<Output = anyhow::Result<Client>>>> { + fn from(value: NatsConfiguration) -> Self { + Box::pin(async move { Ok(async_nats::connect(value.host).await?) }) } -}
\ No newline at end of file +} diff --git a/libs/shared/src/redis.rs b/libs/shared/src/redis.rs index a196f8d..5753fb6 100644 --- a/libs/shared/src/redis.rs +++ b/libs/shared/src/redis.rs @@ -1,6 +1,6 @@ -use redis::Client; +use redis::{aio::MultiplexedConnection, Client}; use serde::Deserialize; - +use std::{future::Future, pin::Pin}; #[derive(Clone, Debug, Deserialize)] pub struct RedisConfiguration { @@ -13,3 +13,18 @@ impl Into<Client> for RedisConfiguration { redis::Client::open(self.url).unwrap() } } + +impl From<RedisConfiguration> + for Pin<Box<dyn Future<Output = anyhow::Result<MultiplexedConnection>>>> +{ + fn from(value: RedisConfiguration) -> Self { + Box::pin(async move { + let con = Client::open(value.url)?; + let (multiplex, ready) = con.create_multiplexed_tokio_connection().await?; + + tokio::spawn(ready); + + Ok(multiplex) + }) + } +} |
