relay/src/data/actor.rs

105 lines
3.1 KiB
Rust
Raw Normal View History

2021-02-10 04:05:06 +00:00
use crate::{
apub::AcceptedActors,
db::{Actor, Db},
2021-09-18 17:55:39 +00:00
error::{Error, ErrorKind},
requests::{BreakerStrategy, Requests},
2021-02-10 04:05:06 +00:00
};
2022-01-17 22:54:45 +00:00
use activitystreams::{iri_string::types::IriString, prelude::*};
2021-02-10 04:05:06 +00:00
use std::time::{Duration, SystemTime};
2020-03-23 22:17:53 +00:00
const REFETCH_DURATION: Duration = Duration::from_secs(60 * 30);
2020-03-23 22:17:53 +00:00
#[derive(Debug)]
pub enum MaybeCached<T> {
Cached(T),
Fetched(T),
}
impl<T> MaybeCached<T> {
2021-02-10 04:05:06 +00:00
pub(crate) fn is_cached(&self) -> bool {
2021-11-23 22:19:59 +00:00
matches!(self, MaybeCached::Cached(_))
}
2021-02-10 04:05:06 +00:00
pub(crate) fn into_inner(self) -> T {
match self {
MaybeCached::Cached(t) | MaybeCached::Fetched(t) => t,
}
}
}
2021-09-18 17:55:39 +00:00
#[derive(Clone, Debug)]
2020-03-23 22:17:53 +00:00
pub struct ActorCache {
db: Db,
}
impl ActorCache {
2021-02-10 04:05:06 +00:00
pub(crate) fn new(db: Db) -> Self {
ActorCache { db }
}
#[tracing::instrument(level = "debug" name = "Get Actor", skip_all, fields(id = id.to_string().as_str()))]
2021-02-10 04:05:06 +00:00
pub(crate) async fn get(
&self,
2022-01-17 22:54:45 +00:00
id: &IriString,
2021-02-10 04:05:06 +00:00
requests: &Requests,
2021-09-18 17:55:39 +00:00
) -> Result<MaybeCached<Actor>, Error> {
2021-02-10 04:05:06 +00:00
if let Some(actor) = self.db.actor(id.clone()).await? {
if actor.saved_at + REFETCH_DURATION > SystemTime::now() {
return Ok(MaybeCached::Cached(actor));
}
}
2020-03-23 22:17:53 +00:00
2021-02-10 04:05:06 +00:00
self.get_no_cache(id, requests)
.await
.map(MaybeCached::Fetched)
}
2020-03-23 22:17:53 +00:00
2022-11-16 01:56:13 +00:00
#[tracing::instrument(level = "debug", name = "Add Connection", skip(self))]
2021-09-18 17:55:39 +00:00
pub(crate) async fn add_connection(&self, actor: Actor) -> Result<(), Error> {
self.db.add_connection(actor.id.clone()).await?;
self.db.save_actor(actor).await
2020-03-23 22:17:53 +00:00
}
2022-11-16 01:56:13 +00:00
#[tracing::instrument(level = "debug", name = "Remove Connection", skip(self))]
2021-09-18 17:55:39 +00:00
pub(crate) async fn remove_connection(&self, actor: &Actor) -> Result<(), Error> {
2021-02-10 06:44:48 +00:00
self.db.remove_connection(actor.id.clone()).await
2020-03-23 22:17:53 +00:00
}
#[tracing::instrument(level = "debug", name = "Fetch remote actor", skip_all, fields(id = id.to_string().as_str()))]
2022-01-17 22:54:45 +00:00
pub(crate) async fn get_no_cache(
&self,
id: &IriString,
requests: &Requests,
) -> Result<Actor, Error> {
let accepted_actor = requests
.fetch::<AcceptedActors>(id, BreakerStrategy::Require2XX)
.await?;
2020-03-23 22:17:53 +00:00
2022-01-17 22:54:45 +00:00
let input_authority = id.authority_components().ok_or(ErrorKind::MissingDomain)?;
2020-06-20 04:11:02 +00:00
let accepted_actor_id = accepted_actor
2022-01-17 22:54:45 +00:00
.id(input_authority.host(), input_authority.port())?
2021-09-18 17:55:39 +00:00
.ok_or(ErrorKind::MissingId)?;
2020-03-23 22:17:53 +00:00
2020-06-20 04:11:02 +00:00
let inbox = get_inbox(&accepted_actor)?.clone();
2020-03-23 22:17:53 +00:00
let actor = Actor {
2021-11-23 22:19:59 +00:00
id: accepted_actor_id.clone(),
2020-05-21 21:24:56 +00:00
public_key: accepted_actor.ext_one.public_key.public_key_pem,
public_key_id: accepted_actor.ext_one.public_key.id,
2021-11-23 22:19:59 +00:00
inbox,
2021-02-10 04:05:06 +00:00
saved_at: SystemTime::now(),
2020-03-23 22:17:53 +00:00
};
2021-02-10 04:05:06 +00:00
self.db.save_actor(actor.clone()).await?;
2020-03-23 22:17:53 +00:00
Ok(actor)
}
}
2022-01-17 22:54:45 +00:00
fn get_inbox(actor: &AcceptedActors) -> Result<&IriString, Error> {
2020-06-20 04:11:02 +00:00
Ok(actor
.endpoints()?
2023-07-20 01:23:11 +00:00
.and_then(|e| e.shared_inbox.as_ref())
2020-06-20 04:11:02 +00:00
.unwrap_or(actor.inbox()?))
}