fix: add concurrency semaphore for image processing
Limit concurrent image processing tasks to 4 via a tokio::Semaphore on AppState. Acquired before spawn_blocking in both upload_image() and save_deferred_image() to prevent CPU/memory exhaustion from concurrent image uploads.
This commit is contained in:
parent
3675a2cdc6
commit
dfd9814fa5
2 changed files with 17 additions and 0 deletions
|
|
@ -105,6 +105,12 @@ pub(crate) async fn upload_image(
|
|||
|
||||
let (upload, _source) = payload.into_parts();
|
||||
|
||||
let _permit = state
|
||||
.image_semaphore
|
||||
.acquire()
|
||||
.await
|
||||
.map_err(|_| AppError::unexpected("image processing unavailable"))?;
|
||||
|
||||
let image_data = upload.image;
|
||||
let processed = tokio::task::spawn_blocking(move || process_data_url(&image_data))
|
||||
.await
|
||||
|
|
@ -235,6 +241,15 @@ pub(crate) async fn save_deferred_image(
|
|||
let Some(data_url) = data_url.filter(|s| !s.is_empty()) else {
|
||||
return;
|
||||
};
|
||||
let Ok(_permit) = state.image_semaphore.acquire().await else {
|
||||
tracing::warn!(
|
||||
entity_type,
|
||||
entity_id,
|
||||
"image semaphore closed, skipping deferred image"
|
||||
);
|
||||
return;
|
||||
};
|
||||
|
||||
let data_url = data_url.to_string();
|
||||
let processed = match tokio::task::spawn_blocking(move || process_data_url(&data_url)).await {
|
||||
Ok(Ok(p)) => p,
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ pub struct AppState {
|
|||
pub cup_service: CupService,
|
||||
pub insecure_cookies: bool,
|
||||
pub stats_invalidator: StatsInvalidator,
|
||||
pub image_semaphore: Arc<tokio::sync::Semaphore>,
|
||||
}
|
||||
|
||||
impl AppState {
|
||||
|
|
@ -172,6 +173,7 @@ impl AppState {
|
|||
cup_service,
|
||||
insecure_cookies: config.insecure_cookies,
|
||||
stats_invalidator: config.stats_invalidator,
|
||||
image_semaphore: Arc::new(tokio::sync::Semaphore::new(4)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue