diff --git a/crates/xmedia-bot/src/handlers/callback.rs b/crates/xmedia-bot/src/handlers/callback.rs index 0bbda7c..b5b80d9 100644 --- a/crates/xmedia-bot/src/handlers/callback.rs +++ b/crates/xmedia-bot/src/handlers/callback.rs @@ -83,7 +83,7 @@ pub async fn callback_query_handler(bot: Bot, query: CallbackQuery) -> Result<() task, }) => { log::info!("forward queued for retry in {delay_seconds:.1}s"); - enqueue_retry(&TASK_QUEUE, task, delay_seconds).await; + enqueue_retry(&TASK_QUEUE, *task, delay_seconds).await; bot.answer_callback_query(callback_query_id) .text("Forward queued for retry.") .await?; diff --git a/crates/xmedia-bot/src/handlers/urls.rs b/crates/xmedia-bot/src/handlers/urls.rs index 5a06062..b66603d 100644 --- a/crates/xmedia-bot/src/handlers/urls.rs +++ b/crates/xmedia-bot/src/handlers/urls.rs @@ -211,7 +211,7 @@ async fn dispatch_send( "send for [key={}] failed, queued for retry in {delay_seconds:.1}s", log_key(url) ); - enqueue_retry(ctx.task_queue, task, delay_seconds).await; + enqueue_retry(ctx.task_queue, *task, delay_seconds).await; let _ = reply( ctx.sender, chat_id, diff --git a/crates/xmedia-bot/src/photo.rs b/crates/xmedia-bot/src/photo.rs index e9844c8..b73d72d 100644 --- a/crates/xmedia-bot/src/photo.rs +++ b/crates/xmedia-bot/src/photo.rs @@ -122,7 +122,7 @@ fn output_channels(color: png::ColorType) -> usize { /// white; 16-bit per channel was already stripped to 8-bit at decode. fn flatten_rgba_to_rgb(rgba: &[u8]) -> Vec { let mut rgb = Vec::with_capacity(rgba.len() / 4 * 3); - for px in rgba.chunks_exact(4) { + for px in rgba.as_chunks::<4>().0 { let a = px[3] as u32; for v in &px[..3] { // Over white: C = C*a/255 + 255*(1 - a/255). @@ -178,7 +178,9 @@ fn encode_jpeg(pix: &PixBuf, w: u32, h: u32) -> Result, String> { PixBuf::GrayAlpha(v) => { // JPEG has no alpha: composite onto white, output as gray. let gray: Vec = v - .chunks_exact(2) + .as_chunks::<2>() + .0 + .iter() .map(|px| { let (g, a) = (px[0] as u32, px[1] as u32); ((g * a + 255 * (255 - a)) / 255).min(255) as u8 diff --git a/crates/xmedia-bot/src/send.rs b/crates/xmedia-bot/src/send.rs index 7720bfd..f0d7620 100644 --- a/crates/xmedia-bot/src/send.rs +++ b/crates/xmedia-bot/src/send.rs @@ -386,22 +386,26 @@ pub fn classify_request_error(e: &RequestError) -> Classification { } } +/// Task boxed to keep the error size within `result_large_err` limits. #[derive(Debug)] pub enum SendError { - Retryable { delay_seconds: f64, task: Task }, - Permanent { message: String, task: Task }, + Retryable { delay_seconds: f64, task: Box }, + Permanent { message: String, task: Box }, } fn classify_to_send_error(e: &RequestError, task: Task) -> SendError { match classify_request_error(e) { Classification::Retryable { delay_seconds } => SendError::Retryable { delay_seconds, - task, + task: Box::new(task), + }, + Classification::Permanent { message } => SendError::Permanent { + message, + task: Box::new(task), }, - Classification::Permanent { message } => SendError::Permanent { message, task }, Classification::MediaFetchFailure => SendError::Permanent { message: "media fetch failed".into(), - task, + task: Box::new(task), }, } } @@ -415,9 +419,12 @@ impl SendError { match f { FallbackError::Retryable { delay_seconds } => SendError::Retryable { delay_seconds, - task, + task: Box::new(task), + }, + FallbackError::Permanent { message } => SendError::Permanent { + message, + task: Box::new(task), }, - FallbackError::Permanent { message } => SendError::Permanent { message, task }, FallbackError::MediaTooLarge => unreachable!("handled inside the upload fallback"), } } @@ -847,7 +854,7 @@ async fn send_batch_via_upload( Err(e) => { return Err(SendError::Permanent { message: format!("upload worker panicked: {e}"), - task, + task: Box::new(task), }); } }; @@ -875,12 +882,15 @@ async fn send_batch_via_upload( Err(e) => Err(match classify_request_error(&e) { Classification::Retryable { delay_seconds } => SendError::Retryable { delay_seconds, - task: task.clone(), + task: Box::new(task.clone()), + }, + Classification::Permanent { message } => SendError::Permanent { + message, + task: Box::new(task), }, - Classification::Permanent { message } => SendError::Permanent { message, task }, Classification::MediaFetchFailure => SendError::Permanent { message: "upload failed".into(), - task, + task: Box::new(task), }, }), } @@ -957,7 +967,7 @@ pub async fn send_media_sequence( Err(message) => { return Err(SendError::Permanent { message, - task: updated_sequence_task(task, idx, sent), + task: Box::new(updated_sequence_task(task, idx, sent)), }); } }; @@ -1060,7 +1070,7 @@ pub async fn send_animation(sender: &dyn MediaSender, task: &Task) -> Result { return Err(SendError::Permanent { message, - task: task.clone(), + task: Box::new(task.clone()), }); } };