use crate::http::error::BybitHttpError;
pub(crate) fn should_retry_http(error: &BybitHttpError) -> bool {
match error {
BybitHttpError::NetworkError(_) => true,
BybitHttpError::UnexpectedStatus { status, .. } => {
is_retryable_status(*status) || *status >= 600
}
BybitHttpError::BybitError { error_code, .. } => *error_code == 10006,
BybitHttpError::MissingCredentials
| BybitHttpError::JsonError(_)
| BybitHttpError::ValidationError(_)
| BybitHttpError::BuildError(_)
| BybitHttpError::Canceled(_) => false,
}
}
const fn is_retryable_status(status: u16) -> bool {
matches!(status, 429 | 500..=599)
}
#[cfg(test)]
mod tests {
use rstest::rstest;
use super::*;
#[rstest]
#[case(408, false)]
#[case(425, false)]
#[case(429, true)]
#[case(500, true)]
#[case(599, true)]
#[case(600, true)]
#[case(404, false)]
fn http_status_classification(#[case] status: u16, #[case] expected: bool) {
let error = BybitHttpError::UnexpectedStatus {
status,
body: String::new(),
};
assert_eq!(should_retry_http(&error), expected);
}
#[rstest]
#[case(10006, true)]
#[case(10001, false)]
fn http_error_code_classification(#[case] error_code: i32, #[case] expected: bool) {
let error = BybitHttpError::BybitError {
error_code,
message: String::new(),
};
assert_eq!(should_retry_http(&error), expected);
}
#[rstest]
#[case(BybitHttpError::NetworkError(String::new()), true)]
#[case(BybitHttpError::MissingCredentials, false)]
#[case(BybitHttpError::Canceled(String::new()), false)]
fn http_error_classification(#[case] error: BybitHttpError, #[case] expected: bool) {
assert_eq!(should_retry_http(&error), expected);
}
}