|
|
|
@ -1,9 +1,10 @@ |
|
|
|
|
use std::collections::HashSet; |
|
|
|
|
|
|
|
|
|
use axum::{extract::State, response::IntoResponse, Json}; |
|
|
|
|
use tokio::select; |
|
|
|
|
|
|
|
|
|
use crate::{ |
|
|
|
|
error::AppResult, |
|
|
|
|
error::{AppError, AppResult}, |
|
|
|
|
models::{AppStateShared, UrlReportResponse, UrlRequest, UrlResult}, |
|
|
|
|
repo::Repo, |
|
|
|
|
}; |
|
|
|
@ -62,16 +63,24 @@ pub async fn upload_urls<R: Repo>( |
|
|
|
|
tokio::spawn(async move { |
|
|
|
|
let r_state = state.read().await; |
|
|
|
|
let _sem = r_state.url_handling_semaphore.acquire().await.unwrap(); |
|
|
|
|
let ct = r_state.cancellation_token.clone(); |
|
|
|
|
info!("fetching {url}"); |
|
|
|
|
|
|
|
|
|
let response: AppResult<_> = (|| async { |
|
|
|
|
let request = (|| async { |
|
|
|
|
let resp = reqwest::get(url.to_string()).await?; |
|
|
|
|
let status = resp.status().as_u16(); |
|
|
|
|
let result = resp.text().await?; |
|
|
|
|
|
|
|
|
|
Ok((status, result)) |
|
|
|
|
})() |
|
|
|
|
.await; |
|
|
|
|
})(); |
|
|
|
|
|
|
|
|
|
let response: AppResult<_> = select! { |
|
|
|
|
r = request => r, |
|
|
|
|
_ = ct.cancelled() => { |
|
|
|
|
info!("fetching {url} cancelled"); |
|
|
|
|
Err(AppError::Cancelled(url.to_string())) |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
match response { |
|
|
|
|
Ok((status, resp)) => UrlResult { |
|
|
|
@ -92,8 +101,14 @@ pub async fn upload_urls<R: Repo>( |
|
|
|
|
.collect::<Vec<_>>() |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
let ct = state.read().await.cancellation_token.clone(); |
|
|
|
|
for task in tasks { |
|
|
|
|
let result = task.await.unwrap(); |
|
|
|
|
let result = if let Some(result) = ct.run_until_cancelled(task).await { |
|
|
|
|
result.unwrap() |
|
|
|
|
} else { |
|
|
|
|
continue; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
let status = result.status.unwrap_or(0); |
|
|
|
|
|
|
|
|
|
if status >= 200 && status < 400 { |
|
|
|
@ -102,7 +117,12 @@ pub async fn upload_urls<R: Repo>( |
|
|
|
|
failures.push(result); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
state.write().await.repo.insert_urls(&successes)?; |
|
|
|
|
info!("fetching completed"); |
|
|
|
|
|
|
|
|
|
let mut w_state = state.write().await; |
|
|
|
|
w_state.repo.insert_urls(&successes)?; |
|
|
|
|
w_state.regen_cancellation_token(); |
|
|
|
|
drop(w_state); |
|
|
|
|
|
|
|
|
|
Ok(Json(UrlReportResponse { |
|
|
|
|
successes, |
|
|
|
|