diff --git a/src/commands/download.rs b/src/commands/download.rs index 74817b8..c73c8f9 100644 --- a/src/commands/download.rs +++ b/src/commands/download.rs @@ -110,9 +110,17 @@ pub async fn download( } let url = make_absolute_url(&conn, &f.download_url); let conn = conn.clone(); + let remote = remote.clone(); futs.push(tokio::spawn(async move { + // Refresh the access token if it has expired or is about to + // expire. conn.with_token() reuses the shared HTTP client + // (connection pool) while supplying a fresh Bearer token. + let task_conn = match load_cache_with_token_refresh(&remote).await { + Ok(c) => conn.with_token(c.token.access), + Err(e) => { eprintln!("Error: {}", e); return; } + }; let dest_str = dest_path.to_string_lossy().to_string(); - match conn.download_file(&url, &dest_str).await { + match task_conn.download_file(&url, &dest_str).await { Ok(_) => println!("{}", dest_path.display()), Err(_) => { eprintln!("Failed: {}", dest_path.display()); diff --git a/src/commands/upload.rs b/src/commands/upload.rs index 6a25e6d..2d83be1 100644 --- a/src/commands/upload.rs +++ b/src/commands/upload.rs @@ -102,8 +102,16 @@ pub async fn upload( let folder_id = remote_id.clone(); let remote_path_prefix = folder_detail.path.clone(); let fname = filename.clone(); + let remote = remote.clone(); futs.push(tokio::spawn(async move { - match conn.upload_file(&folder_id, &file_path_str).await { + // Refresh the access token if it has expired or is about to + // expire. conn.with_token() reuses the shared HTTP client + // (connection pool) while supplying a fresh Bearer token. + let task_conn = match load_cache_with_token_refresh(&remote).await { + Ok(c) => conn.with_token(c.token.access), + Err(e) => { eprintln!("Error: {}", e); return; } + }; + match task_conn.upload_file(&folder_id, &file_path_str).await { Ok(_) => println!("{}{}", remote_path_prefix, fname), Err(e) => eprintln!("Error: {}", e), } diff --git a/src/connection.rs b/src/connection.rs index fa8dd88..b7a13aa 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -41,6 +41,21 @@ impl MDRSConnection { } } + /// Create a new connection that shares the HTTP client (and its connection + /// pool) with the receiver but uses a fresh access token. Useful for + /// spawning per-task connections without allocating a new connection pool + /// for every concurrent task. + /// + /// `reqwest::Client` wraps an internal `Arc`; cloning it is cheap and + /// keeps the shared pool intact. + pub fn with_token(&self, access_token: String) -> Self { + MDRSConnection { + url: self.url.clone(), + client: self.client.clone(), + token: Some(access_token), + } + } + pub fn build_url(&self, path: &str) -> String { format!("{}/{}", self.url.trim_end_matches('/'), path) }