diff --git a/services/blob/src/config.rs b/services/blob/src/config.rs index a11e6316f..bdb166d26 100644 --- a/services/blob/src/config.rs +++ b/services/blob/src/config.rs @@ -1,64 +1,68 @@ use anyhow::Result; -use clap::Parser; +use clap::{ArgAction, Parser}; use once_cell::sync::Lazy; use tracing::info; use crate::constants::{ DEFAULT_HTTP_PORT, DEFAULT_S3_BUCKET_NAME, S3_BUCKET_ENV_VAR, }; #[derive(Parser)] #[command(version, about, long_about = None)] pub struct AppConfig { /// HTTP server listening port #[arg(long, default_value_t = DEFAULT_HTTP_PORT, global = true)] pub http_port: u16, /// AWS Localstack service URL #[arg(env = "LOCALSTACK_ENDPOINT")] #[arg(long)] pub localstack_endpoint: Option, #[arg(env = S3_BUCKET_ENV_VAR)] #[arg(long, default_value_t = DEFAULT_S3_BUCKET_NAME.to_string())] pub s3_bucket_name: String, /// Identity service endpoint #[arg(env = "IDENTITY_SERVICE_ENDPOINT")] #[arg(long, default_value = "http://localhost:50054")] pub identity_endpoint: String, + /// If set, blobs will be deleted instantly after revoking last holder + #[arg(long, global = true, action = ArgAction::SetTrue)] + pub instant_delete: bool, + #[clap(subcommand)] pub command: Option, } #[derive(clap::Subcommand)] pub enum Command { Server, Cleanup, } /// Stores configuration parsed from command-line arguments /// and environment variables pub static CONFIG: Lazy = Lazy::new(AppConfig::parse); /// Processes the command-line arguments and environment variables. /// Should be called at the beginning of the `main()` function. pub(super) fn parse_cmdline_args() -> Result<&'static AppConfig> { // force evaluation of the lazy initialized config let cfg = Lazy::force(&CONFIG); if cfg.s3_bucket_name != DEFAULT_S3_BUCKET_NAME { info!("Using custom S3 bucket: {}", &cfg.s3_bucket_name); } Ok(cfg) } /// Provides region/credentials configuration for AWS SDKs pub async fn load_aws_config() -> aws_config::SdkConfig { let mut config_builder = aws_config::from_env(); if let Some(endpoint) = &CONFIG.localstack_endpoint { info!("Using Localstack. AWS endpoint URL: {}", endpoint); config_builder = config_builder.endpoint_url(endpoint); } config_builder.load().await } diff --git a/services/blob/src/main.rs b/services/blob/src/main.rs index 13bef2ae2..c44471e29 100644 --- a/services/blob/src/main.rs +++ b/services/blob/src/main.rs @@ -1,48 +1,55 @@ pub mod config; pub mod constants; pub mod database; pub mod http; pub mod s3; pub mod service; pub mod tools; use anyhow::Result; use comm_services_lib::auth::AuthService; use config::Command; use tracing_subscriber::filter::{EnvFilter, LevelFilter}; use crate::service::BlobServiceConfig; fn configure_logging() -> Result<()> { let filter = EnvFilter::builder() .with_default_directive(LevelFilter::INFO.into()) .with_env_var(constants::LOG_LEVEL_ENV_VAR) .from_env_lossy(); let subscriber = tracing_subscriber::fmt().with_env_filter(filter).finish(); tracing::subscriber::set_global_default(subscriber)?; Ok(()) } #[tokio::main] async fn main() -> Result<()> { configure_logging()?; let config = config::parse_cmdline_args()?; let aws_config = config::load_aws_config().await; let db = database::DatabaseClient::new(&aws_config); let s3 = s3::S3Client::new(&aws_config); let auth_service = AuthService::new(&aws_config, &config.identity_endpoint); - let blob_service = - service::BlobService::new(db, s3, BlobServiceConfig::default()); + let blob_service = service::BlobService::new( + db, + s3, + BlobServiceConfig { + instant_delete_orphaned_blobs: config.instant_delete, + // orphan_protection_period: chrono::Duration::milliseconds(1), + ..Default::default() + }, + ); match &config.command { Some(Command::Cleanup) => blob_service.perform_cleanup().await?, None | Some(Command::Server) => { crate::http::run_http_server(blob_service, auth_service).await? } }; Ok(()) }