aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrtkay123 <dev@kanjala.com>2025-08-08 08:58:03 +0200
committerrtkay123 <dev@kanjala.com>2025-08-08 08:58:03 +0200
commit92d853e8c535d21c7e51200ba5ca2b8393fb0656 (patch)
tree0097009ddd837ec84550808a55fa46fbb73a5b4f
parentb9df4e581cf747c4ccffa3ded49c153e7cbf4cc1 (diff)
downloadwarden-92d853e8c535d21c7e51200ba5ca2b8393fb0656.tar.bz2
warden-92d853e8c535d21c7e51200ba5ca2b8393fb0656.zip
feat(warden): health route
-rw-r--r--Cargo.lock2
-rw-r--r--Cargo.toml2
-rw-r--r--crates/warden/Cargo.toml4
-rw-r--r--crates/warden/src/cnfg.rs7
-rw-r--r--crates/warden/src/error.rs26
-rw-r--r--crates/warden/src/main.rs23
-rw-r--r--crates/warden/src/server.rs25
-rw-r--r--crates/warden/src/server/routes.rs36
-rw-r--r--crates/warden/src/state.rs40
-rw-r--r--crates/warden/src/version.rs30
-rw-r--r--crates/warden/warden.toml3
11 files changed, 195 insertions, 3 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 4b98786..2efb04a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1450,8 +1450,10 @@ dependencies = [
"clap",
"config",
"serde",
+ "serde_json",
"stack-up",
"tokio",
+ "tower",
"tracing",
"warden-core",
]
diff --git a/Cargo.toml b/Cargo.toml
index 711db8a..cd839b1 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -15,8 +15,10 @@ clap = "4.5.43"
config = { version = "0.15.13", default-features = false }
prost = "0.14.1"
serde = "1.0.219"
+serde_json = "1.0.142"
stack-up = { git = "https://github.com/rtkay123/stack-up" }
tokio = "1.47.1"
tonic = "0.14.0"
+tower = "0.5.2"
tracing = "0.1.41"
warden-core = { path = "lib/warden-core" }
diff --git a/crates/warden/Cargo.toml b/crates/warden/Cargo.toml
index 7b9ae9e..c50271e 100644
--- a/crates/warden/Cargo.toml
+++ b/crates/warden/Cargo.toml
@@ -13,10 +13,14 @@ axum = { workspace = true, features = ["macros"] }
clap = { workspace = true, features = ["derive"] }
config = { workspace = true, features = ["convert-case", "toml"] }
serde = { workspace = true, features = ["derive"] }
+serde_json.workspace = true
tokio = { workspace = true, features = ["macros", "rt-multi-thread", "signal"] }
tracing.workspace = true
warden-core = { workspace = true, features = ["iso20022"] }
+[dev-dependencies]
+tower = { workspace = true, features = ["util"] }
+
[dependencies.stack-up]
workspace = true
features = ["api", "tracing"]
diff --git a/crates/warden/src/cnfg.rs b/crates/warden/src/cnfg.rs
new file mode 100644
index 0000000..f3fa016
--- /dev/null
+++ b/crates/warden/src/cnfg.rs
@@ -0,0 +1,7 @@
+use serde::Deserialize;
+
+#[derive(Deserialize, Clone)]
+#[serde(rename_all = "kebab-case")]
+pub struct LocalConfig {
+ pub cache_ttl: u64,
+}
diff --git a/crates/warden/src/error.rs b/crates/warden/src/error.rs
new file mode 100644
index 0000000..730f99a
--- /dev/null
+++ b/crates/warden/src/error.rs
@@ -0,0 +1,26 @@
+use axum::{
+ http::StatusCode,
+ response::{IntoResponse, Response},
+};
+
+#[derive(Debug)]
+pub struct AppError(anyhow::Error);
+
+impl IntoResponse for AppError {
+ fn into_response(self) -> Response {
+ (
+ StatusCode::INTERNAL_SERVER_ERROR,
+ format!("Something went wrong: {}", self.0),
+ )
+ .into_response()
+ }
+}
+
+impl<E> From<E> for AppError
+where
+ E: Into<anyhow::Error>,
+{
+ fn from(err: E) -> Self {
+ Self(err.into())
+ }
+}
diff --git a/crates/warden/src/main.rs b/crates/warden/src/main.rs
index 884d2a8..8ebbdf8 100644
--- a/crates/warden/src/main.rs
+++ b/crates/warden/src/main.rs
@@ -1,8 +1,17 @@
-use anyhow::Result;
+mod cnfg;
+mod error;
+mod server;
+mod state;
+mod version;
+
+use std::net::{Ipv6Addr, SocketAddr};
+
use clap::{Parser, command};
use stack_up::{Configuration, tracing::Tracing};
use tracing::info;
+use crate::state::AppState;
+
/// warden
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
@@ -13,7 +22,7 @@ struct Args {
}
#[tokio::main]
-async fn main() -> Result<()> {
+async fn main() -> Result<(), error::AppError> {
let args = Args::parse();
let config = include_str!("../warden.toml");
@@ -30,6 +39,14 @@ async fn main() -> Result<()> {
let _tracing = Tracing::builder().build(&config.monitoring);
- info!("Hello, world!");
+ let state = AppState::create(&config).await?;
+
+ let addr = SocketAddr::from((Ipv6Addr::UNSPECIFIED, config.application.port));
+
+ let listener = tokio::net::TcpListener::bind(addr).await?;
+ info!(port = addr.port(), "starting warden");
+
+ axum::serve(listener, server::router(state)).await?;
+
Ok(())
}
diff --git a/crates/warden/src/server.rs b/crates/warden/src/server.rs
new file mode 100644
index 0000000..15f80bd
--- /dev/null
+++ b/crates/warden/src/server.rs
@@ -0,0 +1,25 @@
+mod routes;
+
+use axum::{routing::get, Router};
+
+use crate::state::AppHandle;
+
+pub fn router(state: AppHandle) -> Router {
+ Router::new()
+ .route("/", get(routes::health_check))
+}
+
+
+#[cfg(test)]
+pub(crate) fn test_config() -> stack_up::Configuration {
+ use stack_up::Configuration;
+
+ let config_path = "warden.toml";
+
+ let config = config::Config::builder()
+ .add_source(config::File::new(config_path, config::FileFormat::Toml))
+ .build()
+ .unwrap();
+
+ config.try_deserialize::<Configuration>().unwrap()
+}
diff --git a/crates/warden/src/server/routes.rs b/crates/warden/src/server/routes.rs
new file mode 100644
index 0000000..e8e6705
--- /dev/null
+++ b/crates/warden/src/server/routes.rs
@@ -0,0 +1,36 @@
+use axum::response::IntoResponse;
+
+pub async fn health_check() -> impl IntoResponse {
+ let name = env!("CARGO_PKG_NAME");
+ let ver = env!("CARGO_PKG_VERSION");
+
+ format!("{name} v{ver} is live")
+}
+
+#[cfg(test)]
+mod tests {
+ use axum::{
+ body::Body,
+ http::{Request, StatusCode},
+ };
+ use tower::ServiceExt;
+
+ use crate::{
+ server::{self, test_config},
+ state::AppState,
+ };
+
+ #[tokio::test]
+ async fn health_check() {
+ let state = AppState::create( &test_config()).await.unwrap();
+ let app = server::router(state);
+
+ let response = app
+ .oneshot(Request::builder().uri("/").body(Body::empty()).unwrap())
+ .await
+ .unwrap();
+
+ assert_eq!(response.status(), StatusCode::OK);
+ }
+}
+
diff --git a/crates/warden/src/state.rs b/crates/warden/src/state.rs
new file mode 100644
index 0000000..ce44221
--- /dev/null
+++ b/crates/warden/src/state.rs
@@ -0,0 +1,40 @@
+use std::{ops::Deref, sync::Arc};
+use stack_up::{Configuration, Environment};
+
+use crate::{cnfg::LocalConfig, error::AppError};
+
+#[derive(Clone)]
+pub struct AppHandle(Arc<AppState>);
+
+impl Deref for AppHandle {
+ type Target = Arc<AppState>;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+#[derive(Clone)]
+pub struct Services {
+}
+
+pub struct AppState {
+ pub environment: Environment,
+}
+
+impl AppState {
+ pub async fn create(
+ configuration: &Configuration,
+ ) -> Result<AppHandle, AppError> {
+ let local_config: LocalConfig = serde_json::from_value(configuration.misc.clone())?;
+
+
+ Ok(
+
+ AppHandle(Arc::new(Self {
+ environment: configuration.application.env,
+ }
+ )))
+ }
+}
+
diff --git a/crates/warden/src/version.rs b/crates/warden/src/version.rs
new file mode 100644
index 0000000..1d4a9ca
--- /dev/null
+++ b/crates/warden/src/version.rs
@@ -0,0 +1,30 @@
+use std::collections::HashMap;
+
+use axum::{extract::{FromRequestParts, Path}, http::{request::Parts, StatusCode}, response::{IntoResponse, Response}, RequestPartsExt};
+
+#[derive(Debug)]
+pub enum Version {
+ V0,
+}
+
+
+impl<S> FromRequestParts<S> for Version
+where
+ S: Send + Sync,
+{
+ type Rejection = Response;
+
+ async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<Self, Self::Rejection> {
+ let params: Path<HashMap<String, String>> =
+ parts.extract().await.map_err(IntoResponse::into_response)?;
+
+ let version = params
+ .get("version")
+ .ok_or_else(|| (StatusCode::NOT_FOUND, "version param missing").into_response())?;
+
+ match version.as_str() {
+ "v0" => Ok(Version::V0),
+ _ => Err((StatusCode::NOT_FOUND, "unknown version").into_response()),
+ }
+ }
+}
diff --git a/crates/warden/warden.toml b/crates/warden/warden.toml
index ec10f51..5222260 100644
--- a/crates/warden/warden.toml
+++ b/crates/warden/warden.toml
@@ -2,6 +2,9 @@
env = "development"
port = 2210
+[misc]
+cache-ttl = 1000
+
[monitoring]
log-level = "warden=trace,info"