]> Untitled Git - lemmy.git/blob - crates/db_schema/src/aggregates/comment_aggregates.rs
Calculate initial hot_rank and hot_rank_active for posts and comments from other...
[lemmy.git] / crates / db_schema / src / aggregates / comment_aggregates.rs
1 use crate::{
2   aggregates::structs::CommentAggregates,
3   newtypes::CommentId,
4   schema::comment_aggregates,
5   utils::{functions::hot_rank, get_conn, DbPool},
6 };
7 use diesel::{result::Error, ExpressionMethods, QueryDsl};
8 use diesel_async::RunQueryDsl;
9
10 impl CommentAggregates {
11   pub async fn read(pool: &DbPool, comment_id: CommentId) -> Result<Self, Error> {
12     let conn = &mut get_conn(pool).await?;
13     comment_aggregates::table
14       .filter(comment_aggregates::comment_id.eq(comment_id))
15       .first::<Self>(conn)
16       .await
17   }
18
19   pub async fn update_hot_rank(pool: &DbPool, comment_id: CommentId) -> Result<Self, Error> {
20     let conn = &mut get_conn(pool).await?;
21
22     diesel::update(comment_aggregates::table)
23       .filter(comment_aggregates::comment_id.eq(comment_id))
24       .set(comment_aggregates::hot_rank.eq(hot_rank(
25         comment_aggregates::score,
26         comment_aggregates::published,
27       )))
28       .get_result::<Self>(conn)
29       .await
30   }
31 }
32
33 #[cfg(test)]
34 mod tests {
35   use crate::{
36     aggregates::comment_aggregates::CommentAggregates,
37     source::{
38       comment::{Comment, CommentInsertForm, CommentLike, CommentLikeForm},
39       community::{Community, CommunityInsertForm},
40       instance::Instance,
41       person::{Person, PersonInsertForm},
42       post::{Post, PostInsertForm},
43     },
44     traits::{Crud, Likeable},
45     utils::build_db_pool_for_tests,
46   };
47   use serial_test::serial;
48
49   #[tokio::test]
50   #[serial]
51   async fn test_crud() {
52     let pool = &build_db_pool_for_tests().await;
53
54     let inserted_instance = Instance::read_or_create(pool, "my_domain.tld".to_string())
55       .await
56       .unwrap();
57
58     let new_person = PersonInsertForm::builder()
59       .name("thommy_comment_agg".into())
60       .public_key("pubkey".into())
61       .instance_id(inserted_instance.id)
62       .build();
63
64     let inserted_person = Person::create(pool, &new_person).await.unwrap();
65
66     let another_person = PersonInsertForm::builder()
67       .name("jerry_comment_agg".into())
68       .public_key("pubkey".into())
69       .instance_id(inserted_instance.id)
70       .build();
71
72     let another_inserted_person = Person::create(pool, &another_person).await.unwrap();
73
74     let new_community = CommunityInsertForm::builder()
75       .name("TIL_comment_agg".into())
76       .title("nada".to_owned())
77       .public_key("pubkey".to_string())
78       .instance_id(inserted_instance.id)
79       .build();
80
81     let inserted_community = Community::create(pool, &new_community).await.unwrap();
82
83     let new_post = PostInsertForm::builder()
84       .name("A test post".into())
85       .creator_id(inserted_person.id)
86       .community_id(inserted_community.id)
87       .build();
88
89     let inserted_post = Post::create(pool, &new_post).await.unwrap();
90
91     let comment_form = CommentInsertForm::builder()
92       .content("A test comment".into())
93       .creator_id(inserted_person.id)
94       .post_id(inserted_post.id)
95       .build();
96
97     let inserted_comment = Comment::create(pool, &comment_form, None).await.unwrap();
98
99     let child_comment_form = CommentInsertForm::builder()
100       .content("A test comment".into())
101       .creator_id(inserted_person.id)
102       .post_id(inserted_post.id)
103       .build();
104
105     let _inserted_child_comment =
106       Comment::create(pool, &child_comment_form, Some(&inserted_comment.path))
107         .await
108         .unwrap();
109
110     let comment_like = CommentLikeForm {
111       comment_id: inserted_comment.id,
112       post_id: inserted_post.id,
113       person_id: inserted_person.id,
114       score: 1,
115     };
116
117     CommentLike::like(pool, &comment_like).await.unwrap();
118
119     let comment_aggs_before_delete = CommentAggregates::read(pool, inserted_comment.id)
120       .await
121       .unwrap();
122
123     assert_eq!(1, comment_aggs_before_delete.score);
124     assert_eq!(1, comment_aggs_before_delete.upvotes);
125     assert_eq!(0, comment_aggs_before_delete.downvotes);
126
127     // Add a post dislike from the other person
128     let comment_dislike = CommentLikeForm {
129       comment_id: inserted_comment.id,
130       post_id: inserted_post.id,
131       person_id: another_inserted_person.id,
132       score: -1,
133     };
134
135     CommentLike::like(pool, &comment_dislike).await.unwrap();
136
137     let comment_aggs_after_dislike = CommentAggregates::read(pool, inserted_comment.id)
138       .await
139       .unwrap();
140
141     assert_eq!(0, comment_aggs_after_dislike.score);
142     assert_eq!(1, comment_aggs_after_dislike.upvotes);
143     assert_eq!(1, comment_aggs_after_dislike.downvotes);
144
145     // Remove the first comment like
146     CommentLike::remove(pool, inserted_person.id, inserted_comment.id)
147       .await
148       .unwrap();
149     let after_like_remove = CommentAggregates::read(pool, inserted_comment.id)
150       .await
151       .unwrap();
152     assert_eq!(-1, after_like_remove.score);
153     assert_eq!(0, after_like_remove.upvotes);
154     assert_eq!(1, after_like_remove.downvotes);
155
156     // Remove the parent post
157     Post::delete(pool, inserted_post.id).await.unwrap();
158
159     // Should be none found, since the post was deleted
160     let after_delete = CommentAggregates::read(pool, inserted_comment.id).await;
161     assert!(after_delete.is_err());
162
163     // This should delete all the associated rows, and fire triggers
164     Person::delete(pool, another_inserted_person.id)
165       .await
166       .unwrap();
167     let person_num_deleted = Person::delete(pool, inserted_person.id).await.unwrap();
168     assert_eq!(1, person_num_deleted);
169
170     // Delete the community
171     let community_num_deleted = Community::delete(pool, inserted_community.id)
172       .await
173       .unwrap();
174     assert_eq!(1, community_num_deleted);
175
176     Instance::delete(pool, inserted_instance.id).await.unwrap();
177   }
178 }