Revert changes to comment.rs

This commit is contained in:
dullbananas 2023-12-20 15:53:31 -07:00 committed by GitHub
parent 82e37f7b57
commit f54a350b85
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -1,16 +1,6 @@
use crate::{ use crate::{
newtypes::{CommentId, DbUrl, PersonId}, newtypes::{CommentId, DbUrl, PersonId},
schema::comment::dsl::{ schema::comment::dsl::{ap_id, comment, content, creator_id, deleted, path, removed, updated},
ap_id,
comment,
content,
creator_id,
deleted,
id,
path,
removed,
updated,
},
source::comment::{ source::comment::{
Comment, Comment,
CommentInsertForm, CommentInsertForm,
@ -21,24 +11,16 @@ use crate::{
CommentUpdateForm, CommentUpdateForm,
}, },
traits::{Crud, Likeable, Saveable}, traits::{Crud, Likeable, Saveable},
utils::{functions::AsText, get_conn, naive_now, DbPool, DELETED_REPLACEMENT_TEXT}, utils::{get_conn, naive_now, DbPool, DELETED_REPLACEMENT_TEXT},
}; };
use diesel::{ use diesel::{
dsl::{insert_into, sql_query}, dsl::{insert_into, sql_query},
result::Error, result::Error,
ExpressionMethods, ExpressionMethods,
QueryDsl, QueryDsl,
TextExpressionMethods,
}; };
use diesel_async::RunQueryDsl; use diesel_async::RunQueryDsl;
use diesel_ltree::{ use diesel_ltree::Ltree;
functions::{ltree2text, text2ltree},
Ltree,
};
use futures_util::{
future::TryFutureExt,
stream::{self, StreamExt, TryStreamExt},
};
use url::Url; use url::Url;
impl Comment { impl Comment {
@ -75,63 +57,42 @@ impl Comment {
comment_form: &CommentInsertForm, comment_form: &CommentInsertForm,
parent_path: Option<&Ltree>, parent_path: Option<&Ltree>,
) -> Result<Comment, Error> { ) -> Result<Comment, Error> {
Comment::create_batch(pool, &[(comment_form.clone(), parent_path.cloned())])
.await?
.into_iter()
.next()
.ok_or(Error::NotFound)
}
pub async fn create_batch(
pool: &mut DbPool<'_>,
items: &[(CommentInsertForm, Option<Ltree>)],
) -> Result<Vec<Comment>, Error> {
let conn = &mut get_conn(pool).await?; let conn = &mut get_conn(pool).await?;
conn conn
.build_transaction() .build_transaction()
.run(|conn| { .run(|conn| {
Box::pin(async move { Box::pin(async move {
let forms = items // Insert, to get the id
.iter() let inserted_comment = insert_into(comment)
.map(|(comment_form, parent_path)| CommentInsertForm { .values(comment_form)
path: Some(parent_path.clone().unwrap_or(Ltree("0".to_owned()))),
..comment_form.clone()
});
// Insert, to get the ids
let inserted_comments = insert_into(comment)
.values(forms.clone().collect::<Vec<_>>())
.load::<Self>(conn)
.or_else(|_| {
// `ap_id` unique constraint violation is handled individually for each row
// because batched upsert requires having the same `set` argument for all rows
stream::iter(forms)
.then(|form| {
insert_into(comment)
.values(form.clone())
.on_conflict(ap_id) .on_conflict(ap_id)
.do_update() .do_update()
.set(form) .set(comment_form)
.get_result::<Self>(conn) .get_result::<Self>(conn)
})
.try_collect::<Vec<_>>()
})
.await?; .await?;
// For each comment, append its id to its path let comment_id = inserted_comment.id;
let updated_comments = diesel::update(comment)
.filter(id.eq_any(inserted_comments.into_iter().map(|c| c.id))) // You need to update the ltree column
.set(path.eq(text2ltree( let ltree = Ltree(if let Some(parent_path) = parent_path {
ltree2text(path).concat(".").concat(AsText::new(id)), // The previous parent will already have 0 in it
))) // Append this comment id
.load::<Self>(conn) format!("{}.{}", parent_path.0, comment_id)
.await?; } else {
// '0' is always the first path, append to that
format!("{}.{}", 0, comment_id)
});
let updated_comment = diesel::update(comment.find(comment_id))
.set(path.eq(ltree))
.get_result::<Self>(conn)
.await;
// Update the child count for the parent comment_aggregates // Update the child count for the parent comment_aggregates
// You could do this with a trigger, but since you have to do this manually anyway, // You could do this with a trigger, but since you have to do this manually anyway,
// you can just have it here // you can just have it here
for parent_path in items.iter().filter_map(|(_, p)| p.as_ref()) { if let Some(parent_path) = parent_path {
// You have to update counts for all parents, not just the immediate one // You have to update counts for all parents, not just the immediate one
// TODO if the performance of this is terrible, it might be better to do this as part of a // TODO if the performance of this is terrible, it might be better to do this as part of a
// scheduled query... although the counts would often be wrong. // scheduled query... although the counts would often be wrong.
@ -160,7 +121,7 @@ where ca.comment_id = c.id"
sql_query(update_child_count_stmt).execute(conn).await?; sql_query(update_child_count_stmt).execute(conn).await?;
} }
} }
Ok(updated_comments) updated_comment
}) as _ }) as _
}) })
.await .await