fix: is_following helper, fixed fe follow fields

This commit is contained in:
əlemi 2024-05-29 19:25:43 +02:00
parent 2a6b6a88ae
commit f487ac06e9
Signed by: alemi
GPG key ID: A4895B84D311642C
2 changed files with 18 additions and 24 deletions

View file

@ -62,6 +62,7 @@ impl Related<super::activity::Entity> for Entity {
impl ActiveModelBehavior for ActiveModel {} impl ActiveModelBehavior for ActiveModel {}
impl Entity { impl Entity {
// TODO this is 2 queries!!! can it be optimized down to 1?
pub async fn followers(uid: &str, db: &DatabaseConnection) -> crate::Result<Vec<String>> { pub async fn followers(uid: &str, db: &DatabaseConnection) -> crate::Result<Vec<String>> {
let internal_id = super::actor::Entity::ap_to_internal(uid, db).await?; let internal_id = super::actor::Entity::ap_to_internal(uid, db).await?;
let out = Entity::find() let out = Entity::find()
@ -82,6 +83,7 @@ impl Entity {
Ok(out) Ok(out)
} }
// TODO this is 2 queries!!! can it be optimized down to 1?
pub async fn following(uid: &str, db: &DatabaseConnection) -> crate::Result<Vec<String>> { pub async fn following(uid: &str, db: &DatabaseConnection) -> crate::Result<Vec<String>> {
let internal_id = super::actor::Entity::ap_to_internal(uid, db).await?; let internal_id = super::actor::Entity::ap_to_internal(uid, db).await?;
let out = Entity::find() let out = Entity::find()
@ -101,4 +103,14 @@ impl Entity {
Ok(out) Ok(out)
} }
// TODO this is 3 queries!!! can it be optimized down to 1?
pub fn is_following(follower: i64, following: i64) -> sea_orm::Selector<sea_orm::SelectGetableTuple<i64>> {
Entity::find()
.filter(Column::Follower.eq(follower))
.filter(Column::Following.eq(following))
.select_only()
.select_column(Column::Internal)
.into_tuple::<i64>()
}
} }

View file

@ -5,10 +5,9 @@ pub mod outbox;
pub mod following; pub mod following;
use axum::extract::{Path, Query, State}; use axum::extract::{Path, Query, State};
use sea_orm::{ColumnTrait, EntityTrait, QueryFilter, QuerySelect, SelectColumns};
use apb::{ActorMut, EndpointsMut, Node}; use apb::{ActorMut, EndpointsMut, Node};
use crate::{errors::UpubError, model, server::{auth::AuthIdentity, fetcher::Fetcher, Context}, url}; use crate::{errors::UpubError, model, server::{auth::AuthIdentity, builders::AnyQuery, fetcher::Fetcher, Context}, url};
use super::{jsonld::LD, JsonLD, TryFetch}; use super::{jsonld::LD, JsonLD, TryFetch};
@ -30,34 +29,17 @@ pub async fn view(
ctx.fetch_user(&uid).await?; ctx.fetch_user(&uid).await?;
} }
} }
let internal_uid = model::actor::Entity::ap_to_internal(&uid, ctx.db()).await?;
let (followed_by_me, following_me) = match auth.my_id() { let (followed_by_me, following_me) = match auth.my_id() {
None => (None, None), None => (None, None),
Some(my_id) => { Some(my_id) => {
// TODO these two queries are fast because of indexes but still are 2 subqueries for each // TODO these two queries are fast because of indexes but still are 2 subqueries for each
// user GET, not even parallelized... should really add these as joins on the main query, so // user GET, not even parallelized... should maybe add these as joins on the main query? so
// that it's one roundtrip only // that it's one roundtrip only
let followed_by_me = model::relation::Entity::find() let followed_by_me = model::relation::Entity::is_following(my_id, internal_uid).any(ctx.db()).await?;
.filter(model::relation::Column::Follower.eq(my_id)) let following_me = model::relation::Entity::is_following(internal_uid, my_id).any(ctx.db()).await?;
.filter(model::relation::Column::Following.eq(&uid)) (Some(followed_by_me), Some(following_me))
.select_only()
.select_column(model::relation::Column::Follower)
.into_tuple::<String>()
.one(ctx.db())
.await?
.map(|_| true);
let following_me = model::relation::Entity::find()
.filter(model::relation::Column::Following.eq(my_id))
.filter(model::relation::Column::Follower.eq(&uid))
.select_only()
.select_column(model::relation::Column::Follower)
.into_tuple::<String>()
.one(ctx.db())
.await?
.map(|_| true);
(followed_by_me, following_me)
}, },
}; };