Skip to content

Commit

Permalink
Merge branch 'LemmyNet:main' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
kroese authored Nov 12, 2024
2 parents c12a5eb + 2e8687e commit cf8029e
Show file tree
Hide file tree
Showing 42 changed files with 2,285 additions and 1,522 deletions.
17 changes: 17 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@ i-love-jesus = { version = "0.1.0" }
clap = { version = "4.5.13", features = ["derive", "env"] }
pretty_assertions = "1.4.0"
derive-new = "0.7.0"
diesel-bind-if-some = "0.1.0"
tuplex = "0.1.2"

[dependencies]
lemmy_api = { workspace = true }
Expand Down
1 change: 0 additions & 1 deletion crates/api_common/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,6 @@ pub async fn update_read_comments(
person_id,
post_id,
read_comments,
..PersonPostAggregatesForm::default()
};

PersonPostAggregates::upsert(pool, &person_post_agg_form).await?;
Expand Down
4 changes: 4 additions & 0 deletions crates/db_schema/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ full = [
"tokio-postgres-rustls",
"rustls",
"i-love-jesus",
"tuplex",
"diesel-bind-if-some",
]

[dependencies]
Expand Down Expand Up @@ -76,8 +78,10 @@ rustls = { workspace = true, optional = true }
uuid = { workspace = true, features = ["v4"] }
i-love-jesus = { workspace = true, optional = true }
anyhow = { workspace = true }
diesel-bind-if-some = { workspace = true, optional = true }
moka.workspace = true
derive-new.workspace = true
tuplex = { workspace = true, optional = true }

