use diesel::{r2d2::ConnectionManager as DieselConnectionManager, PgConnection}; use redis::{Client as RedisClient, aio::Connection as RedisConnection}; use s3::{Region, creds::Credentials, Bucket, BucketConfiguration, request::ResponseData}; use siren::ServiceError; use crate::diesel_migrations::MigrationHarness; use lazy_static::lazy_static; use log::{error, info}; use r2d2; use std::env; pub mod schema; type DbPool = r2d2::Pool>; pub type DbConnection = r2d2::PooledConnection>; pub const MIGRATIONS: diesel_migrations::EmbeddedMigrations = embed_migrations!(); lazy_static! { static ref POOL: DbPool = { let username = env::var("DATABASE_USER").expect("DATABASE_USERNAME is not set"); let password = env::var("DATABASE_PASSWORD").expect("DATABASE_PASSWORD is not set"); let host = env::var("DATABASE_HOST").unwrap_or("localhost".to_string()); let name = env::var("DATABASE_NAME").expect("DATABASE_NAME is not set"); let port = env::var("DATABASE_PORT").unwrap_or("5432".to_string()); let url = format!( "postgres://{}:{}@{}:{}/{}", username, password, host, port, name ); let manager = DieselConnectionManager::::new(url); DbPool::builder() .test_on_check_out(true) .build(manager) .expect("Failed to create db pool") }; static ref REDIS: RedisClient = { let host = env::var("REDIS_HOST").unwrap_or("localhost".to_string()); let port = env::var("REDIS_PORT").unwrap_or("6379".to_string()); let url = format!("redis://{}:{}", host, port); RedisClient::open(url).expect("Failed to create redis client") }; static ref BUCKET: Bucket = { let url = env::var("MINIO_HOST").unwrap_or("localhost".to_string()); let port = env::var("MINIO_PORT").unwrap_or("9000".to_string()); let user = env::var("MINIO_ROOT_USER").expect("MINIO_ROOT_USER is not set"); let password = env::var("MINIO_ROOT_PASSWORD").expect("MINIO_ROOT_PASSWORD is not set"); let base_url = format!("http://{}:{}", url, port); let region = Region::Custom { region: "".to_string(), endpoint: base_url, }; let credentials = Credentials { access_key: Some(user), secret_key: Some(password), security_token: None, session_token: None, expiration: None, }; Bucket::new("siren", region.clone(), credentials.clone()) .expect("Failed to create S3 Bucket") .with_path_style() }; } pub async fn init() { lazy_static::initialize(&POOL); lazy_static::initialize(&REDIS); lazy_static::initialize(&BUCKET); create_bucket().await; let mut pool: DbConnection = connection().expect("Failed to get db connection"); match pool.run_pending_migrations(MIGRATIONS) { Ok(_) => info!("Database initialized"), Err(err) => error!("Failed to initialize database; {}", err), }; } pub fn connection() -> Result { POOL .get() .map_err(|e| ServiceError::new(500, format!("Failed getting db connection: {}", e))) } pub fn redis_connection() -> Result { let conn = REDIS.get_connection()?; Ok(conn) } pub async fn redis_async_connection() -> Result { let conn = REDIS.get_async_connection().await?; Ok(conn) } async fn create_bucket() { let url = env::var("MINIO_URL").unwrap_or("localhost".to_string()); let port = env::var("MINIO_PORT").unwrap_or("9000".to_string()); let user = env::var("MINIO_ROOT_USER").expect("MINIO_ROOT_USER is not set"); let password = env::var("MINIO_ROOT_PASSWORD").expect("MINIO_ROOT_PASSWORD is not set"); let base_url = format!("http://{}:{}", url, port); let region = Region::Custom { region: "".to_string(), endpoint: base_url, }; let credentials = Credentials { access_key: Some(user), secret_key: Some(password), security_token: None, session_token: None, expiration: None, }; let _ = Bucket::create_with_path_style("siren", region, credentials, BucketConfiguration::default()) .await; } pub async fn upload_file(path: &str, content: &[u8]) -> Result { let response = BUCKET.put_object(path, content).await?; Ok(response) } pub async fn get_file(path: &str) -> Result, ServiceError> { let response = BUCKET.get_object(path).await?; let bytes = response.bytes(); Ok(bytes.to_vec()) } pub async fn delete_file(path: &str) -> Result { let response = BUCKET.delete_object(path).await?; Ok(response) }