From f49e9e6d4cb7cfdd0c2fbb2ea74c82a7ec7d13e4 Mon Sep 17 00:00:00 2001 From: ilja Date: Sun, 21 May 2023 13:02:28 +0200 Subject: [PATCH] Clean up bookmarks after prune_objects When doing prune_objects, it's possible that bookmarked objects are deleted. This gave problems when fetching the bookmark TL. Here we clean up the bookmarks during pruning in the case were it's possible that bookmarked objects are deleted. --- lib/mix/tasks/pleroma/database.ex | 15 +++++++++++++++ test/mix/tasks/pleroma/database_test.exs | 24 ++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/lib/mix/tasks/pleroma/database.ex b/lib/mix/tasks/pleroma/database.ex index 726a22d41..55d1c8ddc 100644 --- a/lib/mix/tasks/pleroma/database.ex +++ b/lib/mix/tasks/pleroma/database.ex @@ -171,6 +171,21 @@ def run(["prune_objects" | args]) do end |> Repo.delete_all(timeout: :infinity) + if !Keyword.get(options, :keep_threads) do + # Without the --keep-threads option, it's possible that bookmarked + # objects have been deleted. We remove the corresponding bookmarks. + """ + delete from public.bookmarks + where id in ( + select b.id from public.bookmarks b + left join public.activities a on b.activity_id = a.id + left join public.objects o on a."data" ->> 'object' = o.data ->> 'id' + where o.id is null + ) + """ + |> Repo.query([], timeout: :infinity) + end + if Keyword.get(options, :prune_orphaned_activities) do # Prune activities who link to a single object """ diff --git a/test/mix/tasks/pleroma/database_test.exs b/test/mix/tasks/pleroma/database_test.exs index 21c365412..40c5fd402 100644 --- a/test/mix/tasks/pleroma/database_test.exs +++ b/test/mix/tasks/pleroma/database_test.exs @@ -7,6 +7,7 @@ defmodule Mix.Tasks.Pleroma.DatabaseTest do use Oban.Testing, repo: Pleroma.Repo alias Pleroma.Activity + alias Pleroma.Bookmark alias Pleroma.Object alias Pleroma.Repo alias Pleroma.User @@ -87,6 +88,29 @@ test "it prunes old objects from the database", %{old_insert_date: old_insert_da refute Object.get_by_id(note_remote_non_public_id) end + test "it cleans up bookmarks", %{old_insert_date: old_insert_date} do + user = insert(:user) + {:ok, old_object_activity} = CommonAPI.post(user, %{status: "yadayada"}) + + Repo.one(Object) + |> Ecto.Changeset.change(%{updated_at: old_insert_date}) + |> Repo.update!() + + {:ok, new_object_activity} = CommonAPI.post(user, %{status: "yadayada"}) + + {:ok, _} = Bookmark.create(user.id, old_object_activity.id) + {:ok, _} = Bookmark.create(user.id, new_object_activity.id) + + assert length(Repo.all(Object)) == 2 + assert length(Repo.all(Bookmark)) == 2 + + Mix.Tasks.Pleroma.Database.run(["prune_objects"]) + + assert length(Repo.all(Object)) == 1 + assert length(Repo.all(Bookmark)) == 1 + refute Bookmark.get(user.id, old_object_activity.id) + end + test "with the --keep-non-public option it still keeps non-public posts even if they are not local", %{old_insert_date: old_insert_date} do insert(:note)