trading_ig/repeat_dealing/
api.rs1use http::Method;
4use serde::Deserialize;
5use tracing::{instrument, warn};
6
7use crate::Result;
8use crate::client::IgClient;
9use crate::models::Epic;
10
11use super::models::RepeatDealingWindow;
12
13#[derive(Debug)]
17pub struct RepeatDealingApi<'a> {
18 pub(crate) client: &'a IgClient,
19}
20
21#[derive(Deserialize)]
22#[serde(rename_all = "camelCase")]
23struct WindowEnvelope {
24 repeat_dealing_windows: Vec<RepeatDealingWindow>,
25}
26
27const MAX_ATTEMPTS: u8 = 5;
29const RETRY_DELAY: std::time::Duration = std::time::Duration::from_secs(1);
31
32impl RepeatDealingApi<'_> {
33 #[instrument(skip(self))]
38 pub async fn window(&self) -> Result<Vec<RepeatDealingWindow>> {
39 self.fetch_with_retry("repeat-dealing-window").await
40 }
41
42 #[instrument(skip(self), fields(epic = %epic))]
47 pub async fn window_for(&self, epic: &Epic) -> Result<Vec<RepeatDealingWindow>> {
48 let path = format!("repeat-dealing-window?epic={epic}");
49 self.fetch_with_retry(&path).await
50 }
51
52 async fn fetch_with_retry(&self, path: &str) -> Result<Vec<RepeatDealingWindow>> {
54 let mut last_err = None;
55 for attempt in 1..=MAX_ATTEMPTS {
56 match self
57 .client
58 .transport
59 .request::<(), WindowEnvelope>(
60 Method::GET,
61 path,
62 Some(1),
63 None::<&()>,
64 &self.client.session,
65 )
66 .await
67 {
68 Ok(envelope) => return Ok(envelope.repeat_dealing_windows),
69 Err(e) => {
70 warn!(attempt, "repeat-dealing-window request failed, will retry");
71 last_err = Some(e);
72 if attempt < MAX_ATTEMPTS {
73 tokio::time::sleep(RETRY_DELAY).await;
74 }
75 }
76 }
77 }
78 Err(last_err.expect("loop always runs at least once"))
79 }
80}