refactor: SocialActor rich queries, migrate remaining handlers, slim SocialQueryPort

SocialQuery returns SocialActor (identity+handle+display_name+avatar_url)
instead of bare SocialIdentity. Migrated get_following_page,
get_followers_page, get_blocked_actors_page to use cases. Moved
get_activity_feed + get_profile from SocialQueryPort to SocialQuery.
Legacy SocialQueryPort remains only for get_users listing.
This commit is contained in:
2026-07-10 15:52:37 +02:00
parent 3ee75305a9
commit 7cfa234902
18 changed files with 276 additions and 148 deletions

View File

@@ -1,13 +1,19 @@
use std::sync::Arc;
use domain::ports::{
DiaryQuery, EventPublisher, ObjectStorage, SocialQueryPort, StatsRepository, UserRepository,
DiaryQuery, EventPublisher, ObjectStorage, SocialQuery, SocialQueryPort, StatsRepository,
UserRepository,
};
pub struct GetProfileDeps {
pub stats: Arc<dyn StatsRepository>,
pub diary: Arc<dyn DiaryQuery>,
pub social_query: Arc<dyn SocialQueryPort>,
pub social_query: Arc<dyn SocialQuery>,
}
pub struct GetUsersListDeps {
pub user: Arc<dyn UserRepository>,
pub social_query_legacy: Arc<dyn SocialQueryPort>,
}
pub struct UpdateProfileDeps {

View File

@@ -86,7 +86,7 @@ async fn load_social_counts(
.unwrap_or(0);
let followers = deps
.social_query
.count_accepted_followers(user_id)
.count_followers(user_id)
.await
.unwrap_or(0);
if !is_own_profile {
@@ -98,11 +98,19 @@ async fn load_social_counts(
.await
.unwrap_or_default()
.into_iter()
.map(|p| PendingFollowerView {
url: p.url,
handle: p.handle,
display_name: p.display_name,
avatar_url: p.avatar_url,
.map(|p| {
let url = match &p.identity {
domain::value_objects::SocialIdentity::Remote { actor_url } => actor_url.clone(),
domain::value_objects::SocialIdentity::Local(uid) => {
format!("local:{}", uid.value())
}
};
PendingFollowerView {
url,
handle: p.handle,
display_name: p.display_name,
avatar_url: p.avatar_url,
}
})
.collect();
(following, followers, pending)

View File

@@ -1,10 +1,7 @@
use std::sync::Arc;
use crate::users::queries::GetUsersQuery;
use crate::users::{deps::GetUsersListDeps, queries::GetUsersQuery};
use domain::{
errors::DomainError,
models::{RemoteActorInfo, UserSummary},
ports::{SocialQueryPort, UserRepository},
};
pub struct UsersListData {
@@ -13,13 +10,12 @@ pub struct UsersListData {
}
pub async fn execute(
user: Arc<dyn UserRepository>,
social_query: Arc<dyn SocialQueryPort>,
deps: &GetUsersListDeps,
_query: GetUsersQuery,
) -> Result<UsersListData, DomainError> {
let (users_result, actors_result) = tokio::join!(
user.list_with_stats(),
social_query.list_all_followed_remote_actors()
deps.user.list_with_stats(),
deps.social_query_legacy.list_all_followed_remote_actors()
);
Ok(UsersListData {
@@ -27,7 +23,3 @@ pub async fn execute(
remote_actors: actors_result?,
})
}
#[cfg(test)]
#[path = "tests/get_users.rs"]
mod tests;

View File

@@ -35,7 +35,7 @@ async fn returns_profile_with_empty_stats() {
let deps = GetProfileDeps {
stats: b.stats_repo.clone(),
diary: b.diary_repo.clone(),
social_query: b.social_query.clone(),
social_query: b.social_query_unified.clone(),
};
setup_user(&b, "profile@test.com", "profuser").await;
@@ -70,7 +70,7 @@ async fn returns_history_view() {
let deps = GetProfileDeps {
stats: b.stats_repo.clone(),
diary: b.diary_repo.clone(),
social_query: b.social_query.clone(),
social_query: b.social_query_unified.clone(),
};
setup_user(&b, "hist@test.com", "histuser").await;
@@ -107,7 +107,7 @@ async fn returns_trends_view() {
let deps = GetProfileDeps {
stats: b.stats_repo.clone(),
diary: b.diary_repo.clone(),
social_query: b.social_query.clone(),
social_query: b.social_query_unified.clone(),
};
setup_user(&b, "trends@test.com", "trendsuser").await;
@@ -144,7 +144,7 @@ async fn returns_ratings_view() {
let deps = GetProfileDeps {
stats: b.stats_repo.clone(),
diary: b.diary_repo.clone(),
social_query: b.social_query.clone(),
social_query: b.social_query_unified.clone(),
};
setup_user(&b, "ratings@test.com", "ratingsuser").await;
@@ -179,7 +179,7 @@ async fn returns_recent_with_search() {
let deps = GetProfileDeps {
stats: b.stats_repo.clone(),
diary: b.diary_repo.clone(),
social_query: b.social_query.clone(),
social_query: b.social_query_unified.clone(),
};
setup_user(&b, "search@test.com", "searchuser").await;
@@ -214,7 +214,7 @@ async fn non_own_profile_skips_pending_followers() {
let deps = GetProfileDeps {
stats: b.stats_repo.clone(),
diary: b.diary_repo.clone(),
social_query: b.social_query.clone(),
social_query: b.social_query_unified.clone(),
};
setup_user(&b, "other@test.com", "otheruser").await;