diff --git a/Cargo.lock b/Cargo.lock index eb0a0c5..23de700 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -35,12 +35,25 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "arch-api" version = "0.1.0" +dependencies = [ + "arch-core", + "axum", + "hyper", + "hyper-util", + "thiserror", + "tokio", + "tokio-graceful-shutdown", + "tower", + "tower-http", + "tracing", +] [[package]] name = "arch-core" version = "0.1.0" dependencies = [ "async-trait", + "tracing", ] [[package]] @@ -54,12 +67,82 @@ dependencies = [ "syn", ] +[[package]] +name = "atomic" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d818003e740b63afc82337e3160717f4f63078720a810b7b903e70a5d1d2994" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "autocfg" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +[[package]] +name = "axum" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" +dependencies = [ + "async-trait", + "axum-core", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-util", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "serde_json", + "serde_path_to_error", + "serde_urlencoded", + "sync_wrapper 1.0.1", + "tokio", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "axum-core" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "mime", + "pin-project-lite", + "rustversion", + "sync_wrapper 0.1.2", + "tower-layer", + "tower-service", + "tracing", +] + [[package]] name = "backtrace" version = "0.3.73" @@ -81,6 +164,26 @@ version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +[[package]] +name = "bytemuck" +version = "1.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "102087e286b4677862ea56cf8fc58bb2cdfa8725c40ffb80fe3a008eb7f2fc83" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ee891b04274a59bd38b412188e24b849617b2e45a0fd8d057deb63e7403761b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "bytes" version = "1.6.1" @@ -99,18 +202,195 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + [[package]] name = "gimli" version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +[[package]] +name = "h2" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + [[package]] name = "hermit-abi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-util" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ab92f4f49ee4fb4f997c784b7a2e0fa70050211e0b6a287f898c3c9785ca956" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "indexmap" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0" +dependencies = [ + "equivalent", + "hashbrown", +] + [[package]] name = "itoa" version = "1.0.11" @@ -154,12 +434,47 @@ dependencies = [ "regex-automata 0.1.10", ] +[[package]] +name = "matchit" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" + [[package]] name = "memchr" version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "miette" +version = "7.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4edc8853320c2a0dab800fbda86253c8938f6ea88510dc92c5f1ed20e794afc1" +dependencies = [ + "cfg-if", + "miette-derive", + "thiserror", + "unicode-width", +] + +[[package]] +name = "miette-derive" +version = "7.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf09caffaac8068c346b6df2a7fc27a177fd20b39421a39ce0a211bde679a6c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + [[package]] name = "miniz_oxide" version = "0.7.4" @@ -235,12 +550,44 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "pin-project-lite" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + [[package]] name = "proc-macro2" version = "1.0.86" @@ -317,9 +664,11 @@ name = "rust-arch" version = "0.1.0" dependencies = [ "anyhow", + "arch-api", "arch-core", "log", "tokio", + "tokio-graceful-shutdown", "tracing", "tracing-log", "tracing-subscriber", @@ -331,6 +680,12 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +[[package]] +name = "rustversion" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" + [[package]] name = "ryu" version = "1.0.18" @@ -374,6 +729,28 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_path_to_error" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" +dependencies = [ + "itoa", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -392,6 +769,15 @@ dependencies = [ "libc", ] +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + [[package]] name = "smallvec" version = "1.13.2" @@ -419,6 +805,38 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" + +[[package]] +name = "thiserror" +version = "1.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "thread_local" version = "1.1.8" @@ -447,6 +865,23 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "tokio-graceful-shutdown" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fafa3ccdad018530a5eb1c2c87772384fb94273675022240bc5729044f7696e5" +dependencies = [ + "async-trait", + "atomic", + "bytemuck", + "miette", + "pin-project-lite", + "thiserror", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "tokio-macros" version = "2.4.0" @@ -458,6 +893,65 @@ dependencies = [ "syn", ] +[[package]] +name = "tokio-util" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-http" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" +dependencies = [ + "bitflags", + "bytes", + "http", + "http-body", + "http-body-util", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + [[package]] name = "tracing" version = "0.1.40" @@ -533,12 +1027,24 @@ dependencies = [ "tracing-serde", ] +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "unicode-width" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" + [[package]] name = "utils" version = "0.1.0" @@ -549,6 +1055,15 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index 401beab..63df880 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,9 +14,11 @@ rust-version = "1.79" [workspace.dependencies] arch-api = { path = "crates/api" } -arch-core = { path = "crates/core"} +arch-core = { path = "crates/core" } async-trait = "0.1.81" +thiserror = "1.0.63" +tokio-graceful-shutdown = "0.15.0" [workspace.dependencies.tokio] version = "1.39.1" diff --git a/crates/api/Cargo.toml b/crates/api/Cargo.toml index 94634f2..3b00ce8 100644 --- a/crates/api/Cargo.toml +++ b/crates/api/Cargo.toml @@ -10,3 +10,27 @@ readme.workspace = true rust-version.workspace = true [dependencies] +arch-core.workspace = true + +thiserror.workspace = true +tokio.workspace = true +tokio-graceful-shutdown.workspace = true +tracing.workspace = true + +axum = "0.7.5" + +[dependencies.hyper] +version = "1.3.1" +features = ["full"] + +[dependencies.hyper-util] +version = "0.1.3" +features = ["tokio", "server-auto", "http1"] + +[dependencies.tower] +version = "0.4.13" +features = ["util"] + +[dependencies.tower-http] +version = "0.5.2" +features = ["timeout", "trace"] diff --git a/crates/api/src/api_error.rs b/crates/api/src/api_error.rs new file mode 100644 index 0000000..72d22e7 --- /dev/null +++ b/crates/api/src/api_error.rs @@ -0,0 +1,5 @@ +#[derive(Debug, thiserror::Error)] +pub enum ApiError { + #[error("Bad port - {}", _0)] + BadPort(u16), +} diff --git a/crates/api/src/lib.rs b/crates/api/src/lib.rs index b93cf3f..36acff8 100644 --- a/crates/api/src/lib.rs +++ b/crates/api/src/lib.rs @@ -1,14 +1,91 @@ -pub fn add(left: u64, right: u64) -> u64 { - left + right +use std::{net::SocketAddr, sync::Arc, time::Duration}; + +use arch_core::ArchService; + +pub mod api_error; + +pub use api_error::*; +use axum::{ + extract::{Request, State}, + response::{IntoResponse, Response}, + routing::get, + Router, +}; +use hyper::{body::Incoming, StatusCode}; +use hyper_util::rt::TokioIo; +use tokio::net::{TcpListener, TcpStream}; +use tokio_graceful_shutdown::{SubsystemBuilder, SubsystemHandle}; +use tower::Service; +use tower_http::timeout::TimeoutLayer; + +pub async fn start_http(port: u16, arch_service: Arc, subsys: SubsystemHandle) -> Result<(), ApiError> { + tracing::trace!("Starting http service"); + + let addr: SocketAddr = format!("0.0.0.0:{}", port).parse().map_err(|_| ApiError::BadPort(port))?; + let listener = TcpListener::bind(addr).await.unwrap(); + + let routes = get_routes(arch_service.clone()); + + tracing::info!("Listening on port {}", port); + loop { + let (socket, remote_addr) = tokio::select! { + _ = subsys.on_shutdown_requested() => { + break; + } + + result = listener.accept() => { + result.unwrap() + } + }; + + tracing::debug!("connection {} accepted", remote_addr); + let tower_service = routes.clone(); + let name = format!("handler-{remote_addr}"); + subsys.start(SubsystemBuilder::new(name, move |h| handler(socket, remote_addr, tower_service, h))); + } + + Ok(()) } -#[cfg(test)] -mod tests { - use super::*; +fn get_routes(arch_service: Arc) -> Router<()> { + axum::Router::new() + .route("/health", get(health)) + .with_state(arch_service) + .layer(TimeoutLayer::new(Duration::from_secs(2))) +} + +pub async fn handler(socket: TcpStream, remote_addr: SocketAddr, tower_service: Router<()>, subsys: SubsystemHandle) -> Result<(), ApiError> { + let socket = TokioIo::new(socket); + let hyper_service = hyper::service::service_fn(move |request: Request| tower_service.clone().call(request)); + let conn = hyper::server::conn::http1::Builder::new().serve_connection(socket, hyper_service); + let mut conn = std::pin::pin!(conn); + + tokio::select! { + result = conn.as_mut() => { + if let Err(err) = result { + tracing::warn!("Failed to serve connection{}: {:#}", remote_addr, err); + } + } + + _ = subsys.on_shutdown_requested() => { + tracing::debug!("signal received, starting graceful shutdown"); + } + } + + tracing::debug!("Connection {} closed", remote_addr); + Ok(()) +} + +#[tracing::instrument(level = "trace", skip(arch_service))] +pub async fn health(State(arch_service): State>) -> impl IntoResponse { + match arch_service.health_service.is_healthy().await { + true => StatusCode::OK, + false => StatusCode::BAD_REQUEST, + } +} - #[test] - fn it_works() { - let result = add(2, 2); - assert_eq!(result, 4); +impl IntoResponse for ApiError { + fn into_response(self) -> Response { + (StatusCode::INTERNAL_SERVER_ERROR, format!("Something went wrong: {}", self)).into_response() } } diff --git a/crates/apps/Cargo.toml b/crates/apps/Cargo.toml index 6de26b3..ce7ba6e 100644 --- a/crates/apps/Cargo.toml +++ b/crates/apps/Cargo.toml @@ -15,9 +15,11 @@ anyhow = "1.0.86" log = "0.4.22" tracing-log = "0.2.0" +arch-api.workspace = true arch-core.workspace = true tokio.workspace = true +tokio-graceful-shutdown.workspace = true tracing.workspace = true [dependencies.tracing-subscriber] diff --git a/crates/apps/src/main.rs b/crates/apps/src/main.rs index 70d7190..8e71297 100644 --- a/crates/apps/src/main.rs +++ b/crates/apps/src/main.rs @@ -1,6 +1,10 @@ +use std::{sync::Arc, time::Duration}; + +use arch_api::start_http; use arch_core::create_service; use anyhow::Result; +use tokio_graceful_shutdown::{SubsystemBuilder, Toplevel}; mod logging; @@ -8,9 +12,17 @@ mod logging; async fn main() -> Result<()> { logging::init_logging()?; - let arch_service = create_service(); + let arch_service = Arc::new(create_service()); tracing::info!("Hello, world!"); tracing::info!("Healthy={}", arch_service.health_service.is_healthy().await); + let server = Toplevel::new(|s| async move { + s.start(SubsystemBuilder::new("http_api", |h| start_http(3000, arch_service, h))); + }) + .catch_signals() + .handle_shutdown_requests(Duration::from_secs(5)); + + server.await?; + Ok(()) } diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml index 2a1fa22..90c5211 100644 --- a/crates/core/Cargo.toml +++ b/crates/core/Cargo.toml @@ -11,3 +11,4 @@ rust-version.workspace = true [dependencies] async-trait.workspace = true +tracing.workspace = true diff --git a/crates/core/src/health.rs b/crates/core/src/health.rs index ba0dd7d..d3923dc 100644 --- a/crates/core/src/health.rs +++ b/crates/core/src/health.rs @@ -2,10 +2,12 @@ use async_trait::async_trait; use crate::HealthService; +#[derive(Clone)] pub(crate) struct HealthServiceImpl {} #[async_trait] impl HealthService for HealthServiceImpl { + #[tracing::instrument(level = "trace", skip(self))] async fn is_healthy(&self) -> bool { true } diff --git a/crates/core/src/lib.rs b/crates/core/src/lib.rs index 055d5c1..92ac542 100644 --- a/crates/core/src/lib.rs +++ b/crates/core/src/lib.rs @@ -4,7 +4,7 @@ use health::HealthServiceImpl; mod health; #[async_trait] -pub trait HealthService { +pub trait HealthService: Send + Sync { async fn is_healthy(&self) -> bool; }