| 
									
										
										
										
											2024-09-24 20:26:15 -04:00
										 |  |  | use axum::Router;
 | 
					
						
							|  |  |  | use config::config;
 | 
					
						
							|  |  |  | use sqlx::{postgres::PgPoolOptions, PgPool};
 | 
					
						
							| 
									
										
										
										
											2024-09-26 13:11:55 -04:00
										 |  |  | use std::fs::File;
 | 
					
						
							|  |  |  | use std::sync::Arc;
 | 
					
						
							| 
									
										
										
										
											2024-09-22 22:38:35 -04:00
										 |  |  | use std::time::Duration;
 | 
					
						
							|  |  |  | use tokio::net::TcpListener;
 | 
					
						
							| 
									
										
										
										
											2024-09-24 20:26:15 -04:00
										 |  |  | use tokio::signal;
 | 
					
						
							| 
									
										
										
										
											2024-09-26 13:11:55 -04:00
										 |  |  | use tower_http::trace::{self, TraceLayer};
 | 
					
						
							|  |  |  | use tracing_subscriber::{filter, layer::SubscriberExt, prelude::*, util::SubscriberInitExt};
 | 
					
						
							| 
									
										
										
										
											2024-09-22 22:38:35 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-24 20:26:15 -04:00
										 |  |  | mod config;
 | 
					
						
							| 
									
										
										
										
											2024-09-22 22:38:35 -04:00
										 |  |  | mod datasources;
 | 
					
						
							|  |  |  | mod routes;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-24 20:26:15 -04:00
										 |  |  | pub struct AppState {
 | 
					
						
							|  |  |  |     db: PgPool,
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-22 22:38:35 -04:00
										 |  |  | #[tokio::main]
 | 
					
						
							|  |  |  | async fn main() {
 | 
					
						
							| 
									
										
										
										
											2024-09-26 13:11:55 -04:00
										 |  |  |     // setting up configuration
 | 
					
						
							| 
									
										
										
										
											2024-09-24 20:26:15 -04:00
										 |  |  |     let _ = config();
 | 
					
						
							| 
									
										
										
										
											2024-09-26 13:11:55 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // setting up logging
 | 
					
						
							|  |  |  |     let stdout_log = tracing_subscriber::fmt::layer().pretty();
 | 
					
						
							|  |  |  |     let file = File::create("debug.log");
 | 
					
						
							|  |  |  |     let file = match file {
 | 
					
						
							|  |  |  |         Ok(file) => file,
 | 
					
						
							|  |  |  |         Err(error) => panic!("Error: {:?}", error),
 | 
					
						
							|  |  |  |     };
 | 
					
						
							|  |  |  |     let debug_log = tracing_subscriber::fmt::layer().with_writer(Arc::new(file));
 | 
					
						
							|  |  |  |     let metrics_layer = filter::LevelFilter::INFO;
 | 
					
						
							| 
									
										
										
										
											2024-09-22 22:38:35 -04:00
										 |  |  |     tracing_subscriber::registry()
 | 
					
						
							|  |  |  |         .with(
 | 
					
						
							| 
									
										
										
										
											2024-09-26 13:11:55 -04:00
										 |  |  |             stdout_log
 | 
					
						
							|  |  |  |                 // Add an `INFO` filter to the stdout logging layer
 | 
					
						
							|  |  |  |                 .with_filter(filter::LevelFilter::INFO)
 | 
					
						
							|  |  |  |                 // Combine the filtered `stdout_log` layer with the
 | 
					
						
							|  |  |  |                 // `debug_log` layer, producing a new `Layered` layer.
 | 
					
						
							|  |  |  |                 .and_then(debug_log)
 | 
					
						
							|  |  |  |                 // Add a filter to *both* layers that rejects spans and
 | 
					
						
							|  |  |  |                 // events whose targets start with `metrics`.
 | 
					
						
							|  |  |  |                 .with_filter(filter::filter_fn(|metadata| {
 | 
					
						
							|  |  |  |                     !metadata.target().starts_with("metrics")
 | 
					
						
							|  |  |  |                 })),
 | 
					
						
							|  |  |  |         )
 | 
					
						
							|  |  |  |         .with(
 | 
					
						
							|  |  |  |             // Add a filter to the metrics label that *only* enables
 | 
					
						
							|  |  |  |             // events whose targets start with `metrics`.
 | 
					
						
							|  |  |  |             metrics_layer.with_filter(filter::filter_fn(|metadata| {
 | 
					
						
							|  |  |  |                 metadata.target().starts_with("metrics")
 | 
					
						
							|  |  |  |             })),
 | 
					
						
							| 
									
										
										
										
											2024-09-22 22:38:35 -04:00
										 |  |  |         )
 | 
					
						
							|  |  |  |         .init();
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-26 13:11:55 -04:00
										 |  |  |     // tracing_subscriber::registry()
 | 
					
						
							|  |  |  |     //     .with(
 | 
					
						
							|  |  |  |     //         tracing_subscriber::EnvFilter::try_from_default_env().unwrap_or_else(|_| {
 | 
					
						
							|  |  |  |     //             format!(
 | 
					
						
							|  |  |  |     //                 "{}=debug,tower_http=debug,axum=trace",
 | 
					
						
							|  |  |  |     //                 env!("CARGO_CRATE_NAME")
 | 
					
						
							|  |  |  |     //             )
 | 
					
						
							|  |  |  |     //             .into()
 | 
					
						
							|  |  |  |     //         }),
 | 
					
						
							|  |  |  |     //     )
 | 
					
						
							|  |  |  |     //     .with(tracing_subscriber::fmt::layer())
 | 
					
						
							|  |  |  |     //     .init();
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // grabbing the database url from our env variables
 | 
					
						
							|  |  |  |     let db_connection_str = std::env::var("DATABASE_URL")
 | 
					
						
							|  |  |  |         .unwrap_or_else(|_| "postgres://postgres:password@localhost".to_string());
 | 
					
						
							| 
									
										
										
										
											2024-09-22 22:38:35 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // set up connection pool
 | 
					
						
							|  |  |  |     let pool = PgPoolOptions::new()
 | 
					
						
							|  |  |  |         .max_connections(10)
 | 
					
						
							|  |  |  |         .acquire_timeout(Duration::from_secs(3))
 | 
					
						
							|  |  |  |         .connect(&db_connection_str)
 | 
					
						
							|  |  |  |         .await
 | 
					
						
							| 
									
										
										
										
											2024-09-24 20:26:15 -04:00
										 |  |  |         .expect("Failed to connect to database");
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     let app_state = AppState { db: pool.clone() };
 | 
					
						
							| 
									
										
										
										
											2024-09-22 22:38:35 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // build our application with some routes
 | 
					
						
							|  |  |  |     let app = Router::new()
 | 
					
						
							| 
									
										
										
										
											2024-09-24 20:26:15 -04:00
										 |  |  |         .nest("/", routes::root::RootRoute::routes())
 | 
					
						
							| 
									
										
										
										
											2024-09-26 13:11:55 -04:00
										 |  |  |         .nest("/posts", routes::posts::PostsRoute::routes(&app_state))
 | 
					
						
							|  |  |  |         .layer(
 | 
					
						
							|  |  |  |             TraceLayer::new_for_http()
 | 
					
						
							|  |  |  |                 .make_span_with(trace::DefaultMakeSpan::new().level(tracing::Level::INFO))
 | 
					
						
							|  |  |  |                 .on_response(trace::DefaultOnResponse::new().level(tracing::Level::INFO)),
 | 
					
						
							|  |  |  |         );
 | 
					
						
							| 
									
										
										
										
											2024-09-25 18:29:12 -04:00
										 |  |  |     // .nest(
 | 
					
						
							|  |  |  |     //     "/comments",
 | 
					
						
							|  |  |  |     //     routes::comments::CommentsRoute::routes(&app_state),
 | 
					
						
							|  |  |  |     // );
 | 
					
						
							| 
									
										
										
										
											2024-09-22 22:38:35 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // run it with hyper
 | 
					
						
							|  |  |  |     let listener = TcpListener::bind("0.0.0.0:3000").await.unwrap();
 | 
					
						
							|  |  |  |     tracing::debug!("listening on {}", listener.local_addr().unwrap());
 | 
					
						
							| 
									
										
										
										
											2024-09-24 20:26:15 -04:00
										 |  |  |     axum::serve(listener, app)
 | 
					
						
							|  |  |  |         .with_graceful_shutdown(shutdown_signal())
 | 
					
						
							|  |  |  |         .await
 | 
					
						
							|  |  |  |         .unwrap();
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | async fn shutdown_signal() {
 | 
					
						
							|  |  |  |     let ctrl_c = async {
 | 
					
						
							|  |  |  |         signal::ctrl_c()
 | 
					
						
							|  |  |  |             .await
 | 
					
						
							|  |  |  |             .expect("Failed to install Ctrl+C handler");
 | 
					
						
							|  |  |  |     };
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     #[cfg(unix)]
 | 
					
						
							|  |  |  |     let terminate = async {
 | 
					
						
							|  |  |  |         signal::unix::signal(signal::unix::SignalKind::terminate())
 | 
					
						
							|  |  |  |             .expect("Failed to install signal handler")
 | 
					
						
							|  |  |  |             .recv()
 | 
					
						
							|  |  |  |             .await;
 | 
					
						
							|  |  |  |     };
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     #[cfg(not(unix))]
 | 
					
						
							|  |  |  |     let terminate = std::future::pending::<()>();
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     tokio::select! {
 | 
					
						
							|  |  |  |         _ = ctrl_c => {},
 | 
					
						
							|  |  |  |         _ = terminate => {},
 | 
					
						
							|  |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2024-09-03 01:17:19 -04:00
										 |  |  | }
 |