remove download states map
This commit is contained in:
51
src/main.rs
51
src/main.rs
@@ -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())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user