Clippy lints, dashmap for breakers

This commit is contained in:
Aode (lion) 2021-11-23 16:19:59 -06:00
parent e1c61d5b5f
commit 1dba31e3a0
18 changed files with 74 additions and 101 deletions

12
Cargo.lock generated
View file

@ -678,6 +678,16 @@ dependencies = [
"subtle",
]
[[package]]
name = "dashmap"
version = "4.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e77a43b28d0668df09411cb0bc9a8c2adc40f9a048afe863e05fd43251e8e39c"
dependencies = [
"cfg-if",
"num_cpus",
]
[[package]]
name = "der"
version = "0.4.4"
@ -1949,13 +1959,13 @@ dependencies = [
"actix-webfinger",
"ammonia",
"anyhow",
"async-mutex",
"async-rwlock",
"awc",
"background-jobs",
"base64",
"chrono",
"config",
"dashmap",
"dotenv",
"futures-util",
"http-signature-normalization-actix",

View file

@ -20,12 +20,12 @@ actix-webfinger = "0.4.0-beta.3"
activitystreams = "0.7.0-alpha.10"
activitystreams-ext = "0.1.0-alpha.2"
ammonia = "3.1.0"
async-mutex = "1.0.1"
async-rwlock = "1.3.0"
awc = { version = "3.0.0-beta.6", default-features = false, features = ["rustls"] }
base64 = "0.13"
chrono = "0.4.19"
config = "0.11.0"
dashmap = "4.0.2"
dotenv = "0.15.0"
futures-util = "0.3.17"
lru = "0.7.0"

View file

@ -17,10 +17,7 @@ pub enum MaybeCached<T> {
impl<T> MaybeCached<T> {
pub(crate) fn is_cached(&self) -> bool {
match self {
MaybeCached::Cached(_) => true,
_ => false,
}
matches!(self, MaybeCached::Cached(_))
}
pub(crate) fn into_inner(self) -> T {
@ -74,16 +71,16 @@ impl ActorCache {
let input_domain = id.domain().ok_or(ErrorKind::MissingDomain)?;
let accepted_actor_id = accepted_actor
.id(&input_domain)?
.id(input_domain)?
.ok_or(ErrorKind::MissingId)?;
let inbox = get_inbox(&accepted_actor)?.clone();
let actor = Actor {
id: accepted_actor_id.clone().into(),
id: accepted_actor_id.clone(),
public_key: accepted_actor.ext_one.public_key.public_key_pem,
public_key_id: accepted_actor.ext_one.public_key.id,
inbox: inbox.into(),
inbox,
saved_at: SystemTime::now(),
};

View file

@ -46,9 +46,9 @@ impl NodeCache {
.await?
.into_iter()
.map(move |actor_id| {
let info = infos.get(&actor_id).map(|info| info.clone());
let instance = instances.get(&actor_id).map(|instance| instance.clone());
let contact = contacts.get(&actor_id).map(|contact| contact.clone());
let info = infos.get(&actor_id).cloned();
let instance = instances.get(&actor_id).cloned();
let contact = contacts.get(&actor_id).cloned();
Node::new(actor_id)
.info(info)

View file

@ -107,10 +107,7 @@ impl std::fmt::Debug for Contact {
impl Inner {
fn connected_by_domain(&self, domains: &[String]) -> impl DoubleEndedIterator<Item = Url> {
let reversed: Vec<_> = domains
.into_iter()
.map(|s| domain_key(s.as_str()))
.collect();
let reversed: Vec<_> = domains.iter().map(|s| domain_key(s.as_str())).collect();
self.connected_actor_ids
.iter()
@ -147,7 +144,7 @@ impl Inner {
.filter_map(url_from_ivec)
}
fn connected_actors<'a>(&'a self) -> impl DoubleEndedIterator<Item = Actor> + 'a {
fn connected_actors(&self) -> impl DoubleEndedIterator<Item = Actor> + '_ {
self.connected_actor_ids
.iter()
.values()
@ -159,7 +156,7 @@ impl Inner {
})
}
fn connected_info<'a>(&'a self) -> impl DoubleEndedIterator<Item = (Url, Info)> + 'a {
fn connected_info(&self) -> impl DoubleEndedIterator<Item = (Url, Info)> + '_ {
self.connected_actor_ids
.iter()
.values()
@ -173,7 +170,7 @@ impl Inner {
})
}
fn connected_instance<'a>(&'a self) -> impl DoubleEndedIterator<Item = (Url, Instance)> + 'a {
fn connected_instance(&self) -> impl DoubleEndedIterator<Item = (Url, Instance)> + '_ {
self.connected_actor_ids
.iter()
.values()
@ -187,7 +184,7 @@ impl Inner {
})
}
fn connected_contact<'a>(&'a self) -> impl DoubleEndedIterator<Item = (Url, Contact)> + 'a {
fn connected_contact(&self) -> impl DoubleEndedIterator<Item = (Url, Contact)> + '_ {
self.connected_actor_ids
.iter()
.values()

View file

@ -17,7 +17,7 @@ pub(crate) struct Error {
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}\n", self.kind)?;
writeln!(f, "{}", self.kind)?;
std::fmt::Display::fmt(&self.context, f)
}
}
@ -171,7 +171,7 @@ impl ResponseError for Error {
serde_json::to_string(&serde_json::json!({
"error": self.kind.to_string(),
}))
.unwrap_or("{}".to_string()),
.unwrap_or_else(|_| "{}".to_string()),
)
}
}