[dev-dependencies]
serial_test = { workspace = true }
Expand Down
16 changes: 9 additions & 7 deletions crates/db_schema/replaceable_schema/triggers.sql
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,16 @@ AS $a$
BEGIN
EXECUTE replace($b$
-- When a thing gets a vote, update its aggregates and its creator's aggregates
CALL r.create_triggers ('thing_like', $$
CALL r.create_triggers ('thing_actions', $$
BEGIN
WITH thing_diff AS ( UPDATE
thing_aggregates AS a
SET
score = a.score + diff.upvotes - diff.downvotes, upvotes = a.upvotes + diff.upvotes, downvotes = a.downvotes + diff.downvotes, controversy_rank = r.controversy_rank ((a.upvotes + diff.upvotes)::numeric, (a.downvotes + diff.downvotes)::numeric)
FROM (
SELECT
(thing_like).thing_id, coalesce(sum(count_diff) FILTER (WHERE (thing_like).score = 1), 0) AS upvotes, coalesce(sum(count_diff) FILTER (WHERE (thing_like).score != 1), 0) AS downvotes FROM select_old_and_new_rows AS old_and_new_rows GROUP BY (thing_like).thing_id) AS diff
(thing_actions).thing_id, coalesce(sum(count_diff) FILTER (WHERE (thing_actions).like_score = 1), 0) AS upvotes, coalesce(sum(count_diff) FILTER (WHERE (thing_actions).like_score != 1), 0) AS downvotes FROM select_old_and_new_rows AS old_and_new_rows
WHERE (thing_actions).like_score IS NOT NULL GROUP BY (thing_actions).thing_id) AS diff
WHERE
a.thing_id = diff.thing_id
AND (diff.upvotes, diff.downvotes) != (0, 0)
Expand Down Expand Up @@ -360,18 +361,19 @@ CREATE TRIGGER comment_count
-- Count subscribers for communities.
-- subscribers should be updated only when a local community is followed by a local or remote person.
-- subscribers_local should be updated only when a local person follows a local or remote community.
CALL r.create_triggers ('community_follower', $$
CALL r.create_triggers ('community_actions', $$
BEGIN
UPDATE
community_aggregates AS a
SET
subscribers = a.subscribers + diff.subscribers, subscribers_local = a.subscribers_local + diff.subscribers_local
FROM (
SELECT
(community_follower).community_id, coalesce(sum(count_diff) FILTER (WHERE community.local), 0) AS subscribers, coalesce(sum(count_diff) FILTER (WHERE person.local), 0) AS subscribers_local
(community_actions).community_id, coalesce(sum(count_diff) FILTER (WHERE community.local), 0) AS subscribers, coalesce(sum(count_diff) FILTER (WHERE person.local), 0) AS subscribers_local
FROM select_old_and_new_rows AS old_and_new_rows
LEFT JOIN community ON community.id = (community_follower).community_id
LEFT JOIN person ON person.id = (community_follower).person_id GROUP BY (community_follower).community_id) AS diff
LEFT JOIN community ON community.id = (community_actions).community_id
LEFT JOIN person ON person.id = (community_actions).person_id
WHERE (community_actions).followed IS NOT NULL GROUP BY (community_actions).community_id) AS diff
WHERE
a.community_id = diff.community_id
AND (diff.subscribers, diff.subscribers_local) != (0, 0);
Expand Down Expand Up @@ -541,7 +543,7 @@ CREATE FUNCTION r.delete_follow_before_person ()
LANGUAGE plpgsql
AS $$
BEGIN
DELETE FROM community_follower AS c
DELETE FROM community_actions AS c
WHERE c.person_id = OLD.id;
RETURN OLD;
END;
Expand Down
23 changes: 16 additions & 7 deletions crates/db_schema/src/aggregates/person_post_aggregates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,17 @@ use crate::{
aggregates::structs::{PersonPostAggregates, PersonPostAggregatesForm},
diesel::OptionalExtension,
newtypes::{PersonId, PostId},
schema::person_post_aggregates::dsl::{person_id, person_post_aggregates, post_id},
utils::{get_conn, DbPool},
schema::post_actions,
utils::{find_action, get_conn, now, DbPool},
};
use diesel::{
expression::SelectableHelper,
insert_into,
result::Error,
ExpressionMethods,
NullableExpressionMethods,
QueryDsl,
};
use diesel::{insert_into, result::Error, QueryDsl};
use diesel_async::RunQueryDsl;

impl PersonPostAggregates {
Expand All @@ -14,11 +21,13 @@ impl PersonPostAggregates {
form: &PersonPostAggregatesForm,
) -> Result<Self, Error> {
let conn = &mut get_conn(pool).await?;
insert_into(person_post_aggregates)
let form = (form, post_actions::read_comments.eq(now().nullable()));
insert_into(post_actions::table)
.values(form)
.on_conflict((person_id, post_id))
.on_conflict((post_actions::person_id, post_actions::post_id))
.do_update()
.set(form)
.returning(Self::as_select())
.get_result::<Self>(conn)
.await
}
Expand All @@ -28,8 +37,8 @@ impl PersonPostAggregates {
post_id_: PostId,
) -> Result<Option<Self>, Error> {
let conn = &mut get_conn(pool).await?;
person_post_aggregates
.find((person_id_, post_id_))
find_action(post_actions::read_comments, (person_id_, post_id_))
.select(Self::as_select())
.first(conn)
.await
.optional()
Expand Down
14 changes: 10 additions & 4 deletions crates/db_schema/src/aggregates/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ use crate::schema::{
comment_aggregates,
community_aggregates,
person_aggregates,
person_post_aggregates,
post_actions,
post_aggregates,
site_aggregates,
};
use chrono::{DateTime, Utc};
#[cfg(feature = "full")]
use diesel::{dsl, expression_methods::NullableExpressionMethods};
#[cfg(feature = "full")]
use i_love_jesus::CursorKeysModule;
use serde::{Deserialize, Serialize};
#[cfg(feature = "full")]
Expand Down Expand Up @@ -151,7 +153,7 @@ pub struct PostAggregates {
feature = "full",
derive(Queryable, Selectable, Associations, Identifiable)
)]
#[cfg_attr(feature = "full", diesel(table_name = person_post_aggregates))]
#[cfg_attr(feature = "full", diesel(table_name = post_actions))]
#[cfg_attr(feature = "full", diesel(primary_key(person_id, post_id)))]
#[cfg_attr(feature = "full", diesel(belongs_to(crate::source::person::Person)))]
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
Expand All @@ -162,18 +164,22 @@ pub struct PersonPostAggregates {
/// The number of comments they've read on that post.
///
/// This is updated to the current post comment count every time they view a post.
#[cfg_attr(feature = "full", diesel(select_expression = post_actions::read_comments_amount.assume_not_null()))]
#[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull<post_actions::read_comments_amount>))]
pub read_comments: i64,
#[cfg_attr(feature = "full", diesel(select_expression = post_actions::read_comments.assume_not_null()))]
#[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull<post_actions::read_comments>))]
pub published: DateTime<Utc>,
}

#[derive(Clone, Default)]
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
#[cfg_attr(feature = "full", diesel(table_name = person_post_aggregates))]
#[cfg_attr(feature = "full", diesel(table_name = post_actions))]
pub struct PersonPostAggregatesForm {
pub person_id: PersonId,
pub post_id: PostId,
#[cfg_attr(feature = "full", diesel(column_name = read_comments_amount))]
pub read_comments: i64,
pub published: Option<DateTime<Utc>>,
}

#[derive(PartialEq, Eq, Debug, Serialize, Deserialize, Clone, Copy, Hash)]
Expand Down
66 changes: 45 additions & 21 deletions crates/db_schema/src/impls/comment.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
diesel::{DecoratableTarget, OptionalExtension},
newtypes::{CommentId, DbUrl, PersonId},
schema::comment,
schema::{comment, comment_actions},
source::comment::{
Comment,
CommentInsertForm,
Expand All @@ -12,10 +12,25 @@ use crate::{
CommentUpdateForm,
},
traits::{Crud, Likeable, Saveable},
utils::{functions::coalesce, get_conn, naive_now, DbPool, DELETED_REPLACEMENT_TEXT},
utils::{
functions::coalesce,
get_conn,
naive_now,
now,
uplete,
DbPool,
DELETED_REPLACEMENT_TEXT,
},
};
use chrono::{DateTime, Utc};
use diesel::{dsl::insert_into, result::Error, ExpressionMethods, QueryDsl};
use diesel::{
dsl::insert_into,
expression::SelectableHelper,
result::Error,
ExpressionMethods,
NullableExpressionMethods,
QueryDsl,
};
use diesel_async::RunQueryDsl;
use diesel_ltree::Ltree;
use url::Url;
Expand Down Expand Up @@ -141,25 +156,30 @@ impl Likeable for CommentLike {
type Form = CommentLikeForm;
type IdType = CommentId;
async fn like(pool: &mut DbPool<'_>, comment_like_form: &CommentLikeForm) -> Result<Self, Error> {
use crate::schema::comment_like::dsl::{comment_id, comment_like, person_id};
let conn = &mut get_conn(pool).await?;
insert_into(comment_like)
let comment_like_form = (
comment_like_form,
comment_actions::liked.eq(now().nullable()),
);
insert_into(comment_actions::table)
.values(comment_like_form)
.on_conflict((comment_id, person_id))
.on_conflict((comment_actions::comment_id, comment_actions::person_id))
.do_update()
.set(comment_like_form)
.returning(Self::as_select())
.get_result::<Self>(conn)
.await
}
async fn remove(
pool: &mut DbPool<'_>,
person_id: PersonId,
comment_id: CommentId,
) -> Result<usize, Error> {
use crate::schema::comment_like::dsl::comment_like;
) -> Result<uplete::Count, Error> {
let conn = &mut get_conn(pool).await?;
diesel::delete(comment_like.find((person_id, comment_id)))
.execute(conn)
uplete::new(comment_actions::table.find((person_id, comment_id)))
.set_null(comment_actions::like_score)
.set_null(comment_actions::liked)
.get_result(conn)
.await
}
}
Expand All @@ -171,26 +191,30 @@ impl Saveable for CommentSaved {
pool: &mut DbPool<'_>,
comment_saved_form: &CommentSavedForm,
) -> Result<Self, Error> {
use crate::schema::comment_saved::dsl::{comment_id, comment_saved, person_id};
let conn = &mut get_conn(pool).await?;
insert_into(comment_saved)
let comment_saved_form = (
comment_saved_form,
comment_actions::saved.eq(now().nullable()),
);
insert_into(comment_actions::table)
.values(comment_saved_form)
.on_conflict((comment_id, person_id))
.on_conflict((comment_actions::comment_id, comment_actions::person_id))
.do_update()
.set(comment_saved_form)
.returning(Self::as_select())
.get_result::<Self>(conn)
.await
}
async fn unsave(
pool: &mut DbPool<'_>,
comment_saved_form: &CommentSavedForm,
) -> Result<usize, Error> {
use crate::schema::comment_saved::dsl::comment_saved;
) -> Result<uplete::Count, Error> {
let conn = &mut get_conn(pool).await?;
diesel::delete(
comment_saved.find((comment_saved_form.person_id, comment_saved_form.comment_id)),
uplete::new(
comment_actions::table.find((comment_saved_form.person_id, comment_saved_form.comment_id)),
)
.execute(conn)
.set_null(comment_actions::saved)
.get_result(conn)
.await
}
}
Expand All @@ -216,7 +240,7 @@ mod tests {
post::{Post, PostInsertForm},
},
traits::{Crud, Likeable, Saveable},
utils::build_db_pool_for_tests,
utils::{build_db_pool_for_tests, uplete},
};
use diesel_ltree::Ltree;
use lemmy_utils::error::LemmyResult;
Expand Down Expand Up @@ -342,8 +366,8 @@ mod tests {
format!("0.{}.{}", expected_comment.id, inserted_child_comment.id),
inserted_child_comment.path.0,
);
assert_eq!(1, like_removed);
assert_eq!(1, saved_removed);
assert_eq!(uplete::Count::only_updated(1), like_removed);
assert_eq!(uplete::Count::only_deleted(1), saved_removed);
assert_eq!(1, num_deleted);

Ok(())
Expand Down
Loading

0 comments on commit cf8029e

Please sign in to comment.