Files
oe1-player/src/downloader.rs
Philipp Hofer a7ab1e8360
All checks were successful
CI/CD Pipeline / test (push) Successful in 2m51s
CI/CD Pipeline / deploy (push) Successful in 3m44s
retry failed chunk downloads; Continues #1
2025-07-28 21:29:58 +02:00

61 lines
1.6 KiB
Rust

use crate::state::AppState;
use std::{sync::Arc, time::Duration};
use tokio::time::timeout;
use tokio_stream::StreamExt;
pub async fn spawn_download_task(url: &str, state: Arc<AppState>) {
state.reset().await;
let url = url.to_string();
tokio::spawn(async move {
if let Err(e) = download_stream(&url, state).await {
eprintln!("Download failed: {e:?}");
}
});
}
async fn download_stream(url: &str, state: Arc<AppState>) -> Result<(), reqwest::Error> {
println!("Starting download from: {url}");
let response = reqwest::Client::new().get(url).send().await?;
let mut stream = response.bytes_stream();
loop {
let Ok(bytes) = timeout(Duration::from_secs(5), stream.next()).await else {
println!("Error fetching stream, trying again...");
continue;
};
if handle_bytes(bytes, state.clone()).await {
break;
}
}
state.mark_complete().await;
println!("Download complete!");
Ok(())
}
/// Returns if the end (= no more bytes) has been received
async fn handle_bytes(
bytes: Option<Result<bytes::Bytes, reqwest::Error>>,
state: Arc<AppState>,
) -> bool {
// TODO: switch checks, such that `.transpose()` is not needed anymore
let bytes = match bytes.transpose() {
Ok(bytes) => bytes,
Err(e) => {
println!("Error fetching chunk from stream: {e:?}");
return false;
}
};
if let Some(bytes) = bytes {
state.add_chunk(bytes).await;
false
} else {
true
}
}