Optimize database queries in can_view_post()

This commit is contained in:
silverpill 2022-02-08 18:25:48 +00:00
parent 7d89f65b37
commit 0a2a145807
2 changed files with 37 additions and 13 deletions

View file

@ -3,7 +3,8 @@ use uuid::Uuid;
use crate::errors::DatabaseError; use crate::errors::DatabaseError;
use crate::models::reactions::queries::find_favourited_by_user; use crate::models::reactions::queries::find_favourited_by_user;
use crate::models::relationships::queries::get_relationship; use crate::models::relationships::queries::has_relationship;
use crate::models::relationships::types::RelationshipType;
use crate::models::users::types::User; use crate::models::users::types::User;
use super::queries::{get_posts, find_reposted_by_user}; use super::queries::{get_posts, find_reposted_by_user};
use super::types::{Post, PostActions, Visibility}; use super::types::{Post, PostActions, Visibility};
@ -65,41 +66,41 @@ pub async fn can_view_post(
user: Option<&User>, user: Option<&User>,
post: &Post, post: &Post,
) -> Result<bool, DatabaseError> { ) -> Result<bool, DatabaseError> {
let is_mentioned = |user: &User| {
post.mentions.iter().any(|profile| profile.id == user.profile.id)
};
let result = match post.visibility { let result = match post.visibility {
Visibility::Public => true, Visibility::Public => true,
Visibility::Direct => { Visibility::Direct => {
if let Some(user) = user { if let Some(user) = user {
// Returns true if user is mentioned // Returns true if user is mentioned
post.mentions.iter() is_mentioned(user)
.any(|profile| profile.id == user.profile.id)
} else { } else {
false false
} }
}, },
Visibility::Followers => { Visibility::Followers => {
if let Some(user) = user { if let Some(user) = user {
let relationship = get_relationship( let is_following = has_relationship(
db_client, db_client,
&post.author.id,
&user.id, &user.id,
&post.author.id,
RelationshipType::Follow,
).await?; ).await?;
let is_mentioned = post.mentions.iter() is_following || is_mentioned(user)
.any(|profile| profile.id == user.profile.id);
relationship.followed_by || is_mentioned
} else { } else {
false false
} }
}, },
Visibility::Subscribers => { Visibility::Subscribers => {
if let Some(user) = user { if let Some(user) = user {
let relationship = get_relationship( let is_subscriber = has_relationship(
db_client, db_client,
&post.author.id,
&user.id, &user.id,
&post.author.id,
RelationshipType::Subscription,
).await?; ).await?;
let is_mentioned = post.mentions.iter() is_subscriber || is_mentioned(user)
.any(|profile| profile.id == user.profile.id);
relationship.subscription_from || is_mentioned
} else { } else {
false false
} }

View file

@ -87,6 +87,29 @@ pub async fn get_relationship(
Ok(relationship_map) Ok(relationship_map)
} }
pub async fn has_relationship(
db_client: &impl GenericClient,
source_id: &Uuid,
target_id: &Uuid,
relationship_type: RelationshipType,
) -> Result<bool, DatabaseError> {
let maybe_row = db_client.query_opt(
"
SELECT 1
FROM relationship
WHERE
source_id = $1 AND target_id = $2
AND relationship_type = $3
",
&[
&source_id,
&target_id,
&relationship_type,
],
).await?;
Ok(maybe_row.is_some())
}
pub async fn follow( pub async fn follow(
db_client: &mut impl GenericClient, db_client: &mut impl GenericClient,
source_id: &Uuid, source_id: &Uuid,