Refactor to clean-up axum server implementation

This commit is contained in:
Alex Selimov 2026-03-17 10:53:57 -04:00
parent 09e538872d
commit 4b16f39b4d
10 changed files with 1308 additions and 57 deletions

1256
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -6,6 +6,7 @@ edition = "2024"
[dependencies] [dependencies]
axum = "0.8" axum = "0.8"
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }
sqlx = { version = "0.8.6", features = ["runtime-tokio", "postgres", "macros"] }
tokio = { version = "1", features = ["full"] } tokio = { version = "1", features = ["full"] }
tower = "0.5" tower = "0.5"
tower-http = { version = "0.6", features = ["trace"] } tower-http = { version = "0.6", features = ["trace"] }

17
src/env.rs Normal file
View file

@ -0,0 +1,17 @@
use std::env;
#[derive(Clone)]
pub struct Env {
pub postgres_connection_string: String,
}
impl Env {
pub fn parse_env() -> Env {
let postgres_connection_string = env::var("POSTGRES_CONNECTION_STRING")
.expect("Missing POSTGRES_CONNECTION_STRING as an environment variable");
Env {
postgres_connection_string,
}
}
}

View file

@ -1,9 +1,12 @@
pub mod env;
pub mod routes; pub mod routes;
pub mod state;
pub mod votes; pub mod votes;
use axum::Router; use axum::Router;
use state::AppState;
use tower_http::trace::TraceLayer; use tower_http::trace::TraceLayer;
pub fn app() -> Router { pub fn app(state: AppState) -> Router {
routes::router().layer(TraceLayer::new_for_http()) routes::router(state).layer(TraceLayer::new_for_http())
} }

View file

@ -1,4 +1,5 @@
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
use uprs::state::AppState;
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
@ -13,5 +14,7 @@ async fn main() {
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap(); let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
tracing::info!("listening on {}", listener.local_addr().unwrap()); tracing::info!("listening on {}", listener.local_addr().unwrap());
axum::serve(listener, uprs::app()).await.unwrap(); axum::serve(listener, uprs::app(AppState::new().await))
.await
.unwrap();
} }

View file

@ -1,15 +1,12 @@
use std::sync::Arc;
use axum::{Router, routing::get}; use axum::{Router, routing::get};
use crate::votes::{repository::VoteRepository, service::VoteService}; use crate::state::AppState;
pub fn router() -> Router {
let vote_service = Arc::new(VoteService::new(VoteRepository::new()));
pub fn router(state: AppState) -> Router {
Router::new() Router::new()
.route("/health", get(health)) .route("/health", get(health))
.merge(crate::votes::handlers::router(vote_service)) .merge(crate::votes::handlers::router())
.with_state(state)
} }
async fn health() -> &'static str { async fn health() -> &'static str {

19
src/state.rs Normal file
View file

@ -0,0 +1,19 @@
use sqlx::PgPool;
use crate::env::Env;
#[derive(Clone)]
pub struct AppState {
pub db: PgPool,
pub env: Env,
}
impl AppState {
pub async fn new() -> Self {
let env = Env::parse_env();
let db = sqlx::PgPool::connect(&env.postgres_connection_string)
.await
.expect("Unable to connect to postgres db");
AppState { db, env }
}
}

View file

@ -1,29 +1,13 @@
use std::sync::Arc;
use axum::{ use axum::{
Router, Router,
extract::{Path, State}, extract::{Path, State},
routing::{get, post}, routing::{get, post},
}; };
use super::{dto::CreateVoteRequest, service::VoteService}; use crate::state::AppState;
pub fn router(service: Arc<VoteService>) -> Router { use super::dto::CreateVoteRequest;
pub fn router() -> Router<AppState> {
Router::new() Router::new()
.route("/votes", get(list))
.route("/votes/{id}", get(get_by_id))
.route("/votes", post(create))
.with_state(service)
}
async fn list(State(service): State<Arc<VoteService>>) {
todo!()
}
async fn get_by_id(State(service): State<Arc<VoteService>>, Path(id): Path<u64>) {
todo!()
}
async fn create(State(service): State<Arc<VoteService>>, body: axum::Json<CreateVoteRequest>) {
todo!()
} }

View file

@ -1,9 +1,3 @@
use sqlx::PgPool;
use super::model::Vote; use super::model::Vote;
pub struct VoteRepository {}
impl VoteRepository {
pub fn new() -> Self {
Self {}
}
}

View file

@ -1,14 +1,3 @@
use super::{ use crate::state::AppState;
dto::{CreateVoteRequest, VoteResponse},
repository::VoteRepository,
};
pub struct VoteService { use super::dto::{CreateVoteRequest, VoteResponse};
repository: VoteRepository,
}
impl VoteService {
pub fn new(repository: VoteRepository) -> Self {
Self { repository }
}
}