mirror of
https://github.com/teloxide/teloxide.git
synced 2025-03-14 11:44:04 +01:00
Use Duration
instead of u32
as the RetryAfter
field
This commit is contained in:
parent
d259f8aa23
commit
af0dd99ef4
5 changed files with 62 additions and 15 deletions
|
@ -23,7 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- Improve `Throttling` adoptor
|
||||
- Freeze when getting `RetryAfter(_)` error
|
||||
- Retry requests that previously returned `RetryAfter(_)` error
|
||||
- `RequestError::RetryAfter` now has a `u32` field instead of `i32`
|
||||
- `RequestError::RetryAfter` now has a `Duration` field instead of `i32`
|
||||
|
||||
### Added
|
||||
|
||||
|
|
|
@ -1,9 +1,4 @@
|
|||
use std::{
|
||||
future::Future,
|
||||
pin::Pin,
|
||||
sync::Arc,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
use std::{future::Future, pin::Pin, sync::Arc, time::Instant};
|
||||
|
||||
use futures::{
|
||||
future::BoxFuture,
|
||||
|
@ -188,7 +183,7 @@ where
|
|||
|
||||
let retry_after = res.as_ref().err().and_then(<_>::retry_after);
|
||||
if let Some(retry_after) = retry_after {
|
||||
let after = Duration::from_secs(retry_after.into());
|
||||
let after = retry_after;
|
||||
let until = Instant::now() + after;
|
||||
|
||||
// If we'll retry, we check that worker hasn't died at the start of the loop
|
||||
|
@ -196,7 +191,7 @@ where
|
|||
let _ = freeze.send(FreezeUntil { until, after, chat }).await;
|
||||
|
||||
if retry {
|
||||
log::warn!("Freezing, before retrying: {}", retry_after);
|
||||
log::warn!("Freezing, before retrying: {:?}", retry_after);
|
||||
tokio::time::sleep_until(until.into()).await;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::io;
|
||||
use std::{io, time::Duration};
|
||||
|
||||
use serde::Deserialize;
|
||||
use thiserror::Error;
|
||||
|
@ -19,8 +19,8 @@ pub enum RequestError {
|
|||
|
||||
/// In case of exceeding flood control, the number of seconds left to wait
|
||||
/// before the request can be repeated.
|
||||
#[error("Retry after {0} seconds")]
|
||||
RetryAfter(u32),
|
||||
#[error("Retry after {0:?}")]
|
||||
RetryAfter(Duration),
|
||||
|
||||
/// Network error while sending a request to Telegram.
|
||||
#[error("A network error: {0}")]
|
||||
|
@ -62,7 +62,7 @@ pub enum DownloadError {
|
|||
pub trait AsResponseParameters {
|
||||
fn response_parameters(&self) -> Option<ResponseParameters>;
|
||||
|
||||
fn retry_after(&self) -> Option<u32> {
|
||||
fn retry_after(&self) -> Option<Duration> {
|
||||
self.response_parameters().and_then(|rp| match rp {
|
||||
ResponseParameters::RetryAfter(n) => Some(n),
|
||||
_ => None,
|
||||
|
|
50
src/types.rs
50
src/types.rs
|
@ -345,3 +345,53 @@ pub(crate) mod option_url_from_string {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) mod duration_secs {
|
||||
use std::time::Duration;
|
||||
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
pub(crate) fn serialize<S>(this: &Duration, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
// match this {
|
||||
// Some(url) => url.serialize(serializer),
|
||||
// None => "".serialize(serializer),
|
||||
// }
|
||||
this.as_secs().serialize(serializer)
|
||||
}
|
||||
|
||||
pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<Duration, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
u64::deserialize(deserializer).map(Duration::from_secs)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct Struct {
|
||||
#[serde(with = "crate::types::duration_secs")]
|
||||
duration: Duration,
|
||||
}
|
||||
|
||||
{
|
||||
let json = r#"{"duration":0}"#;
|
||||
let duration: Struct = serde_json::from_str(json).unwrap();
|
||||
assert_eq!(duration.duration, Duration::from_secs(0));
|
||||
assert_eq!(serde_json::to_string(&duration).unwrap(), json.to_owned());
|
||||
|
||||
let json = r#"{"duration":12}"#;
|
||||
let duration: Struct = serde_json::from_str(json).unwrap();
|
||||
assert_eq!(duration.duration, Duration::from_secs(12));
|
||||
assert_eq!(serde_json::to_string(&duration).unwrap(), json.to_owned());
|
||||
|
||||
let json = r#"{"duration":1234}"#;
|
||||
let duration: Struct = serde_json::from_str(json).unwrap();
|
||||
assert_eq!(duration.duration, Duration::from_secs(1234));
|
||||
assert_eq!(serde_json::to_string(&duration).unwrap(), json.to_owned());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use std::time::Duration;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Contains information about why a request was unsuccessful.
|
||||
|
@ -16,7 +18,7 @@ pub enum ResponseParameters {
|
|||
|
||||
/// In case of exceeding flood control, the number of seconds left to wait
|
||||
/// before the request can be repeated.
|
||||
RetryAfter(u32),
|
||||
RetryAfter(#[serde(with = "crate::types::duration_secs")] Duration),
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -34,7 +36,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn retry_after_deserialization() {
|
||||
let expected = ResponseParameters::RetryAfter(123_456);
|
||||
let expected = ResponseParameters::RetryAfter(Duration::from_secs(123_456));
|
||||
let actual: ResponseParameters = serde_json::from_str(r#"{"retry_after":123456}"#).unwrap();
|
||||
|
||||
assert_eq!(expected, actual);
|
||||
|
|
Loading…
Add table
Reference in a new issue