use crate::{
errors::{AntiBotTech, CrawlError},
proxy::{ProxyInfo, ProxyKind},
request::Request,
session::SessionId,
};
use std::time::Duration;
#[derive(Debug, Default, Clone)]
#[non_exhaustive]
pub struct AttemptOverrides {
pub proxy_kind: Option<ProxyKind>,
pub user_agent_profile: Option<String>,
pub backoff: Option<Duration>,
}
#[non_exhaustive]
pub struct AttemptOutcome<'a> {
pub request: &'a Request,
pub attempt: u32,
pub status: Option<http::StatusCode>,
pub error: Option<&'a CrawlError>,
pub anti_bot: Option<AntiBotTech>,
pub proxy_info: Option<&'a ProxyInfo>,
pub session_id: Option<&'a SessionId>,
pub response_bytes: Option<usize>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[non_exhaustive]
pub enum SessionRetryAction {
#[default]
Keep,
Rotate,
Retire,
}
#[derive(Debug, Clone, Default)]
#[non_exhaustive]
pub struct RetryDirective {
pub should_retry: bool,
pub backoff: Option<Duration>,
pub proxy_kind: Option<ProxyKind>,
pub user_agent_profile: Option<String>,
pub session_action: SessionRetryAction,
}
impl RetryDirective {
pub fn retry() -> Self {
Self {
should_retry: true,
..Self::default()
}
}
pub fn stop() -> Self {
Self::default()
}
pub fn backoff(mut self, backoff: Duration) -> Self {
self.backoff = Some(backoff);
self
}
pub fn proxy_kind(mut self, proxy_kind: ProxyKind) -> Self {
self.proxy_kind = Some(proxy_kind);
self
}
pub fn user_agent_profile(mut self, profile: impl Into<String>) -> Self {
self.user_agent_profile = Some(profile.into());
self
}
pub fn session_action(mut self, action: SessionRetryAction) -> Self {
self.session_action = action;
self
}
}
pub trait RetryStrategy: Send + Sync + 'static {
fn max_retries(&self) -> u32;
fn on_retry(&self, outcome: &AttemptOutcome<'_>) -> RetryDirective;
}