remove download states map

This commit is contained in:
2025-01-05 17:47:07 +08:00
parent c64e6573d9
commit 8d61fe5b39

View File

@@ -1,4 +1,4 @@
use std::{collections::HashMap, sync::Arc}; use std::sync::Arc;
use axum::{ use axum::{
body::Bytes, body::Bytes,
@@ -8,19 +8,10 @@ use axum::{
}; };
use image::GenericImageView; use image::GenericImageView;
use reqwest::StatusCode; use reqwest::StatusCode;
use tokio::sync::{Mutex, Notify};
use webp::WebPConfig; use webp::WebPConfig;
#[derive(Debug)] #[derive(Debug)]
struct Downloader { struct Downloader {}
states: Arc<Mutex<HashMap<String, Arc<DownloadState>>>>,
}
#[derive(Debug)]
struct DownloadState {
notify: Notify,
result: Mutex<Option<Result<Arc<DownloadData>, (StatusCode, String)>>>,
}
#[derive(Debug)] #[derive(Debug)]
struct DownloadData { struct DownloadData {
@@ -30,38 +21,10 @@ struct DownloadData {
impl Downloader { impl Downloader {
fn new() -> Self { fn new() -> Self {
Self { Self {}
states: Arc::new(Mutex::new(HashMap::new())),
}
} }
async fn download(&self, target_url: &str) -> Result<Arc<DownloadData>, (StatusCode, String)> { async fn download(&self, target_url: &str) -> Result<Arc<DownloadData>, (StatusCode, String)> {
// check if the url is already downloading
{
let states = self.states.lock().await;
if let Some(state) = states.get(target_url) {
// wait for notify
state.notify.notified().await;
let result = state.result.lock().await;
match &*result {
Some(Ok(result)) => {
return Ok(result.clone());
}
Some(Err(e)) => return Err(e.clone()),
None => {}
}
}
}
// create a new download state for this url
let mut states = self.states.lock().await;
let state = Arc::new(DownloadState {
notify: Notify::new(),
result: Mutex::new(None),
});
states.insert(target_url.to_string(), state.clone());
drop(states);
let response = reqwest::get(target_url) let response = reqwest::get(target_url)
.await .await
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?; .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
@@ -84,14 +47,6 @@ impl Downloader {
let download_data = Arc::new(DownloadData { body, headers }); let download_data = Arc::new(DownloadData { body, headers });
// notify all waiters
{
let mut states = self.states.lock().await;
let state = states.remove(target_url).unwrap();
state.result.lock().await.replace(Ok(download_data.clone()));
state.notify.notify_waiters();
}
Ok(download_data.into()) Ok(download_data.into())
} }
} }