use http::Method;
use serde::Deserialize;
use tracing::{instrument, warn};
use crate::Result;
use crate::client::IgClient;
use crate::models::Epic;
use super::models::RepeatDealingWindow;
#[derive(Debug)]
pub struct RepeatDealingApi<'a> {
pub(crate) client: &'a IgClient,
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct WindowEnvelope {
repeat_dealing_windows: Vec<RepeatDealingWindow>,
}
const MAX_ATTEMPTS: u8 = 5;
const RETRY_DELAY: std::time::Duration = std::time::Duration::from_secs(1);
impl RepeatDealingApi<'_> {
#[instrument(skip(self))]
pub async fn window(&self) -> Result<Vec<RepeatDealingWindow>> {
self.fetch_with_retry("repeat-dealing-window").await
}
#[instrument(skip(self), fields(epic = %epic))]
pub async fn window_for(&self, epic: &Epic) -> Result<Vec<RepeatDealingWindow>> {
let path = format!("repeat-dealing-window?epic={epic}");
self.fetch_with_retry(&path).await
}
async fn fetch_with_retry(&self, path: &str) -> Result<Vec<RepeatDealingWindow>> {
let mut last_err = None;
for attempt in 1..=MAX_ATTEMPTS {
match self
.client
.transport
.request::<(), WindowEnvelope>(
Method::GET,
path,
Some(1),
None::<&()>,
&self.client.session,
)
.await
{
Ok(envelope) => return Ok(envelope.repeat_dealing_windows),
Err(e) => {
warn!(attempt, "repeat-dealing-window request failed, will retry");
last_err = Some(e);
if attempt < MAX_ATTEMPTS {
tokio::time::sleep(RETRY_DELAY).await;
}
}
}
}
Err(last_err.expect("loop always runs at least once"))
}
}