61 lines
1.6 KiB
Rust
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
|
|
}
|
|
}
|