fix: move image processing off async runtime with spawn_blocking
CPU-intensive image operations (decode, Lanczos3 resize, JPEG encode) were running directly on the async worker thread, blocking all other requests for 100-500ms per upload. Wrap in spawn_blocking in both upload_image() and save_deferred_image().
This commit is contained in:
parent
cf56ac28f7
commit
082b582cb3
1 changed files with 22 additions and 14 deletions
|
|
@ -105,7 +105,10 @@ pub(crate) async fn upload_image(
|
|||
|
||||
let (upload, _source) = payload.into_parts();
|
||||
|
||||
let processed = process_data_url(&upload.image)
|
||||
let image_data = upload.image;
|
||||
let processed = tokio::task::spawn_blocking(move || process_data_url(&image_data))
|
||||
.await
|
||||
.map_err(|e| AppError::unexpected(format!("image processing task failed: {e}")))?
|
||||
.map_err(|e| AppError::validation(format!("invalid image: {e}")))?;
|
||||
|
||||
let image = EntityImage {
|
||||
|
|
@ -232,8 +235,18 @@ pub(crate) async fn save_deferred_image(
|
|||
let Some(data_url) = data_url.filter(|s| !s.is_empty()) else {
|
||||
return;
|
||||
};
|
||||
match process_data_url(data_url) {
|
||||
Ok(processed) => {
|
||||
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,
|
||||
Ok(Err(err)) => {
|
||||
tracing::warn!(entity_type, entity_id, error = %err, "failed to process deferred image");
|
||||
return;
|
||||
}
|
||||
Err(err) => {
|
||||
tracing::warn!(entity_type, entity_id, error = %err, "deferred image task panicked");
|
||||
return;
|
||||
}
|
||||
};
|
||||
let image = EntityImage {
|
||||
entity_type: entity_type.to_string(),
|
||||
entity_id,
|
||||
|
|
@ -244,11 +257,6 @@ pub(crate) async fn save_deferred_image(
|
|||
if let Err(err) = state.image_repo.upsert(image).await {
|
||||
tracing::warn!(entity_type, entity_id, error = %err, "failed to save deferred image");
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
tracing::warn!(entity_type, entity_id, error = %err, "failed to process deferred image");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn image_response(data: Vec<u8>, content_type: &str) -> Response {
|
||||
|
|
|
|||
Loading…
Reference in a new issue