From 93f5df2d2a99868b2d4d27c67c94b01a6d4b2666 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Thu, 25 Apr 2024 18:19:02 -0400 Subject: [PATCH 1/3] Adding post_id desc to all post_aggregates indexes. Fixes #4618 (#4662) * Adding post_id desc to all post_aggregates indexes. Fixes #4618 * Running pg_format * Not rebuilding indexes which had no changes. --- .../down.sql | 120 +++++++++++++++++ .../up.sql | 121 ++++++++++++++++++ 2 files changed, 241 insertions(+) create mode 100644 migrations/2024-04-23-020604_add_post_id_index/down.sql create mode 100644 migrations/2024-04-23-020604_add_post_id_index/up.sql diff --git a/migrations/2024-04-23-020604_add_post_id_index/down.sql b/migrations/2024-04-23-020604_add_post_id_index/down.sql new file mode 100644 index 000000000..fb4c92f6c --- /dev/null +++ b/migrations/2024-04-23-020604_add_post_id_index/down.sql @@ -0,0 +1,120 @@ +DROP INDEX idx_post_aggregates_community_active; + +DROP INDEX idx_post_aggregates_community_controversy; + +DROP INDEX idx_post_aggregates_community_hot; + +DROP INDEX idx_post_aggregates_community_most_comments; + +DROP INDEX idx_post_aggregates_community_newest_comment_time; + +DROP INDEX idx_post_aggregates_community_newest_comment_time_necro; + +DROP INDEX idx_post_aggregates_community_published; + +DROP INDEX idx_post_aggregates_community_published_asc; + +DROP INDEX idx_post_aggregates_community_scaled; + +DROP INDEX idx_post_aggregates_community_score; + +DROP INDEX idx_post_aggregates_featured_community_active; + +DROP INDEX idx_post_aggregates_featured_community_controversy; + +DROP INDEX idx_post_aggregates_featured_community_hot; + +DROP INDEX idx_post_aggregates_featured_community_most_comments; + +DROP INDEX idx_post_aggregates_featured_community_newest_comment_time; + +DROP INDEX idx_post_aggregates_featured_community_newest_comment_time_necr; + +DROP INDEX idx_post_aggregates_featured_community_published; + +DROP INDEX idx_post_aggregates_featured_community_published_asc; + +DROP INDEX idx_post_aggregates_featured_community_scaled; + +DROP INDEX idx_post_aggregates_featured_community_score; + +DROP INDEX idx_post_aggregates_featured_local_active; + +DROP INDEX idx_post_aggregates_featured_local_controversy; + +DROP INDEX idx_post_aggregates_featured_local_hot; + +DROP INDEX idx_post_aggregates_featured_local_most_comments; + +DROP INDEX idx_post_aggregates_featured_local_newest_comment_time; + +DROP INDEX idx_post_aggregates_featured_local_newest_comment_time_necro; + +DROP INDEX idx_post_aggregates_featured_local_published; + +DROP INDEX idx_post_aggregates_featured_local_published_asc; + +DROP INDEX idx_post_aggregates_featured_local_scaled; + +DROP INDEX idx_post_aggregates_featured_local_score; + +CREATE INDEX idx_post_aggregates_community_active ON public.post_aggregates USING btree (community_id, featured_local DESC, hot_rank_active DESC, published DESC); + +CREATE INDEX idx_post_aggregates_community_controversy ON public.post_aggregates USING btree (community_id, featured_local DESC, controversy_rank DESC); + +CREATE INDEX idx_post_aggregates_community_hot ON public.post_aggregates USING btree (community_id, featured_local DESC, hot_rank DESC, published DESC); + +CREATE INDEX idx_post_aggregates_community_most_comments ON public.post_aggregates USING btree (community_id, featured_local DESC, comments DESC, published DESC); + +CREATE INDEX idx_post_aggregates_community_newest_comment_time ON public.post_aggregates USING btree (community_id, featured_local DESC, newest_comment_time DESC); + +CREATE INDEX idx_post_aggregates_community_newest_comment_time_necro ON public.post_aggregates USING btree (community_id, featured_local DESC, newest_comment_time_necro DESC); + +CREATE INDEX idx_post_aggregates_community_published ON public.post_aggregates USING btree (community_id, featured_local DESC, published DESC); + +CREATE INDEX idx_post_aggregates_community_published_asc ON public.post_aggregates USING btree (community_id, featured_local DESC, public.reverse_timestamp_sort (published) DESC); + +CREATE INDEX idx_post_aggregates_community_scaled ON public.post_aggregates USING btree (community_id, featured_local DESC, scaled_rank DESC, published DESC); + +CREATE INDEX idx_post_aggregates_community_score ON public.post_aggregates USING btree (community_id, featured_local DESC, score DESC, published DESC); + +CREATE INDEX idx_post_aggregates_featured_community_active ON public.post_aggregates USING btree (community_id, featured_community DESC, hot_rank_active DESC, published DESC); + +CREATE INDEX idx_post_aggregates_featured_community_controversy ON public.post_aggregates USING btree (community_id, featured_community DESC, controversy_rank DESC); + +CREATE INDEX idx_post_aggregates_featured_community_hot ON public.post_aggregates USING btree (community_id, featured_community DESC, hot_rank DESC, published DESC); + +CREATE INDEX idx_post_aggregates_featured_community_most_comments ON public.post_aggregates USING btree (community_id, featured_community DESC, comments DESC, published DESC); + +CREATE INDEX idx_post_aggregates_featured_community_newest_comment_time ON public.post_aggregates USING btree (community_id, featured_community DESC, newest_comment_time DESC); + +CREATE INDEX idx_post_aggregates_featured_community_newest_comment_time_necr ON public.post_aggregates USING btree (community_id, featured_community DESC, newest_comment_time_necro DESC); + +CREATE INDEX idx_post_aggregates_featured_community_published ON public.post_aggregates USING btree (community_id, featured_community DESC, published DESC); + +CREATE INDEX idx_post_aggregates_featured_community_published_asc ON public.post_aggregates USING btree (community_id, featured_community DESC, public.reverse_timestamp_sort (published) DESC); + +CREATE INDEX idx_post_aggregates_featured_community_scaled ON public.post_aggregates USING btree (community_id, featured_community DESC, scaled_rank DESC, published DESC); + +CREATE INDEX idx_post_aggregates_featured_community_score ON public.post_aggregates USING btree (community_id, featured_community DESC, score DESC, published DESC); + +CREATE INDEX idx_post_aggregates_featured_local_active ON public.post_aggregates USING btree (featured_local DESC, hot_rank_active DESC, published DESC); + +CREATE INDEX idx_post_aggregates_featured_local_controversy ON public.post_aggregates USING btree (featured_local DESC, controversy_rank DESC); + +CREATE INDEX idx_post_aggregates_featured_local_hot ON public.post_aggregates USING btree (featured_local DESC, hot_rank DESC, published DESC); + +CREATE INDEX idx_post_aggregates_featured_local_most_comments ON public.post_aggregates USING btree (featured_local DESC, comments DESC, published DESC); + +CREATE INDEX idx_post_aggregates_featured_local_newest_comment_time ON public.post_aggregates USING btree (featured_local DESC, newest_comment_time DESC); + +CREATE INDEX idx_post_aggregates_featured_local_newest_comment_time_necro ON public.post_aggregates USING btree (featured_local DESC, newest_comment_time_necro DESC); + +CREATE INDEX idx_post_aggregates_featured_local_published ON public.post_aggregates USING btree (featured_local DESC, published DESC); + +CREATE INDEX idx_post_aggregates_featured_local_published_asc ON public.post_aggregates USING btree (featured_local DESC, public.reverse_timestamp_sort (published) DESC); + +CREATE INDEX idx_post_aggregates_featured_local_scaled ON public.post_aggregates USING btree (featured_local DESC, scaled_rank DESC, published DESC); + +CREATE INDEX idx_post_aggregates_featured_local_score ON public.post_aggregates USING btree (featured_local DESC, score DESC, published DESC); + diff --git a/migrations/2024-04-23-020604_add_post_id_index/up.sql b/migrations/2024-04-23-020604_add_post_id_index/up.sql new file mode 100644 index 000000000..8581d7169 --- /dev/null +++ b/migrations/2024-04-23-020604_add_post_id_index/up.sql @@ -0,0 +1,121 @@ +-- Add , post_id DESC to all these +DROP INDEX idx_post_aggregates_community_active; + +DROP INDEX idx_post_aggregates_community_controversy; + +DROP INDEX idx_post_aggregates_community_hot; + +DROP INDEX idx_post_aggregates_community_most_comments; + +DROP INDEX idx_post_aggregates_community_newest_comment_time; + +DROP INDEX idx_post_aggregates_community_newest_comment_time_necro; + +DROP INDEX idx_post_aggregates_community_published; + +DROP INDEX idx_post_aggregates_community_published_asc; + +DROP INDEX idx_post_aggregates_community_scaled; + +DROP INDEX idx_post_aggregates_community_score; + +DROP INDEX idx_post_aggregates_featured_community_active; + +DROP INDEX idx_post_aggregates_featured_community_controversy; + +DROP INDEX idx_post_aggregates_featured_community_hot; + +DROP INDEX idx_post_aggregates_featured_community_most_comments; + +DROP INDEX idx_post_aggregates_featured_community_newest_comment_time; + +DROP INDEX idx_post_aggregates_featured_community_newest_comment_time_necr; + +DROP INDEX idx_post_aggregates_featured_community_published; + +DROP INDEX idx_post_aggregates_featured_community_published_asc; + +DROP INDEX idx_post_aggregates_featured_community_scaled; + +DROP INDEX idx_post_aggregates_featured_community_score; + +DROP INDEX idx_post_aggregates_featured_local_active; + +DROP INDEX idx_post_aggregates_featured_local_controversy; + +DROP INDEX idx_post_aggregates_featured_local_hot; + +DROP INDEX idx_post_aggregates_featured_local_most_comments; + +DROP INDEX idx_post_aggregates_featured_local_newest_comment_time; + +DROP INDEX idx_post_aggregates_featured_local_newest_comment_time_necro; + +DROP INDEX idx_post_aggregates_featured_local_published; + +DROP INDEX idx_post_aggregates_featured_local_published_asc; + +DROP INDEX idx_post_aggregates_featured_local_scaled; + +DROP INDEX idx_post_aggregates_featured_local_score; + +CREATE INDEX idx_post_aggregates_community_active ON public.post_aggregates USING btree (community_id, featured_local DESC, hot_rank_active DESC, published DESC, post_id DESC); + +CREATE INDEX idx_post_aggregates_community_controversy ON public.post_aggregates USING btree (community_id, featured_local DESC, controversy_rank DESC, post_id DESC); + +CREATE INDEX idx_post_aggregates_community_hot ON public.post_aggregates USING btree (community_id, featured_local DESC, hot_rank DESC, published DESC, post_id DESC); + +CREATE INDEX idx_post_aggregates_community_most_comments ON public.post_aggregates USING btree (community_id, featured_local DESC, comments DESC, published DESC, post_id DESC); + +CREATE INDEX idx_post_aggregates_community_newest_comment_time ON public.post_aggregates USING btree (community_id, featured_local DESC, newest_comment_time DESC, post_id DESC); + +CREATE INDEX idx_post_aggregates_community_newest_comment_time_necro ON public.post_aggregates USING btree (community_id, featured_local DESC, newest_comment_time_necro DESC, post_id DESC); + +CREATE INDEX idx_post_aggregates_community_published ON public.post_aggregates USING btree (community_id, featured_local DESC, published DESC, post_id DESC); + +CREATE INDEX idx_post_aggregates_community_published_asc ON public.post_aggregates USING btree (community_id, featured_local DESC, public.reverse_timestamp_sort (published) DESC, post_id DESC); + +CREATE INDEX idx_post_aggregates_community_scaled ON public.post_aggregates USING btree (community_id, featured_local DESC, scaled_rank DESC, published DESC, post_id DESC); + +CREATE INDEX idx_post_aggregates_community_score ON public.post_aggregates USING btree (community_id, featured_local DESC, score DESC, published DESC, post_id DESC); + +CREATE INDEX idx_post_aggregates_featured_community_active ON public.post_aggregates USING btree (community_id, featured_community DESC, hot_rank_active DESC, published DESC, post_id DESC); + +CREATE INDEX idx_post_aggregates_featured_community_controversy ON public.post_aggregates USING btree (community_id, featured_community DESC, controversy_rank DESC, post_id DESC); + +CREATE INDEX idx_post_aggregates_featured_community_hot ON public.post_aggregates USING btree (community_id, featured_community DESC, hot_rank DESC, published DESC, post_id DESC); + +CREATE INDEX idx_post_aggregates_featured_community_most_comments ON public.post_aggregates USING btree (community_id, featured_community DESC, comments DESC, published DESC, post_id DESC); + +CREATE INDEX idx_post_aggregates_featured_community_newest_comment_time ON public.post_aggregates USING btree (community_id, featured_community DESC, newest_comment_time DESC, post_id DESC); + +CREATE INDEX idx_post_aggregates_featured_community_newest_comment_time_necr ON public.post_aggregates USING btree (community_id, featured_community DESC, newest_comment_time_necro DESC, post_id DESC); + +CREATE INDEX idx_post_aggregates_featured_community_published ON public.post_aggregates USING btree (community_id, featured_community DESC, published DESC, post_id DESC); + +CREATE INDEX idx_post_aggregates_featured_community_published_asc ON public.post_aggregates USING btree (community_id, featured_community DESC, public.reverse_timestamp_sort (published) DESC, post_id DESC); + +CREATE INDEX idx_post_aggregates_featured_community_scaled ON public.post_aggregates USING btree (community_id, featured_community DESC, scaled_rank DESC, published DESC, post_id DESC); + +CREATE INDEX idx_post_aggregates_featured_community_score ON public.post_aggregates USING btree (community_id, featured_community DESC, score DESC, published DESC, post_id DESC); + +CREATE INDEX idx_post_aggregates_featured_local_active ON public.post_aggregates USING btree (featured_local DESC, hot_rank_active DESC, published DESC, post_id DESC); + +CREATE INDEX idx_post_aggregates_featured_local_controversy ON public.post_aggregates USING btree (featured_local DESC, controversy_rank DESC, post_id DESC); + +CREATE INDEX idx_post_aggregates_featured_local_hot ON public.post_aggregates USING btree (featured_local DESC, hot_rank DESC, published DESC, post_id DESC); + +CREATE INDEX idx_post_aggregates_featured_local_most_comments ON public.post_aggregates USING btree (featured_local DESC, comments DESC, published DESC, post_id DESC); + +CREATE INDEX idx_post_aggregates_featured_local_newest_comment_time ON public.post_aggregates USING btree (featured_local DESC, newest_comment_time DESC, post_id DESC); + +CREATE INDEX idx_post_aggregates_featured_local_newest_comment_time_necro ON public.post_aggregates USING btree (featured_local DESC, newest_comment_time_necro DESC, post_id DESC); + +CREATE INDEX idx_post_aggregates_featured_local_published ON public.post_aggregates USING btree (featured_local DESC, published DESC, post_id DESC); + +CREATE INDEX idx_post_aggregates_featured_local_published_asc ON public.post_aggregates USING btree (featured_local DESC, public.reverse_timestamp_sort (published) DESC, post_id DESC); + +CREATE INDEX idx_post_aggregates_featured_local_scaled ON public.post_aggregates USING btree (featured_local DESC, scaled_rank DESC, published DESC, post_id DESC); + +CREATE INDEX idx_post_aggregates_featured_local_score ON public.post_aggregates USING btree (featured_local DESC, score DESC, published DESC, post_id DESC); + From b459949f578114779f5459d93e8eba923c56b85e Mon Sep 17 00:00:00 2001 From: Dessalines Date: Thu, 25 Apr 2024 19:59:24 -0400 Subject: [PATCH 2/3] Version 0.19.4-beta.5 --- Cargo.lock | 26 +++++++++++++------------- Cargo.toml | 24 ++++++++++++------------ crates/utils/translations | 2 +- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a6f217bfd..6d97f9aac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2582,7 +2582,7 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "lemmy_api" -version = "0.19.4-beta.4" +version = "0.19.4-beta.5" dependencies = [ "activitypub_federation", "actix-web", @@ -2611,7 +2611,7 @@ dependencies = [ [[package]] name = "lemmy_api_common" -version = "0.19.4-beta.4" +version = "0.19.4-beta.5" dependencies = [ "activitypub_federation", "actix-web", @@ -2649,7 +2649,7 @@ dependencies = [ [[package]] name = "lemmy_api_crud" -version = "0.19.4-beta.4" +version = "0.19.4-beta.5" dependencies = [ "accept-language", "activitypub_federation", @@ -2672,7 +2672,7 @@ dependencies = [ [[package]] name = "lemmy_apub" -version = "0.19.4-beta.4" +version = "0.19.4-beta.5" dependencies = [ "activitypub_federation", "actix-web", @@ -2710,7 +2710,7 @@ dependencies = [ [[package]] name = "lemmy_db_perf" -version = "0.19.4-beta.4" +version = "0.19.4-beta.5" dependencies = [ "anyhow", "clap", @@ -2725,7 +2725,7 @@ dependencies = [ [[package]] name = "lemmy_db_schema" -version = "0.19.4-beta.4" +version = "0.19.4-beta.5" dependencies = [ "activitypub_federation", "anyhow", @@ -2765,7 +2765,7 @@ dependencies = [ [[package]] name = "lemmy_db_views" -version = "0.19.4-beta.4" +version = "0.19.4-beta.5" dependencies = [ "actix-web", "chrono", @@ -2787,7 +2787,7 @@ dependencies = [ [[package]] name = "lemmy_db_views_actor" -version = "0.19.4-beta.4" +version = "0.19.4-beta.5" dependencies = [ "chrono", "diesel", @@ -2807,7 +2807,7 @@ dependencies = [ [[package]] name = "lemmy_db_views_moderator" -version = "0.19.4-beta.4" +version = "0.19.4-beta.5" dependencies = [ "diesel", "diesel-async", @@ -2819,7 +2819,7 @@ dependencies = [ [[package]] name = "lemmy_federate" -version = "0.19.4-beta.4" +version = "0.19.4-beta.5" dependencies = [ "activitypub_federation", "anyhow", @@ -2842,7 +2842,7 @@ dependencies = [ [[package]] name = "lemmy_routes" -version = "0.19.4-beta.4" +version = "0.19.4-beta.5" dependencies = [ "activitypub_federation", "actix-web", @@ -2867,7 +2867,7 @@ dependencies = [ [[package]] name = "lemmy_server" -version = "0.19.4-beta.4" +version = "0.19.4-beta.5" dependencies = [ "activitypub_federation", "actix-cors", @@ -2910,7 +2910,7 @@ dependencies = [ [[package]] name = "lemmy_utils" -version = "0.19.4-beta.4" +version = "0.19.4-beta.5" dependencies = [ "actix-web", "anyhow", diff --git a/Cargo.toml b/Cargo.toml index b8c029752..05b97924c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace.package] -version = "0.19.4-beta.4" +version = "0.19.4-beta.5" edition = "2021" description = "A link aggregator for the fediverse" license = "AGPL-3.0" @@ -88,17 +88,17 @@ unused_self = "deny" unwrap_used = "deny" [workspace.dependencies] -lemmy_api = { version = "=0.19.4-beta.4", path = "./crates/api" } -lemmy_api_crud = { version = "=0.19.4-beta.4", path = "./crates/api_crud" } -lemmy_apub = { version = "=0.19.4-beta.4", path = "./crates/apub" } -lemmy_utils = { version = "=0.19.4-beta.4", path = "./crates/utils", default-features = false } -lemmy_db_schema = { version = "=0.19.4-beta.4", path = "./crates/db_schema" } -lemmy_api_common = { version = "=0.19.4-beta.4", path = "./crates/api_common" } -lemmy_routes = { version = "=0.19.4-beta.4", path = "./crates/routes" } -lemmy_db_views = { version = "=0.19.4-beta.4", path = "./crates/db_views" } -lemmy_db_views_actor = { version = "=0.19.4-beta.4", path = "./crates/db_views_actor" } -lemmy_db_views_moderator = { version = "=0.19.4-beta.4", path = "./crates/db_views_moderator" } -lemmy_federate = { version = "=0.19.4-beta.4", path = "./crates/federate" } +lemmy_api = { version = "=0.19.4-beta.5", path = "./crates/api" } +lemmy_api_crud = { version = "=0.19.4-beta.5", path = "./crates/api_crud" } +lemmy_apub = { version = "=0.19.4-beta.5", path = "./crates/apub" } +lemmy_utils = { version = "=0.19.4-beta.5", path = "./crates/utils", default-features = false } +lemmy_db_schema = { version = "=0.19.4-beta.5", path = "./crates/db_schema" } +lemmy_api_common = { version = "=0.19.4-beta.5", path = "./crates/api_common" } +lemmy_routes = { version = "=0.19.4-beta.5", path = "./crates/routes" } +lemmy_db_views = { version = "=0.19.4-beta.5", path = "./crates/db_views" } +lemmy_db_views_actor = { version = "=0.19.4-beta.5", path = "./crates/db_views_actor" } +lemmy_db_views_moderator = { version = "=0.19.4-beta.5", path = "./crates/db_views_moderator" } +lemmy_federate = { version = "=0.19.4-beta.5", path = "./crates/federate" } activitypub_federation = { version = "0.5.4", default-features = false, features = [ "actix-web", ] } diff --git a/crates/utils/translations b/crates/utils/translations index c88dd1e3b..866e40566 160000 --- a/crates/utils/translations +++ b/crates/utils/translations @@ -1 +1 @@ -Subproject commit c88dd1e3b36ee1617f1b86acf94c1b7946e97cd4 +Subproject commit 866e4056656755f7b31e20094b46391e6931e3e7 From d3737d44532b43b079a1be13400e3beb7453cac4 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 27 Apr 2024 07:59:58 -0700 Subject: [PATCH 3/3] Optimize actor_language.rs (#4612) * Remove useless transaction in actor_language.rs * Update actor_language.rs * site * community * Update actor_language.rs * Update actor_language.rs * Update actor_language.rs * Update actor_language.rs * Update actor_language.rs --- crates/db_schema/src/impls/actor_language.rs | 115 ++++++++++--------- 1 file changed, 61 insertions(+), 54 deletions(-) diff --git a/crates/db_schema/src/impls/actor_language.rs b/crates/db_schema/src/impls/actor_language.rs index fe21cf003..682be2ed0 100644 --- a/crates/db_schema/src/impls/actor_language.rs +++ b/crates/db_schema/src/impls/actor_language.rs @@ -43,20 +43,13 @@ impl LocalUserLanguage { }; let conn = &mut get_conn(pool).await?; - conn - .build_transaction() - .run(|conn| { - Box::pin(async move { - let langs = local_user_language - .filter(local_user_id.eq(for_local_user_id)) - .order(language_id) - .select(language_id) - .get_results(conn) - .await?; - convert_read_languages(conn, langs).await - }) as _ - }) - .await + let langs = local_user_language + .filter(local_user_id.eq(for_local_user_id)) + .order(language_id) + .select(language_id) + .get_results(conn) + .await?; + convert_read_languages(conn, langs).await } /// Update the user's languages. @@ -90,24 +83,33 @@ impl LocalUserLanguage { .build_transaction() .run(|conn| { Box::pin(async move { - use crate::schema::local_user_language::dsl::{local_user_id, local_user_language}; - // Clear the current user languages - delete(local_user_language.filter(local_user_id.eq(for_local_user_id))) - .execute(conn) - .await?; + use crate::schema::local_user_language::dsl::{ + language_id, + local_user_id, + local_user_language, + }; + // Delete old languages, not including new languages + let delete_old = delete(local_user_language) + .filter(local_user_id.eq(for_local_user_id)) + .filter(language_id.ne_all(&lang_ids)) + .execute(conn); let forms = lang_ids - .into_iter() - .map(|l| LocalUserLanguageForm { + .iter() + .map(|&l| LocalUserLanguageForm { local_user_id: for_local_user_id, language_id: l, }) .collect::>(); - insert_into(local_user_language) + // Insert new languages + let insert_new = insert_into(local_user_language) .values(forms) - .execute(conn) - .await?; + .on_conflict((language_id, local_user_id)) + .do_nothing() + .execute(conn); + + tokio::try_join!(delete_old, insert_new)?; Ok(()) }) as _ }) @@ -159,25 +161,30 @@ impl SiteLanguage { .build_transaction() .run(|conn| { Box::pin(async move { - use crate::schema::site_language::dsl::{site_id, site_language}; + use crate::schema::site_language::dsl::{language_id, site_id, site_language}; - // Clear the current languages - delete(site_language.filter(site_id.eq(for_site_id))) - .execute(conn) - .await?; + // Delete old languages, not including new languages + let delete_old = delete(site_language) + .filter(site_id.eq(for_site_id)) + .filter(language_id.ne_all(&lang_ids)) + .execute(conn); let forms = lang_ids - .into_iter() - .map(|l| SiteLanguageForm { + .iter() + .map(|&l| SiteLanguageForm { site_id: for_site_id, language_id: l, }) .collect::>(); - insert_into(site_language) + // Insert new languages + let insert_new = insert_into(site_language) .values(forms) - .get_result::(conn) - .await?; + .on_conflict((site_id, language_id)) + .do_nothing() + .execute(conn); + + tokio::try_join!(delete_old, insert_new)?; CommunityLanguage::limit_languages(conn, instance_id).await?; @@ -278,8 +285,8 @@ impl CommunityLanguage { } let form = lang_ids - .into_iter() - .map(|language_id| CommunityLanguageForm { + .iter() + .map(|&language_id| CommunityLanguageForm { community_id: for_community_id, language_id, }) @@ -289,25 +296,25 @@ impl CommunityLanguage { .build_transaction() .run(|conn| { Box::pin(async move { - use crate::schema::community_language::dsl::{community_id, community_language}; - use diesel::result::DatabaseErrorKind::UniqueViolation; - // Clear the current languages - delete(community_language.filter(community_id.eq(for_community_id))) - .execute(conn) - .await?; - - let insert_res = insert_into(community_language) + use crate::schema::community_language::dsl::{ + community_id, + community_language, + language_id, + }; + // Delete old languages, not including new languages + let delete_old = delete(community_language) + .filter(community_id.eq(for_community_id)) + .filter(language_id.ne_all(&lang_ids)) + .execute(conn); + + // Insert new languages + let insert_new = insert_into(community_language) .values(form) - .get_result::(conn) - .await; - - if let Err(Error::DatabaseError(UniqueViolation, _info)) = insert_res { - // race condition: this function was probably called simultaneously from another caller. ignore error - // tracing::warn!("unique error: {_info:#?}"); - // _info.constraint_name() should be = "community_language_community_id_language_id_key" - return Ok(()); - } - insert_res?; + .on_conflict((community_id, language_id)) + .do_nothing() + .execute(conn); + + tokio::try_join!(delete_old, insert_new)?; Ok(()) }) as _