View file

@ -46,7 +46,7 @@ impl QueryContact {
.await?;
let (username, display_name, url, avatar) =
to_contact(contact).ok_or_else(|| ErrorKind::Extract("contact"))?;
to_contact(contact).ok_or(ErrorKind::Extract("contact"))?;
state
.node_cache

View file

@ -51,18 +51,18 @@ impl QueryInstance {
.await?;
let description = if instance.description.is_empty() {
instance.short_description.unwrap_or(String::new())
instance.short_description.unwrap_or_default()
} else {
instance.description
};
if let Some(mut contact) = instance.contact {
let uuid = if let Some(uuid) = state.media.get_uuid(contact.avatar.clone()).await? {
contact.avatar = state.config.generate_url(UrlKind::Media(uuid)).into();
contact.avatar = state.config.generate_url(UrlKind::Media(uuid));
uuid
} else {
let uuid = state.media.store_url(contact.avatar.clone()).await?;
contact.avatar = state.config.generate_url(UrlKind::Media(uuid)).into();
contact.avatar = state.config.generate_url(UrlKind::Media(uuid));
uuid
};

View file

@ -15,7 +15,6 @@ pub(crate) use self::{
use crate::{
config::Config,
data::{ActorCache, MediaCache, NodeCache, State},
db::Db,
error::{Error, ErrorKind},
jobs::process_listeners::Listeners,
requests::Requests,
@ -24,7 +23,6 @@ use background_jobs::{memory_storage::Storage, Job, QueueHandle, WorkerConfig};
use std::time::Duration;
pub(crate) fn create_workers(
db: Db,
state: State,
actors: ActorCache,
media: MediaCache,
@ -32,7 +30,6 @@ pub(crate) fn create_workers(
) -> JobServer {
let queue_handle = WorkerConfig::new(Storage::new(), move |queue_handle| {
JobState::new(
db.clone(),
state.clone(),
actors.clone(),
JobServer::new(queue_handle),
@ -62,7 +59,6 @@ pub(crate) fn create_workers(
#[derive(Clone, Debug)]
pub(crate) struct JobState {
db: Db,
requests: Requests,
state: State,
actors: ActorCache,
@ -87,7 +83,6 @@ impl std::fmt::Debug for JobServer {
impl JobState {
fn new(
db: Db,
state: State,
actors: ActorCache,
job_server: JobServer,
@ -97,7 +92,6 @@ impl JobState {
JobState {
requests: state.requests(&config),
node_cache: state.node_cache(),
db,
actors,
config,
media,

View file

@ -66,7 +66,8 @@ impl QueryNodeinfo {
if let Some(contact_id) = accounts.get(0) {
state
.job_server
.queue(QueryContact::new(self.actor_id, contact_id.clone())).await?;
.queue(QueryContact::new(self.actor_id, contact_id.clone()))
.await?;
}
}
@ -129,10 +130,7 @@ enum MaybeSupported<T> {
impl<T> MaybeSupported<T> {
fn is_supported(&self) -> bool {
match self {
MaybeSupported::Supported(_) => true,
_ => false,
}
matches!(self, MaybeSupported::Supported(_))
}
}

View file

@ -97,13 +97,7 @@ async fn main() -> Result<(), anyhow::Error> {
let state = State::build(db.clone()).await?;
let actors = ActorCache::new(db.clone());
let job_server = create_workers(
db.clone(),
state.clone(),
actors.clone(),
media.clone(),
config.clone(),
);
let job_server = create_workers(state.clone(), actors.clone(), media.clone(), config.clone());
let bind_address = config.bind_address();
HttpServer::new(move || {

View file

@ -65,7 +65,7 @@ impl MyVerify {
.fetch::<PublicKeyResponse>(public_key_id.as_str())
.await?
.actor_id()
.ok_or_else(|| ErrorKind::MissingId)?
.ok_or(ErrorKind::MissingId)?
};
// Previously we verified the sig from an actor's local cache
@ -90,14 +90,14 @@ enum PublicKeyResponse {
#[allow(dead_code)]
public_key_pem: String,
},
Actor(AcceptedActors),
Actor(Box<AcceptedActors>),
}
impl PublicKeyResponse {
fn actor_id(&self) -> Option<Url> {
match self {
PublicKeyResponse::PublicKey { owner, .. } => Some(owner.clone()),
PublicKeyResponse::Actor(actor) => actor.id_unchecked().map(|url| url.clone()),
PublicKeyResponse::Actor(actor) => actor.id_unchecked().cloned(),
}
}
}

View file

@ -1,16 +1,14 @@
use crate::error::{Error, ErrorKind};
use activitystreams::url::Url;
use actix_web::{http::header::Date, web::Bytes};
use async_mutex::Mutex;
use async_rwlock::RwLock;
use awc::Client;
use chrono::{DateTime, Utc};
use dashmap::DashMap;
use http_signature_normalization_actix::prelude::*;
use rsa::{hash::Hash, padding::PaddingScheme, RsaPrivateKey};
use sha2::{Digest, Sha256};
use std::{
cell::RefCell,
collections::HashMap,
rc::Rc,
sync::{
atomic::{AtomicUsize, Ordering},
@ -23,7 +21,7 @@ use tracing_awc::Propagate;
#[derive(Clone)]
pub(crate) struct Breakers {
inner: Arc<RwLock<HashMap<String, Arc<Mutex<Breaker>>>>>,
inner: Arc<DashMap<String, Breaker>>,
}
impl std::fmt::Debug for Breakers {
@ -33,10 +31,10 @@ impl std::fmt::Debug for Breakers {
}
impl Breakers {
async fn should_try(&self, url: &Url) -> bool {
fn should_try(&self, url: &Url) -> bool {
if let Some(domain) = url.domain() {
if let Some(breaker) = self.inner.read().await.get(domain) {
breaker.lock().await.should_try()
if let Some(breaker) = self.inner.get(domain) {
breaker.should_try()
} else {
true
}
@ -45,15 +43,11 @@ impl Breakers {
}
}
async fn fail(&self, url: &Url) {
fn fail(&self, url: &Url) {
if let Some(domain) = url.domain() {
let should_write = {
let read = self.inner.read().await;
if let Some(breaker) = read.get(domain) {
let owned_breaker = Arc::clone(&breaker);
drop(breaker);
owned_breaker.lock().await.fail();
if let Some(mut breaker) = self.inner.get_mut(domain) {
breaker.fail();
false
} else {
true
@ -61,24 +55,17 @@ impl Breakers {
};
if should_write {
let mut hm = self.inner.write().await;
let breaker = hm
.entry(domain.to_owned())
.or_insert(Arc::new(Mutex::new(Breaker::default())));
breaker.lock().await.fail();
let mut breaker = self.inner.entry(domain.to_owned()).or_default();
breaker.fail();
}
}
}
async fn succeed(&self, url: &Url) {
fn succeed(&self, url: &Url) {
if let Some(domain) = url.domain() {
let should_write = {
let read = self.inner.read().await;
if let Some(breaker) = read.get(domain) {
let owned_breaker = Arc::clone(&breaker);
drop(breaker);
owned_breaker.lock().await.succeed();
if let Some(mut breaker) = self.inner.get_mut(domain) {
breaker.succeed();
false
} else {
true
@ -86,11 +73,8 @@ impl Breakers {
};
if should_write {
let mut hm = self.inner.write().await;
let breaker = hm
.entry(domain.to_owned())
.or_insert(Arc::new(Mutex::new(Breaker::default())));
breaker.lock().await.succeed();
let mut breaker = self.inner.entry(domain.to_owned()).or_default();
breaker.succeed();
}
}
}
@ -99,7 +83,7 @@ impl Breakers {
impl Default for Breakers {
fn default() -> Self {
Breakers {
inner: Arc::new(RwLock::new(HashMap::new())),
inner: Arc::new(DashMap::new()),
}
}
}
@ -233,7 +217,7 @@ impl Requests {
{
let parsed_url = url.parse::<Url>()?;
if !self.breakers.should_try(&parsed_url).await {
if !self.breakers.should_try(&parsed_url) {
return Err(ErrorKind::Breaker.into());
}
@ -256,7 +240,7 @@ impl Requests {
if res.is_err() {
self.count_err();
self.breakers.fail(&parsed_url).await;
self.breakers.fail(&parsed_url);
}
let mut res = res.map_err(|e| ErrorKind::SendRequest(url.to_string(), e.to_string()))?;
@ -272,12 +256,12 @@ impl Requests {
}
}
self.breakers.fail(&parsed_url).await;
self.breakers.fail(&parsed_url);
return Err(ErrorKind::Status(url.to_string(), res.status()).into());
}
self.breakers.succeed(&parsed_url).await;
self.breakers.succeed(&parsed_url);
let body = res
.body()
@ -291,7 +275,7 @@ impl Requests {
pub(crate) async fn fetch_bytes(&self, url: &str) -> Result<(String, Bytes), Error> {
let parsed_url = url.parse::<Url>()?;
if !self.breakers.should_try(&parsed_url).await {
if !self.breakers.should_try(&parsed_url) {
return Err(ErrorKind::Breaker.into());
}
@ -314,7 +298,7 @@ impl Requests {
.await;
if res.is_err() {
self.breakers.fail(&parsed_url).await;
self.breakers.fail(&parsed_url);
self.count_err();
}
@ -341,12 +325,12 @@ impl Requests {
}
}
self.breakers.fail(&parsed_url).await;
self.breakers.fail(&parsed_url);
return Err(ErrorKind::Status(url.to_string(), res.status()).into());
}
self.breakers.succeed(&parsed_url).await;
self.breakers.succeed(&parsed_url);
let bytes = match res.body().limit(1024 * 1024 * 4).await {
Err(e) => {
@ -366,7 +350,7 @@ impl Requests {
where
T: serde::ser::Serialize + std::fmt::Debug,
{
if !self.breakers.should_try(&inbox).await {
if !self.breakers.should_try(&inbox) {
return Err(ErrorKind::Breaker.into());
}
@ -393,7 +377,7 @@ impl Requests {
if res.is_err() {
self.count_err();
self.breakers.fail(&inbox).await;
self.breakers.fail(&inbox);
}
let mut res = res.map_err(|e| ErrorKind::SendRequest(inbox.to_string(), e.to_string()))?;
@ -409,11 +393,11 @@ impl Requests {
}
}
self.breakers.fail(&inbox).await;
self.breakers.fail(&inbox);
return Err(ErrorKind::Status(inbox.to_string(), res.status()).into());
}
self.breakers.succeed(&inbox).await;
self.breakers.succeed(&inbox);
Ok(())
}

View file

@ -24,8 +24,8 @@ pub(crate) async fn route(
ApActor::new(config.generate_url(UrlKind::Inbox), Application::new()),
PublicKey {
public_key: PublicKeyInner {
id: config.generate_url(UrlKind::MainKey).into(),
owner: config.generate_url(UrlKind::Actor).into(),
id: config.generate_url(UrlKind::MainKey),
owner: config.generate_url(UrlKind::Actor),
public_key_pem: state.public_key.to_public_key_pem()?,
},
},

View file

@ -54,13 +54,13 @@ pub(crate) async fn route(
.db
.inboxes()
.await
.unwrap_or(vec![])
.unwrap_or_default()
.iter()
.filter_map(|listener| listener.domain())
.map(|s| s.to_owned())
.collect(),
blocks: if config.publish_blocks() {
Some(state.db.blocks().await.unwrap_or(vec![]))
Some(state.db.blocks().await.unwrap_or_default())
} else {
None
},

View file

@ -4,6 +4,7 @@ use actix_web::{
web, HttpResponse,
};
#[allow(clippy::async_yields_async)]
#[tracing::instrument(name = "Statistics")]
pub(crate) async fn route(filename: web::Path<String>) -> HttpResponse {
if let Some(data) = StaticFile::get(&filename.into_inner()) {

View file

@ -11,10 +11,8 @@
</div>
<div class="right">
<p class="display-name"><a href="@contact.url">@contact.display_name</a></p>
@if let Some(domain) = base.domain() {
<p class="username">@@@contact.username@@@domain</p>
} else {
<p class="username">@@@contact.username</p>
}
<p class="username">
@@@contact.username@if let Some(domain) = base.domain() {@@@domain}
</p>
</div>
</div>

View file

@ -36,7 +36,7 @@
} else {
@if let Some(inf) = node.info.as_ref() {
<li>
@:info(&inf, &node.base)
@:info(inf, &node.base)
</li>
}
}