use std::time::Duration; use cache::{AppCache, AppCacheConfig}; use config::AppConfig; use db::database::AppDatabase; use deadpool_redis::{PoolConfig, Runtime, Timeouts, cluster::Config}; pub struct AppContext { pub config: AppConfig, pub db: AppDatabase, pub cache: AppCache, pub redis_pool: deadpool_redis::cluster::Pool, } impl AppContext { pub async fn init() -> anyhow::Result { let config = AppConfig::load(); init_tracing(&config)?; tracing::info!("initializing database"); let db = AppDatabase::init(&config).await?; tracing::info!("initializing cache"); let cache_config = AppCacheConfig::try_from(&config)?; let cache = AppCache::init(cache_config).await?; tracing::info!("initializing redis pool"); let redis_urls = config.redis_urls()?; let pool_size = config.redis_pool_size()?; let connect_timeout = config.redis_connect_timeout()?; let acquire_timeout = config.redis_acquire_timeout()?; let mut pool_config = PoolConfig::new(pool_size as usize); pool_config.timeouts = Timeouts { wait: Some(Duration::from_secs(acquire_timeout)), create: Some(Duration::from_secs(connect_timeout)), recycle: Some(Duration::from_secs(connect_timeout)), }; let cfg = Config { urls: Some(redis_urls), connections: None, pool: Some(pool_config), read_from_replicas: false, }; let redis_pool = cfg.create_pool(Some(Runtime::Tokio1))?; Ok(Self { config, db, cache, redis_pool, }) } } fn init_tracing(config: &AppConfig) -> anyhow::Result<()> { let level = config.log_level()?; let filter = tracing_subscriber::EnvFilter::try_new(&level)?; tracing_subscriber::fmt() .with_env_filter(filter) .with_target(false) .init(); Ok(()) }