Merge pull request #180 from teloxide/payload_timeout_hint

Add a way for long-running requests to increase network timeout
This commit is contained in:
Waffle Maybe 2022-02-17 06:11:01 +03:00 committed by GitHub
commit 6113bce6e5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 54 additions and 4 deletions

View file

@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## unreleased
### Added
- `Payload::timeout_hint` method to properly handle long running requests like `GetUpdates` ([#180][pr180])
[pr180]: https://github.com/teloxide/teloxide-core/pull/180
## 0.4.1 - 2022-02-13
### Fixed

View file

@ -214,6 +214,7 @@ impl Bot {
let token = Arc::clone(&self.token);
let api_url = Arc::clone(&self.api_url);
let timeout_hint = payload.timeout_hint();
let params = serde_json::to_vec(payload)
// this `expect` should be ok since we don't write request those may trigger error here
.expect("serialization of request to be infallible");
@ -226,6 +227,7 @@ impl Bot {
reqwest::Url::clone(&*api_url),
P::NAME,
params,
timeout_hint,
)
.await
}
@ -243,6 +245,7 @@ impl Bot {
let token = Arc::clone(&self.token);
let api_url = Arc::clone(&self.api_url);
let timeout_hint = payload.timeout_hint();
let params = serde_multipart::to_form(payload);
// async move to capture client&token&api_url&params
@ -254,6 +257,7 @@ impl Bot {
reqwest::Url::clone(&*api_url),
P::NAME,
params,
timeout_hint,
)
.await
}
@ -271,6 +275,7 @@ impl Bot {
let token = Arc::clone(&self.token);
let api_url = self.api_url.clone();
let timeout_hint = payload.timeout_hint();
let params = serde_multipart::to_form_ref(payload);
// async move to capture client&token&api_url&params
@ -282,6 +287,7 @@ impl Bot {
reqwest::Url::clone(&*api_url),
P::NAME,
params,
timeout_hint,
)
.await
}

View file

@ -99,6 +99,9 @@ macro_rules! impl_payload {
$(
@[multipart = $($multipart_attr:ident),*]
)?
$(
@[timeout_secs = $timeout_secs:ident]
)?
$(
#[ $($method_meta:tt)* ]
)*
@ -179,6 +182,12 @@ macro_rules! impl_payload {
type Output = $Ret;
const NAME: &'static str = stringify!($Method);
$(
fn timeout_hint(&self) -> Option<std::time::Duration> {
self.$timeout_secs.map(<_>::into).map(std::time::Duration::from_secs)
}
)?
}
calculated_doc! {

View file

@ -16,6 +16,7 @@ pub async fn request_multipart<T>(
api_url: reqwest::Url,
method_name: &str,
params: reqwest::multipart::Form,
timeout_hint: Option<Duration>,
) -> ResponseResult<T>
where
T: DeserializeOwned,
@ -33,10 +34,18 @@ where
// [#460]: https://github.com/teloxide/teloxide/issues/460
let method_name = method_name.trim_end_matches("Inline");
let response = client
let mut request = client
.post(crate::net::method_url(api_url, token, method_name))
.multipart(params)
.send()
.build()
.map_err(RequestError::Network)?;
if let Some(timeout) = timeout_hint {
*request.timeout_mut().get_or_insert(Duration::ZERO) += timeout;
}
let response = client
.execute(request)
.await
.map_err(RequestError::Network)?;
@ -49,6 +58,7 @@ pub async fn request_json<T>(
api_url: reqwest::Url,
method_name: &str,
params: Vec<u8>,
timeout_hint: Option<Duration>,
) -> ResponseResult<T>
where
T: DeserializeOwned,
@ -66,11 +76,19 @@ where
// [#460]: https://github.com/teloxide/teloxide/issues/460
let method_name = method_name.trim_end_matches("Inline");
let response = client
let mut request = client
.post(crate::net::method_url(api_url, token, method_name))
.header(CONTENT_TYPE, HeaderValue::from_static("application/json"))
.body(params)
.send()
.build()
.map_err(RequestError::Network)?;
if let Some(timeout) = timeout_hint {
*request.timeout_mut().get_or_insert(Duration::ZERO) += timeout;
}
let response = client
.execute(request)
.await
.map_err(RequestError::Network)?;

View file

@ -11,6 +11,7 @@ use serde::Serialize;
use crate::types::{AllowedUpdate, Update};
impl_payload! {
@[timeout_secs = timeout]
/// Use this method to receive incoming updates using long polling ([wiki]). An Array of [`Update`] objects is returned.
///
/// [wiki]: https://en.wikipedia.org/wiki/Push_technology#Long_polling

View file

@ -1,3 +1,5 @@
use std::time::Duration;
/// Payload of a request.
///
/// Simply speaking, structures implementing this trait represent arguments of
@ -21,4 +23,12 @@ pub trait Payload {
/// It is case insensitive, though must not include underscores. (e.g.
/// `GetMe`, `GETME`, `getme`, `getMe` are ok, but `get_me` is not ok).
const NAME: &'static str;
/// If this payload may take long time to execute (e.g. [`GetUpdates`] with
/// big `timeout`), the **minimum** timeout that should be used.
///
/// [`GetUpdates`]: crate::payloads::GetUpdates
fn timeout_hint(&self) -> Option<Duration> {
None
}
}