Merge pull request #105 from polyphony-chat/refactor/limited-requester

Refactor/limited requester
This commit is contained in:
Flori 2023-06-12 19:02:36 +02:00 committed by GitHub
commit 234c0c4a8d
9 changed files with 72 additions and 127 deletions

View File

@ -15,7 +15,6 @@ impl Instance {
&mut self, &mut self,
login_schema: &LoginSchema, login_schema: &LoginSchema,
) -> Result<UserMeta, ChorusLibError> { ) -> Result<UserMeta, ChorusLibError> {
let mut requester = LimitedRequester::new().await;
let json_schema = json!(login_schema); let json_schema = json!(login_schema);
let client = Client::new(); let client = Client::new();
let endpoint_url = self.urls.get_api().to_string() + "/auth/login"; let endpoint_url = self.urls.get_api().to_string() + "/auth/login";
@ -24,14 +23,13 @@ impl Instance {
// request (since login is an instance wide limit), which is why we are just cloning the // request (since login is an instance wide limit), which is why we are just cloning the
// instances' limits to pass them on as user_rate_limits later. // instances' limits to pass them on as user_rate_limits later.
let mut cloned_limits = self.limits.clone(); let mut cloned_limits = self.limits.clone();
let response = requester let response = LimitedRequester::send_request(
.send_request( request_builder,
request_builder, LimitType::AuthRegister,
LimitType::AuthRegister, &mut self.limits,
&mut self.limits, &mut cloned_limits,
&mut cloned_limits, )
) .await;
.await;
if response.is_err() { if response.is_err() {
return Err(ChorusLibError::NoResponse); return Err(ChorusLibError::NoResponse);
} }

View File

@ -24,7 +24,6 @@ impl Instance {
register_schema: &RegisterSchema, register_schema: &RegisterSchema,
) -> Result<UserMeta, ChorusLibError> { ) -> Result<UserMeta, ChorusLibError> {
let json_schema = json!(register_schema); let json_schema = json!(register_schema);
let mut limited_requester = LimitedRequester::new().await;
let client = Client::new(); let client = Client::new();
let endpoint_url = self.urls.get_api().to_string() + "/auth/register"; let endpoint_url = self.urls.get_api().to_string() + "/auth/register";
let request_builder = client.post(endpoint_url).body(json_schema.to_string()); let request_builder = client.post(endpoint_url).body(json_schema.to_string());
@ -32,14 +31,13 @@ impl Instance {
// request (since register is an instance wide limit), which is why we are just cloning // request (since register is an instance wide limit), which is why we are just cloning
// the instances' limits to pass them on as user_rate_limits later. // the instances' limits to pass them on as user_rate_limits later.
let mut cloned_limits = self.limits.clone(); let mut cloned_limits = self.limits.clone();
let response = limited_requester let response = LimitedRequester::send_request(
.send_request( request_builder,
request_builder, LimitType::AuthRegister,
LimitType::AuthRegister, &mut self.limits,
&mut self.limits, &mut cloned_limits,
&mut cloned_limits, )
) .await;
.await;
if response.is_err() { if response.is_err() {
return Err(ChorusLibError::NoResponse); return Err(ChorusLibError::NoResponse);
} }

View File

@ -5,7 +5,6 @@ use crate::{
api::handle_request, api::handle_request,
errors::ChorusLibError, errors::ChorusLibError,
instance::UserMeta, instance::UserMeta,
limit::LimitedRequester,
types::{self, PermissionOverwrite}, types::{self, PermissionOverwrite},
}; };

View File

@ -13,15 +13,13 @@ pub async fn handle_request(
limit_type: LimitType, limit_type: LimitType,
) -> Result<reqwest::Response, crate::errors::ChorusLibError> { ) -> Result<reqwest::Response, crate::errors::ChorusLibError> {
let mut belongs_to = user.belongs_to.borrow_mut(); let mut belongs_to = user.belongs_to.borrow_mut();
match LimitedRequester::new() match LimitedRequester::send_request(
.await request,
.send_request( limit_type,
request, &mut belongs_to.limits,
limit_type, &mut user.limits,
&mut belongs_to.limits, )
&mut user.limits, .await
)
.await
{ {
Ok(response) => return Ok(response), Ok(response) => return Ok(response),
Err(e) => return Err(e), Err(e) => return Err(e),

View File

@ -180,15 +180,13 @@ impl Guild {
let request = Client::new() let request = Client::new()
.get(format!("{}/guilds/{}/", url_api, guild_id)) .get(format!("{}/guilds/{}/", url_api, guild_id))
.bearer_auth(token); .bearer_auth(token);
let response = match LimitedRequester::new() let response = match LimitedRequester::send_request(
.await request,
.send_request( crate::api::limits::LimitType::Guild,
request, limits_instance,
crate::api::limits::LimitType::Guild, limits_user,
limits_instance, )
limits_user, .await
)
.await
{ {
Ok(response) => response, Ok(response) => response,
Err(e) => return Err(e), Err(e) => return Err(e),
@ -242,15 +240,13 @@ impl Channel {
.post(format!("{}/guilds/{}/channels/", url_api, guild_id)) .post(format!("{}/guilds/{}/channels/", url_api, guild_id))
.bearer_auth(token) .bearer_auth(token)
.body(to_string(&schema).unwrap()); .body(to_string(&schema).unwrap());
let mut requester = LimitedRequester::new().await; let result = match LimitedRequester::send_request(
let result = match requester request,
.send_request( crate::api::limits::LimitType::Guild,
request, limits_instance,
crate::api::limits::LimitType::Guild, limits_user,
limits_instance, )
limits_user, .await
)
.await
{ {
Ok(result) => result, Ok(result) => result,
Err(e) => return Err(e), Err(e) => return Err(e),

View File

@ -1,11 +1,9 @@
use reqwest::Client; use reqwest::Client;
use serde_json::from_str;
use crate::{ use crate::{
api::{deserialize_response, handle_request_as_option}, api::{deserialize_response, handle_request_as_option},
errors::ChorusLibError, errors::ChorusLibError,
instance::UserMeta, instance::UserMeta,
limit::LimitedRequester,
types, types,
}; };

View File

@ -1,11 +1,10 @@
use reqwest::Client; use reqwest::Client;
use serde_json::{from_str, to_string}; use serde_json::to_string;
use crate::{ use crate::{
api::deserialize_response, api::deserialize_response,
errors::ChorusLibError, errors::ChorusLibError,
instance::UserMeta, instance::UserMeta,
limit::LimitedRequester,
types::{self, RoleCreateModifySchema, RoleObject}, types::{self, RoleCreateModifySchema, RoleObject},
}; };

View File

@ -1,5 +1,5 @@
use reqwest::Client; use reqwest::Client;
use serde_json::{from_str, to_string}; use serde_json::to_string;
use crate::{ use crate::{
api::{deserialize_response, handle_request_as_option, limits::Limits}, api::{deserialize_response, handle_request_as_option, limits::Limits},
@ -110,16 +110,14 @@ impl User {
url = format!("{}/users/{}", url_api, id.unwrap()); url = format!("{}/users/{}", url_api, id.unwrap());
} }
let request = reqwest::Client::new().get(url).bearer_auth(token); let request = reqwest::Client::new().get(url).bearer_auth(token);
let mut requester = crate::limit::LimitedRequester::new().await;
let mut cloned_limits = limits_instance.clone(); let mut cloned_limits = limits_instance.clone();
match requester match LimitedRequester::send_request(
.send_request( request,
request, crate::api::limits::LimitType::Ip,
crate::api::limits::LimitType::Ip, limits_instance,
limits_instance, &mut cloned_limits,
&mut cloned_limits, )
) .await
.await
{ {
Ok(result) => { Ok(result) => {
let result_text = result.text().await.unwrap(); let result_text = result.text().await.unwrap();
@ -138,15 +136,13 @@ impl User {
.get(format!("{}/users/@me/settings/", url_api)) .get(format!("{}/users/@me/settings/", url_api))
.bearer_auth(token); .bearer_auth(token);
let mut cloned_limits = instance_limits.clone(); let mut cloned_limits = instance_limits.clone();
let mut requester = crate::limit::LimitedRequester::new().await; match LimitedRequester::send_request(
match requester request,
.send_request( crate::api::limits::LimitType::Ip,
request, instance_limits,
crate::api::limits::LimitType::Ip, &mut cloned_limits,
instance_limits, )
&mut cloned_limits, .await
)
.await
{ {
Ok(result) => Ok(serde_json::from_str(&result.text().await.unwrap()).unwrap()), Ok(result) => Ok(serde_json::from_str(&result.text().await.unwrap()).unwrap()),
Err(e) => Err(e), Err(e) => Err(e),

View File

@ -1,5 +1,3 @@
use std::collections::VecDeque;
use reqwest::{Client, RequestBuilder, Response}; use reqwest::{Client, RequestBuilder, Response};
use crate::{ use crate::{
@ -18,24 +16,9 @@ pub struct TypedRequest {
} }
#[derive(Debug)] #[derive(Debug)]
pub struct LimitedRequester { pub struct LimitedRequester;
http: Client,
requests: VecDeque<TypedRequest>,
}
impl LimitedRequester { impl LimitedRequester {
/// Create a new `LimitedRequester`. `LimitedRequester`s use a `VecDeque` to store requests and
/// send them to the server using a `Client`. It keeps track of the remaining requests that can
/// be send within the `Limit` of an external API Ratelimiter, and looks at the returned request
/// headers to see if it can find Ratelimit info to update itself.
#[allow(dead_code)]
pub async fn new() -> Self {
LimitedRequester {
http: Client::new(),
requests: VecDeque::new(),
}
}
/** /**
# send_request # send_request
Checks, if a request can be sent without hitting API rate limits and sends it, if true. Checks, if a request can be sent without hitting API rate limits and sends it, if true.
@ -67,13 +50,12 @@ impl LimitedRequester {
methods' Errors section for more information. methods' Errors section for more information.
*/ */
pub async fn send_request( pub async fn send_request(
&mut self,
request: RequestBuilder, request: RequestBuilder,
limit_type: LimitType, limit_type: LimitType,
instance_rate_limits: &mut Limits, instance_rate_limits: &mut Limits,
user_rate_limits: &mut Limits, user_rate_limits: &mut Limits,
) -> Result<Response, ChorusLibError> { ) -> Result<Response, ChorusLibError> {
if self.can_send_request(limit_type, instance_rate_limits, user_rate_limits) { if LimitedRequester::can_send_request(limit_type, instance_rate_limits, user_rate_limits) {
let built_request = match request.build() { let built_request = match request.build() {
Ok(request) => request, Ok(request) => request,
Err(e) => { Err(e) => {
@ -83,7 +65,7 @@ impl LimitedRequester {
}); });
} }
}; };
let result = self.http.execute(built_request).await; let result = Client::new().execute(built_request).await;
let response = match result { let response = match result {
Ok(is_response) => is_response, Ok(is_response) => is_response,
Err(e) => { Err(e) => {
@ -92,7 +74,7 @@ impl LimitedRequester {
}); });
} }
}; };
self.update_limits( LimitedRequester::update_limits(
&response, &response,
limit_type, limit_type,
instance_rate_limits, instance_rate_limits,
@ -112,10 +94,6 @@ impl LimitedRequester {
Ok(response) Ok(response)
} }
} else { } else {
self.requests.push_back(TypedRequest {
request,
limit_type,
});
Err(ChorusLibError::RateLimited { Err(ChorusLibError::RateLimited {
bucket: limit_type.to_string(), bucket: limit_type.to_string(),
}) })
@ -134,7 +112,6 @@ impl LimitedRequester {
} }
fn can_send_request( fn can_send_request(
&mut self,
limit_type: LimitType, limit_type: LimitType,
instance_rate_limits: &Limits, instance_rate_limits: &Limits,
user_rate_limits: &Limits, user_rate_limits: &Limits,
@ -185,7 +162,6 @@ impl LimitedRequester {
} }
fn update_limits( fn update_limits(
&mut self,
response: &Response, response: &Response,
limit_type: LimitType, limit_type: LimitType,
instance_rate_limits: &mut Limits, instance_rate_limits: &mut Limits,
@ -286,16 +262,6 @@ mod rate_limit {
use super::*; use super::*;
#[tokio::test]
async fn create_limited_requester() {
let _urls = URLBundle::new(
String::from("http://localhost:3001/api/"),
String::from("wss://localhost:3001/"),
String::from("http://localhost:3001/cdn"),
);
let _requester = LimitedRequester::new().await;
}
#[tokio::test] #[tokio::test]
async fn run_into_limit() { async fn run_into_limit() {
let urls = URLBundle::new( let urls = URLBundle::new(
@ -303,23 +269,21 @@ mod rate_limit {
String::from("wss://localhost:3001/"), String::from("wss://localhost:3001/"),
String::from("http://localhost:3001/cdn"), String::from("http://localhost:3001/cdn"),
); );
let mut requester = LimitedRequester::new().await;
let mut request: Option<Result<Response, ChorusLibError>> = None; let mut request: Option<Result<Response, ChorusLibError>> = None;
let mut instance_rate_limits = Limits::check_limits(urls.api.clone()).await; let mut instance_rate_limits = Limits::check_limits(urls.api.clone()).await;
let mut user_rate_limits = Limits::check_limits(urls.api.clone()).await; let mut user_rate_limits = Limits::check_limits(urls.api.clone()).await;
for _ in 0..=50 { for _ in 0..=50 {
let request_path = urls.api.clone() + "/some/random/nonexisting/path"; let request_path = urls.api.clone() + "/some/random/nonexisting/path";
let request_builder = requester.http.get(request_path); let request_builder = Client::new().get(request_path);
request = Some( request = Some(
requester LimitedRequester::send_request(
.send_request( request_builder,
request_builder, LimitType::Channel,
LimitType::Channel, &mut instance_rate_limits,
&mut instance_rate_limits, &mut user_rate_limits,
&mut user_rate_limits, )
) .await,
.await,
); );
} }
if request.is_some() { if request.is_some() {
@ -341,17 +305,16 @@ mod rate_limit {
); );
let mut instance_rate_limits = Limits::check_limits(urls.api.clone()).await; let mut instance_rate_limits = Limits::check_limits(urls.api.clone()).await;
let mut user_rate_limits = Limits::check_limits(urls.api.clone()).await; let mut user_rate_limits = Limits::check_limits(urls.api.clone()).await;
let mut requester = LimitedRequester::new().await; let _requester = LimitedRequester;
let request_path = urls.api.clone() + "/policies/instance/limits"; let request_path = urls.api.clone() + "/policies/instance/limits";
let request_builder = requester.http.get(request_path); let request_builder = Client::new().get(request_path);
let request = requester let request = LimitedRequester::send_request(
.send_request( request_builder,
request_builder, LimitType::Channel,
LimitType::Channel, &mut instance_rate_limits,
&mut instance_rate_limits, &mut user_rate_limits,
&mut user_rate_limits, )
) .await;
.await;
let result = match request { let result = match request {
Ok(result) => result, Ok(result) => result,
Err(_) => panic!("Request failed"), Err(_) => panic!("Request failed"),