forked from mirrors/relay
Rebuild client if too many consecutive failures
This commit is contained in:
parent
4df92f5128
commit
8dc24376fb
1 changed files with 67 additions and 16 deletions
|
@ -3,15 +3,23 @@ use activitystreams_new::primitives::XsdAnyUri;
|
||||||
use actix_web::{client::Client, http::header::Date};
|
use actix_web::{client::Client, http::header::Date};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use http_signature_normalization_actix::prelude::*;
|
use http_signature_normalization_actix::prelude::*;
|
||||||
use log::{debug, info};
|
use log::{debug, info, warn};
|
||||||
use rsa::{hash::Hashes, padding::PaddingScheme, RSAPrivateKey};
|
use rsa::{hash::Hashes, padding::PaddingScheme, RSAPrivateKey};
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
use std::time::SystemTime;
|
use std::{
|
||||||
|
cell::RefCell,
|
||||||
|
rc::Rc,
|
||||||
|
sync::atomic::{AtomicUsize, Ordering},
|
||||||
|
time::SystemTime,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Requests {
|
pub struct Requests {
|
||||||
client: Client,
|
client: Rc<RefCell<Client>>,
|
||||||
|
consecutive_errors: Rc<AtomicUsize>,
|
||||||
|
error_limit: usize,
|
||||||
key_id: String,
|
key_id: String,
|
||||||
|
user_agent: String,
|
||||||
private_key: RSAPrivateKey,
|
private_key: RSAPrivateKey,
|
||||||
config: Config,
|
config: Config,
|
||||||
}
|
}
|
||||||
|
@ -19,21 +27,43 @@ pub struct Requests {
|
||||||
impl Requests {
|
impl Requests {
|
||||||
pub fn new(key_id: String, private_key: RSAPrivateKey, user_agent: String) -> Self {
|
pub fn new(key_id: String, private_key: RSAPrivateKey, user_agent: String) -> Self {
|
||||||
Requests {
|
Requests {
|
||||||
client: Client::build().header("User-Agent", user_agent).finish(),
|
client: Rc::new(RefCell::new(
|
||||||
|
Client::build()
|
||||||
|
.header("User-Agent", user_agent.clone())
|
||||||
|
.finish(),
|
||||||
|
)),
|
||||||
|
consecutive_errors: Rc::new(AtomicUsize::new(0)),
|
||||||
|
error_limit: 3,
|
||||||
key_id,
|
key_id,
|
||||||
|
user_agent,
|
||||||
private_key,
|
private_key,
|
||||||
config: Config::default().dont_use_created_field(),
|
config: Config::default().dont_use_created_field(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn count_err(&self) {
|
||||||
|
let count = self.consecutive_errors.fetch_add(1, Ordering::Relaxed);
|
||||||
|
if count + 1 >= self.error_limit {
|
||||||
|
warn!("{} consecutive errors, rebuilding http client", count);
|
||||||
|
*self.client.borrow_mut() = Client::build()
|
||||||
|
.header("User-Agent", self.user_agent.clone())
|
||||||
|
.finish();
|
||||||
|
self.reset_err();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reset_err(&self) {
|
||||||
|
self.consecutive_errors.swap(0, Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn fetch<T>(&self, url: &str) -> Result<T, MyError>
|
pub async fn fetch<T>(&self, url: &str) -> Result<T, MyError>
|
||||||
where
|
where
|
||||||
T: serde::de::DeserializeOwned,
|
T: serde::de::DeserializeOwned,
|
||||||
{
|
{
|
||||||
let signer = self.signer();
|
let signer = self.signer();
|
||||||
|
|
||||||
let mut res = self
|
let client: Client = self.client.borrow().clone();
|
||||||
.client
|
let res = client
|
||||||
.get(url)
|
.get(url)
|
||||||
.header("Accept", "application/activity+json")
|
.header("Accept", "application/activity+json")
|
||||||
.set(Date(SystemTime::now().into()))
|
.set(Date(SystemTime::now().into()))
|
||||||
|
@ -44,8 +74,15 @@ impl Requests {
|
||||||
)
|
)
|
||||||
.await?
|
.await?
|
||||||
.send()
|
.send()
|
||||||
.await
|
.await;
|
||||||
.map_err(|e| MyError::SendRequest(url.to_string(), e.to_string()))?;
|
|
||||||
|
if res.is_err() {
|
||||||
|
self.count_err();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut res = res.map_err(|e| MyError::SendRequest(url.to_string(), e.to_string()))?;
|
||||||
|
|
||||||
|
self.reset_err();
|
||||||
|
|
||||||
if !res.status().is_success() {
|
if !res.status().is_success() {
|
||||||
if let Ok(bytes) = res.body().await {
|
if let Ok(bytes) = res.body().await {
|
||||||
|
@ -68,8 +105,8 @@ impl Requests {
|
||||||
info!("Fetching bytes for {}", url);
|
info!("Fetching bytes for {}", url);
|
||||||
let signer = self.signer();
|
let signer = self.signer();
|
||||||
|
|
||||||
let mut res = self
|
let client: Client = self.client.borrow().clone();
|
||||||
.client
|
let res = client
|
||||||
.get(url)
|
.get(url)
|
||||||
.header("Accept", "*/*")
|
.header("Accept", "*/*")
|
||||||
.set(Date(SystemTime::now().into()))
|
.set(Date(SystemTime::now().into()))
|
||||||
|
@ -80,8 +117,15 @@ impl Requests {
|
||||||
)
|
)
|
||||||
.await?
|
.await?
|
||||||
.send()
|
.send()
|
||||||
.await
|
.await;
|
||||||
.map_err(|e| MyError::SendRequest(url.to_string(), e.to_string()))?;
|
|
||||||
|
if res.is_err() {
|
||||||
|
self.count_err();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut res = res.map_err(|e| MyError::SendRequest(url.to_string(), e.to_string()))?;
|
||||||
|
|
||||||
|
self.reset_err();
|
||||||
|
|
||||||
let content_type = if let Some(content_type) = res.headers().get("content-type") {
|
let content_type = if let Some(content_type) = res.headers().get("content-type") {
|
||||||
if let Ok(s) = content_type.to_str() {
|
if let Ok(s) = content_type.to_str() {
|
||||||
|
@ -122,8 +166,8 @@ impl Requests {
|
||||||
let signer = self.signer();
|
let signer = self.signer();
|
||||||
let item_string = serde_json::to_string(item)?;
|
let item_string = serde_json::to_string(item)?;
|
||||||
|
|
||||||
let mut res = self
|
let client: Client = self.client.borrow().clone();
|
||||||
.client
|
let res = client
|
||||||
.post(inbox.as_str())
|
.post(inbox.as_str())
|
||||||
.header("Accept", "application/activity+json")
|
.header("Accept", "application/activity+json")
|
||||||
.header("Content-Type", "application/activity+json")
|
.header("Content-Type", "application/activity+json")
|
||||||
|
@ -137,8 +181,15 @@ impl Requests {
|
||||||
)
|
)
|
||||||
.await?
|
.await?
|
||||||
.send()
|
.send()
|
||||||
.await
|
.await;
|
||||||
.map_err(|e| MyError::SendRequest(inbox.to_string(), e.to_string()))?;
|
|
||||||
|
if res.is_err() {
|
||||||
|
self.count_err();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut res = res.map_err(|e| MyError::SendRequest(inbox.to_string(), e.to_string()))?;
|
||||||
|
|
||||||
|
self.reset_err();
|
||||||
|
|
||||||
if !res.status().is_success() {
|
if !res.status().is_success() {
|
||||||
if let Ok(bytes) = res.body().await {
|
if let Ok(bytes) = res.body().await {
|
||||||
|
|
Loading…
Reference in a new issue