billecta 1.14.0

Generated Billecta API
Documentation
use std::time;

use leaky_bucket::RateLimiter;

use crate::{Client, Error, InvoiceAction, Result, Search, SearchResult};

pub struct RateLimitedClient {
    pub c: Client,
    search_rl: RateLimiter,
    get_invoice_rl: RateLimiter,
}

// 600 per minute and 100 per 10 seconds are allowed.

impl RateLimitedClient {
    pub fn new(c: Client) -> Self {
        // Docs:

        // POST /v1/search/actions - 100 per minute and 30 per 10 seconds are allowed.
        // 100 per minute = 100/60 = 1.6 => 1 per second should never trigger rate limit.

        // GET /v1/invoice/action/{id} - 600 per minute and 100 per 10 seconds are allowed.
        // 58 per second should keep us within limits.

        let search_rl = RateLimiter::builder()
            .initial(1)
            .max(1)
            .refill(1)
            .interval(tokio::time::Duration::from_millis(1100)) // 100 extra millis for grace
            .build();

        let get_invoice_rl = RateLimiter::builder()
            .initial(10)
            .max(10)
            .refill(10)
            .interval(tokio::time::Duration::from_millis(1100)) // 100 extra millis for grace
            .build();

        Self {
            c,
            search_rl,
            get_invoice_rl,
        }
    }

    pub async fn search(&self, search_args: &Search) -> Result<SearchResult> {
        loop {
            self.search_rl.acquire(1).await;
            match crate::search::search_for_actions(search_args)
                .send(&self.c)
                .await
            {
                Ok(res) => return Ok(res),
                Err(Error::RateLimited) => {
                    println!("Rate limited, sleeping for 1 second");
                    tokio::time::sleep(time::Duration::from_secs(1)).await;
                }

                Err(err) => return Err(err),
            };
        }
    }

    pub async fn get_invoice(&self, id: &str) -> Result<InvoiceAction> {
        loop {
            self.get_invoice_rl.acquire(1).await;
            match crate::invoice::get_an_invoice(id).send(&self.c).await {
                Ok(res) => return Ok(res),
                Err(Error::RateLimited) => {
                    println!("Rate limited, sleeping for 1 second");
                    tokio::time::sleep(time::Duration::from_secs(1)).await;
                }

                Err(err) => return Err(err),
            };
        }
    }
}