From 44cba8abe0b2f65dd3dacb3b60e053aca1da9061 Mon Sep 17 00:00:00 2001 From: YoursFunny Date: Sat, 8 Aug 2026 20:24:38 +0800 Subject: [PATCH] send: reuse one process-wide Bot for queue workers handle_task and dead_letter_notify built a fresh Bot (env parse + HTTP client) per queue item. A single LazyLock is forced at startup so a missing TELOXIDE_TOKEN fails fast instead of on the first task. --- crates/xmedia-bot/src/main.rs | 3 +++ crates/xmedia-bot/src/send.rs | 10 ++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/crates/xmedia-bot/src/main.rs b/crates/xmedia-bot/src/main.rs index 5e67779..f5ef781 100644 --- a/crates/xmedia-bot/src/main.rs +++ b/crates/xmedia-bot/src/main.rs @@ -43,6 +43,9 @@ async fn main() { log::info!("Starting bot"); let bot = Bot::from_env(); + // Force the queue workers' shared Bot to initialize now so a missing + // token fails at startup, not on the first queued task. + let _ = &*send::BOT; // Register the command list with Telegram (client `/` menu). if let Err(e) = handlers::register_commands(&bot).await { diff --git a/crates/xmedia-bot/src/send.rs b/crates/xmedia-bot/src/send.rs index d41daad..21c7b6a 100644 --- a/crates/xmedia-bot/src/send.rs +++ b/crates/xmedia-bot/src/send.rs @@ -11,6 +11,7 @@ use crate::state::{EditMessage, unix_now}; use rand::Rng; use serde::{Deserialize, Serialize}; use std::collections::HashMap; +use std::sync::LazyLock; use teloxide::prelude::*; use teloxide::types::{ ChatId, InlineKeyboardButton, InlineKeyboardMarkup, InputFile, InputMedia, InputMediaAnimation, @@ -20,6 +21,11 @@ use teloxide::{ApiError, RequestError}; use tempfile::NamedTempFile; use x_media::site::FetchError; +/// One process-wide Bot for queue workers. Building a fresh Bot (and its HTTP +/// client) per queue task was pure waste; forced at startup in main so a +/// missing token fails fast instead of on the first task. +pub static BOT: LazyLock = LazyLock::new(Bot::from_env); + #[derive(Serialize, Deserialize, Clone, Debug)] #[serde(tag = "kind", rename_all = "snake_case")] pub enum MediaItemPayload { @@ -1158,7 +1164,7 @@ pub async fn handle_task(payload: serde_json::Value) -> Result<(), QueueError> { }); } }; - let bot = Bot::from_env(); + let bot = BOT.clone(); // A resumed multi-batch send already ran post_send_actions (edit prompt / // forward) when it first started; running them again on the resume would // open a duplicate edit prompt and double-forward. SendAnimation is @@ -1227,7 +1233,7 @@ pub async fn dead_letter_notify(payload: serde_json::Value, message: String) { let notify_chat_id = payload.get("notify_chat_id").and_then(|v| v.as_i64()); let notify_message_id = payload.get("notify_message_id").and_then(|v| v.as_i64()); if notify_chat_id.is_some() { - let bot = Bot::from_env(); + let bot = BOT.clone(); notify_failure( &bot, notify_chat_id,