Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

operation timed out when uploading a large video file #529

Open
lorenzo9uerra opened this issue Feb 23, 2022 · 3 comments
Open

operation timed out when uploading a large video file #529

lorenzo9uerra opened this issue Feb 23, 2022 · 3 comments
Labels
A-requester Area: requester trait, bot adaptors C-core crate: teloxide-core K-bug Kind: bug S-blocked Status: this is blocked on something

Comments

@lorenzo9uerra
Copy link

While I'm uploading a video of at least 50MB (I guess this depends on the speed of your connection, to reproduce the issue it has to take more than 17 seconds) the program stops after exactly 17 seconds from the start.

I tried this code:

use teloxide::prelude2::*;
use teloxide::types::InputFile;
use std::env;
use serde::{Deserialize, Serialize};
use serde_yaml::{self};

use std::{error::Error as StdError, fmt};

#[derive(Debug)]
pub enum Error {
    /// Some unspecified error.
    Any(Box<dyn StdError + Send + Sync + 'static>),
    TokioError {
        description: String,
    },
    UnknownError,
    UnreadableMessage,
    FileNotFound {
        path: String,
    },
    RequestError {
        description: String,
    },
    ParsingError {
        description: String,
    },
    MissingChatId,
    NoInput,
}

impl Error {
    /// Prints error to stderr and exits the program.
    pub fn exit(self) {
        eprintln!("{}", self);
        std::process::exit(1);
    }
}

impl<'a> fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Error::RequestError { ref description } | Error::TokioError { ref description } => {
                write!(f, "\nMessage failed to send due to:\n\t{}", description)
            }
            Error::FileNotFound { ref path } => {
                write!(f, "\nCould not find file in path:\n\t{}", path)
            }
            Error::MissingChatId => {
                write!(f, "\nChat ID not found in flags or TEPE_TELEGRAM_CHAT_ID")
            }
            Error::NoInput => write!(f, "\nNo input was given"),
            Error::ParsingError { ref description } => {
                write!(f, "\nError from parsing:\n\t{}", description)
            }
            Error::UnreadableMessage => write!(f, "\nIssue parsing message"),
            _ => write!(f, "\nTODO: add error description"),
        }
    }
}

use teloxide::RequestError;
impl From<RequestError> for Error {
    fn from(error: RequestError) -> Self {
        Error::RequestError {
            description: format!("{}", error),
        }
    }
}

use tokio::io::Error as TokioError;
impl From<TokioError> for Error {
    fn from(error: TokioError) -> Self {
        Error::TokioError {
            description: format!("{}", error),
        }
    }
}

impl From<std::num::ParseIntError> for Error {
    fn from(error: std::num::ParseIntError) -> Self {
        Error::ParsingError {
            description: error.to_string(),
        }
    }
}

pub trait CliExit<T> {
    fn cli_expect(self, message: &str) -> T;
}

impl<T, E> CliExit<T> for Result<T, E> {
    fn cli_expect(self, message: &str) -> T {
        match self {
            Ok(t) => t,
            Err(_e) => {
                eprintln!("{}", message);
                std::process::exit(1);
            }
        }
    }
}

impl<T> CliExit<T> for Option<T> {
    fn cli_expect(self, message: &str) -> T {
        match self {
            Some(t) => t,
            None => {
                eprintln!("{}", message);
                std::process::exit(1);
            }
        }
    }
}

#[derive(Debug, Serialize, Deserialize)]
struct Config {
    token: String,
    chat_id: i64,
}

#[tokio::main]
async fn main() {
    run().await.unwrap_or_else(|error| error.exit());
}

async fn run() -> Result<(), Error> {
    let f = std::fs::File::open("tgconfig.yml").expect("Could not open file.");
    let scrape_config: Config = serde_yaml::from_reader(f).expect("Could not read values.");
    teloxide::enable_logging!();
    log::info!("Starting regs_bot...");
    let args: Vec<String> = env::args().collect();

    let bot = Bot::new(scrape_config.token);
    if args.len() != 3 {
        println!("Insert file path and caption");
    }
    else {
        bot.send_video(scrape_config.chat_id, InputFile::file(&args[1])).caption(&args[2]).send().await?;
    }
    Ok(())
}

I expected to see the video uploaded to the chat_id specified.

Instead, the upload stopped after exactly 17 seconds with the message "operation timed out".
I tried to downgrade teloxide-core to 0.4.1 but it didn't make any difference. I also tried to downgrade teloxide version to 0.6.0, no difference.

Dependencies

  • teloxide = { version = "0.7.0", features = ["macros", "auto-send"] }
  • log = "0.4"
  • pretty_env_logger = "0.4.0"
  • tokio = { version = "1.8", features = ["rt-multi-thread", "macros"] }
  • serde = { version = "1.0", features = ["derive"] }
  • serde_yaml = "0.8"
@lorenzo9uerra lorenzo9uerra added the K-bug Kind: bug label Feb 23, 2022
@WaffleLapkin WaffleLapkin added the C-core crate: teloxide-core label Feb 23, 2022
@WaffleLapkin WaffleLapkin self-assigned this Feb 23, 2022
@WaffleLapkin WaffleLapkin added the S-blocked Status: this is blocked on something label Feb 23, 2022
@WaffleLapkin
Copy link
Contributor

WaffleLapkin commented Feb 23, 2022

The problem is that teloxide uses 17 second network timeout by default and iirc we did this since 0.1.

You can workaround this issue by increasing the timeout:

let client = net::default_reqwest_settings().timeout(Duration::from_secs(30));
let bot = Bot::with_client(scrape_config.token, client);

Some ideas how we may fix this in the future:

  • Requests that send files may increase their timeout based on some heuristic based on their size (though I'm not sure if we can always get the size of a file and I'm even less sure how to properly choose the function)
  • We can add functions to Request trait, that would allow to changing timeout on by-request basis

Both of these are blocked on the same thing as #526 (see #526 (comment)).

@hirrolot
Copy link
Collaborator

@WaffleLapkin, is this fixed?

@WaffleLapkin
Copy link
Contributor

@hirrolot no, this is still blocked on seanmonstar/reqwest#1477

@WaffleLapkin WaffleLapkin added the A-requester Area: requester trait, bot adaptors label Jan 21, 2024
@WaffleLapkin WaffleLapkin removed their assignment Aug 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-requester Area: requester trait, bot adaptors C-core crate: teloxide-core K-bug Kind: bug S-blocked Status: this is blocked on something
Projects
None yet
Development

No branches or pull requests

3 participants