improve performance of community followers inbox query (#3482)

* improve performance of community followers inbox query

* nightly format

* force woodpecker to retry

---------

Co-authored-by: Dessalines <dessalines@users.noreply.github.com>
This commit is contained in:
phiresky 2023-07-05 17:50:26 +02:00 committed by GitHub
parent ebaf69bd70
commit 45b1a0d4fb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 38 additions and 21 deletions

View file

@ -14,7 +14,6 @@ use activitypub_federation::{
traits::{Actor, Object},
};
use chrono::NaiveDateTime;
use itertools::Itertools;
use lemmy_api_common::{
context::LemmyContext,
utils::{generate_featured_url, generate_moderators_url, generate_outbox_url},
@ -188,17 +187,11 @@ impl ApubCommunity {
let id = self.id;
let local_site_data = local_site_data_cached(context.pool()).await?;
let follows = CommunityFollowerView::for_community(context.pool(), id).await?;
let follows = CommunityFollowerView::get_community_follower_inboxes(context.pool(), id).await?;
let inboxes: Vec<Url> = follows
.into_iter()
.filter(|f| !f.follower.local)
.map(|f| {
f.follower
.shared_inbox_url
.unwrap_or(f.follower.inbox_url)
.into()
})
.unique()
.map(Into::into)
.filter(|inbox: &Url| inbox.host_str() != Some(&context.settings().hostname))
// Don't send to blocked instances
.filter(|inbox| check_apub_id_valid(inbox, &local_site_data).is_ok())

View file

@ -22,12 +22,12 @@ impl GroupFollowers {
) -> Result<GroupFollowers, LemmyError> {
let community_id = community.id;
let community_followers =
CommunityFollowerView::for_community(context.pool(), community_id).await?;
CommunityFollowerView::count_community_followers(context.pool(), community_id).await?;
Ok(GroupFollowers {
id: generate_followers_url(&community.actor_id)?.into(),
r#type: CollectionType::Collection,
total_items: community_followers.len() as i32,
total_items: community_followers as i32,
items: vec![],
})
}

View file

@ -1,8 +1,14 @@
use crate::structs::CommunityFollowerView;
use diesel::{result::Error, ExpressionMethods, QueryDsl};
use diesel::{
dsl::{count_star, not},
result::Error,
sql_function,
ExpressionMethods,
QueryDsl,
};
use diesel_async::RunQueryDsl;
use lemmy_db_schema::{
newtypes::{CommunityId, PersonId},
newtypes::{CommunityId, DbUrl, PersonId},
schema::{community, community_follower, person},
source::{community::Community, person::Person},
traits::JoinView,
@ -11,19 +17,37 @@ use lemmy_db_schema::{
type CommunityFollowerViewTuple = (Community, Person);
sql_function!(fn coalesce(x: diesel::sql_types::Nullable<diesel::sql_types::Text>, y: diesel::sql_types::Text) -> diesel::sql_types::Text);
impl CommunityFollowerView {
pub async fn for_community(pool: &DbPool, community_id: CommunityId) -> Result<Vec<Self>, Error> {
pub async fn get_community_follower_inboxes(
pool: &DbPool,
community_id: CommunityId,
) -> Result<Vec<DbUrl>, Error> {
let conn = &mut get_conn(pool).await?;
let res = community_follower::table
.inner_join(community::table)
.inner_join(person::table)
.select((community::all_columns, person::all_columns))
.filter(community_follower::community_id.eq(community_id))
.order_by(community::title)
.load::<CommunityFollowerViewTuple>(conn)
.filter(not(person::local))
.inner_join(person::table)
.select(coalesce(person::shared_inbox_url, person::inbox_url))
.distinct()
.load::<DbUrl>(conn)
.await?;
Ok(res.into_iter().map(Self::from_tuple).collect())
Ok(res)
}
pub async fn count_community_followers(
pool: &DbPool,
community_id: CommunityId,
) -> Result<i64, Error> {
let conn = &mut get_conn(pool).await?;
let res = community_follower::table
.filter(community_follower::community_id.eq(community_id))
.select(count_star())
.first::<i64>(conn)
.await?;
Ok(res)
}
pub async fn for_person(pool: &DbPool, person_id: PersonId) -> Result<Vec<Self>, Error> {