use database_service::db::Database; use database_service::grpc::character_db_service_server::CharacterDbServiceServer; use database_service::grpc::database_service::MyDatabaseService; use database_service::grpc::user_service_server::UserServiceServer; use dotenv::dotenv; use sqlx::postgres::PgPoolOptions; use std::collections::HashMap; use std::env; use std::str::FromStr; use std::sync::Arc; use tokio::sync::Mutex; use tonic::transport::Server; use tracing::{info, Level}; use utils::consul_registration; use utils::redis_cache::RedisCache; #[tokio::main] async fn main() -> Result<(), Box> { dotenv().ok(); tracing_subscriber::fmt() .with_max_level( Level::from_str(&env::var("LOG_LEVEL").unwrap_or_else(|_| "info".to_string())) .unwrap_or_else(|_| Level::INFO), ) .init(); let addr = env::var("LISTEN_ADDR").unwrap_or_else(|_| "0.0.0.0".to_string()); let port = env::var("DATABASE_SERVICE_PORT").unwrap_or_else(|_| "50052".to_string()); let database_url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set"); let redis_url = std::env::var("REDIS_URL").unwrap_or_else(|_| "redis://127.0.0.1:6379".to_string()); let consul_url = env::var("CONSUL_URL").unwrap_or_else(|_| "http://127.0.0.1:8500".to_string()); let service_name = env::var("SERVICE_NAME").unwrap_or_else(|_| "database-service".to_string()); let service_address = env::var("DATABASE_SERVICE_ADDR").unwrap_or_else(|_| "127.0.0.1".to_string()); let service_port = port.clone(); // Register service with Consul let service_id = consul_registration::get_or_generate_service_id(env!("CARGO_PKG_NAME")); let version = env!("CARGO_PKG_VERSION").to_string(); let tags = vec![version, "grpc".to_string()]; let meta = HashMap::new(); consul_registration::register_service( &consul_url, service_id.as_str(), service_name.as_str(), service_address.as_str(), service_port.parse().unwrap_or(50052), tags, meta, None, None, ) .await?; consul_registration::start_health_check(addr.as_str()).await?; let full_addr = format!("{}:{}", &addr, port); let address = full_addr.parse().expect("Invalid address"); let pool = PgPoolOptions::new() .max_connections(5) .connect(&database_url) .await .expect("Failed to create PostgreSQL connection pool"); let redis_cache = Arc::new(Mutex::new(RedisCache::new(&redis_url))); let db = Arc::new(Database::new(pool, redis_cache)); let my_service = MyDatabaseService { db }; let (mut health_reporter, health_service) = tonic_health::server::health_reporter(); health_reporter.set_serving::>().await; // Pass `shared_cache` into services as needed info!("Database Service running on {}", address); tokio::spawn( Server::builder() .add_service(health_service) .add_service(UserServiceServer::new(my_service.clone())) .add_service(CharacterDbServiceServer::new(my_service)) .serve(address), ); utils::signal_handler::wait_for_signal().await; consul_registration::deregister_service(&consul_url, service_id.as_str()) .await .expect(""); info!("service {} deregistered", service_name); Ok(()) }