mirror of
https://github.com/OMGeeky/exponential_backoff.git
synced 2025-12-26 16:07:57 +01:00
backup
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
/target
|
||||
/Cargo.lock
|
||||
8
.idea/.gitignore
generated
vendored
Normal file
8
.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
11
.idea/exponential_backoff.iml
generated
Normal file
11
.idea/exponential_backoff.iml
generated
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="CPP_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
6
.idea/misc.xml
generated
Normal file
6
.idea/misc.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="MarkdownSettingsMigration">
|
||||
<option name="stateVersion" value="1" />
|
||||
</component>
|
||||
</project>
|
||||
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/exponential_backoff.iml" filepath="$PROJECT_DIR$/.idea/exponential_backoff.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
15
Cargo.toml
Normal file
15
Cargo.toml
Normal file
@@ -0,0 +1,15 @@
|
||||
[package]
|
||||
name = "exponential_backoff"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
tokio = "1.24.2"
|
||||
reqwest = "0.11.14"
|
||||
chrono = "0.4.23"
|
||||
google-youtube3 = "4.0"
|
||||
mime = "0.2.6"
|
||||
serde_json = "1.0.91"
|
||||
rand = "0.8.5"
|
||||
9
src/bigquery.rs
Normal file
9
src/bigquery.rs
Normal file
@@ -0,0 +1,9 @@
|
||||
|
||||
use std::error::Error;
|
||||
|
||||
|
||||
// pub async fn check_backoff_bigquery<T>(res: Result<T, Box<dyn Error>> )->Result<T, Box<dyn Error>>{
|
||||
//
|
||||
//
|
||||
// Ok(res)
|
||||
// }
|
||||
28
src/lib.rs
Normal file
28
src/lib.rs
Normal file
@@ -0,0 +1,28 @@
|
||||
#![feature(async_closure)]
|
||||
use rand::Rng;
|
||||
|
||||
const EXTRA_BUFFER_TIME: u64 = 100;
|
||||
|
||||
pub enum Api {
|
||||
Youtube,
|
||||
Twitch,
|
||||
Bigquery,
|
||||
}
|
||||
|
||||
pub mod errors;
|
||||
pub mod youtube;
|
||||
pub mod twitch;
|
||||
pub mod bigquery;
|
||||
|
||||
|
||||
async fn sleep_for_backoff_time(backoff_time: u64, with_extra_buffer_time: bool) {
|
||||
let extra_buffer_time = match with_extra_buffer_time {
|
||||
true => EXTRA_BUFFER_TIME,
|
||||
false => 0
|
||||
};
|
||||
let backoff_time = backoff_time * 1000 as u64;
|
||||
|
||||
// let random_extra = rand::thread_rng().gen_range(0..100);
|
||||
let random_extra = rand::thread_rng().gen_range(0..100);
|
||||
tokio::time::sleep(std::time::Duration::from_millis(backoff_time + extra_buffer_time + random_extra)).await;
|
||||
}
|
||||
104
src/twitch.rs
Normal file
104
src/twitch.rs
Normal file
@@ -0,0 +1,104 @@
|
||||
use std::error::Error;
|
||||
|
||||
use chrono::NaiveDateTime;
|
||||
use reqwest::{Body, Client, IntoUrl, Request, RequestBuilder, Response};
|
||||
use reqwest::header::{HeaderMap, HeaderValue};
|
||||
|
||||
use crate::errors::BackoffError;
|
||||
use crate::sleep_for_backoff_time;
|
||||
|
||||
enum ErrorTypes {
|
||||
E429(String),
|
||||
|
||||
}
|
||||
//region reqwest
|
||||
//region convenience functions
|
||||
|
||||
//region GET
|
||||
|
||||
pub async fn check_backoff_twitch_get<T: IntoUrl>(url: T) -> Result<Response, Box<dyn Error>> {
|
||||
check_backoff_twitch(Request::new(reqwest::Method::GET, url.into_url()?)).await
|
||||
}
|
||||
|
||||
pub async fn check_backoff_twitch_get_with_client<T: IntoUrl>(url: T, client: &Client) -> Result<Response, Box<dyn Error>> {
|
||||
check_backoff_twitch_with_client(Request::new(reqwest::Method::GET, url.into_url()?), client).await
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
//region POST
|
||||
|
||||
pub async fn check_backoff_twitch_post<T: IntoUrl, B: Into<Body>>(url: T, headers: Option<HeaderMap>, body: Option<B>) -> Result<Response, Box<dyn Error>> {
|
||||
let client = Client::new();
|
||||
check_backoff_twitch_post_with_client(url, headers, body, &client).await
|
||||
}
|
||||
|
||||
pub async fn check_backoff_twitch_post_with_client<T: IntoUrl, B: Into<Body>>(
|
||||
url: T,
|
||||
headers: Option<HeaderMap>,
|
||||
body: Option<B>,
|
||||
client: &Client
|
||||
) -> Result<Response, Box<dyn Error>> {
|
||||
let mut request = client.post(url.into_url()?);
|
||||
|
||||
if let Some(headers) = headers {
|
||||
request = request.headers(headers);
|
||||
}
|
||||
if let Some(body) = body {
|
||||
request = request.body(body);
|
||||
}
|
||||
|
||||
let request = request.build()?;
|
||||
check_backoff_twitch_with_client(request, client).await
|
||||
}
|
||||
//endregion
|
||||
|
||||
pub async fn check_backoff_twitch(request: Request) -> Result<Response, Box<dyn Error>> {
|
||||
let client = Client::new();
|
||||
check_backoff_twitch_with_client(request, &client).await
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
pub async fn check_backoff_twitch_with_client(request: Request, client: &Client) -> Result<Response, Box<dyn Error>> {
|
||||
loop {
|
||||
let r: Request = request.try_clone().ok_or::<BackoffError>("Request is None".into())?;
|
||||
// Some(v) => Ok(v),
|
||||
// None => Err("Request is None".into()),
|
||||
// }?;
|
||||
let response = client.execute(r).await?;
|
||||
|
||||
let status_code = response.status();
|
||||
match status_code.as_u16() {
|
||||
200 => return Ok(response),
|
||||
429 => {
|
||||
let x = &request.headers().get("Ratelimit-Reset").ok_or(BackoffError::new("No rate limit reset given"))?;
|
||||
let value: String = x.to_str()?.to_string();
|
||||
handle_e429(value).await?;
|
||||
},
|
||||
|
||||
_ => return Ok(response),
|
||||
// _ => todo!("Handle other errors or "),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_e429(value: String) -> Result<(), Box<dyn Error>> {
|
||||
let value = value.parse::<i64>()?;
|
||||
let timestamp = NaiveDateTime::from_timestamp_opt(value, 0)
|
||||
.ok_or(BackoffError::new(format!("Could not convert the provided timestamp: {}", value)))?;
|
||||
let now = chrono::Local::now().naive_local();
|
||||
if timestamp < now {
|
||||
sleep_for_backoff_time(1000, true).await;
|
||||
return Ok(());
|
||||
}
|
||||
let duration = timestamp - now;
|
||||
let duration = duration.num_milliseconds() as u64;
|
||||
println!("Sleeping for {} seconds", duration);
|
||||
sleep_for_backoff_time(duration, true).await;
|
||||
// tokio::time::sleep(tokio::time::Duration::from_secs(duration)).await;
|
||||
//TODO: test this somehow
|
||||
Ok(())
|
||||
}
|
||||
|
||||
//endregion
|
||||
Reference in New Issue
Block a user