feat(worker): handle FetchActorConnections — resolve and cache remote actor connections

This commit is contained in:
2026-05-15 00:40:34 +02:00
parent 58126f195c
commit 38a13ad641
2 changed files with 67 additions and 0 deletions

View File

@@ -14,6 +14,7 @@ pub struct FederationEventService {
pub base_url: String,
pub federation_action: Arc<dyn domain::ports::FederationActionPort>,
pub ap_repo: Arc<dyn ActivityPubRepository>,
pub remote_actor_connections: Arc<dyn domain::ports::RemoteActorConnectionRepository>,
}
impl FederationEventService {
@@ -157,6 +158,52 @@ impl FederationEventService {
Ok(())
}
DomainEvent::FetchActorConnections {
actor_ap_url,
collection_url,
connection_type,
page,
} => {
let urls = match self
.federation_action
.fetch_actor_urls_from_collection(collection_url)
.await
{
Ok(u) => u,
Err(e) => {
tracing::warn!(
collection_url,
error = %e,
"failed to fetch actor connections collection"
);
return Ok(());
}
};
if urls.is_empty() {
return Ok(());
}
let summaries = self.federation_action.resolve_actor_profiles(urls).await;
if summaries.is_empty() {
return Ok(());
}
tracing::info!(
count = summaries.len(),
connection_type,
actor = actor_ap_url,
"caching actor connections"
);
self.remote_actor_connections
.upsert_connections(actor_ap_url, connection_type, *page, &summaries)
.await?;
Ok(())
}
_ => Ok(()),
}
}
@@ -255,6 +302,7 @@ mod tests {
base_url: "https://example.com".to_string(),
federation_action: Arc::new(store.clone()),
ap_repo: Arc::new(store.clone()),
remote_actor_connections: Arc::new(store.clone()),
}
}
@@ -592,4 +640,19 @@ mod tests {
.unwrap();
// TestStore.fetch_outbox_page returns Ok(vec![]) — no notes, no error
}
#[tokio::test]
async fn fetch_actor_connections_is_noop_when_collection_empty() {
let store = TestStore::default();
let spy = Arc::new(SpyPort::default());
svc(&store, spy.clone())
.process(&DomainEvent::FetchActorConnections {
actor_ap_url: "https://mastodon.social/users/alice".into(),
collection_url: "https://mastodon.social/users/alice/followers".into(),
connection_type: "followers".into(),
page: 1,
})
.await
.unwrap();
}
}