diff --git a/lib/mix/tasks/pleroma/database.ex b/lib/mix/tasks/pleroma/database.ex index 396536827..6f4c3b3c4 100644 --- a/lib/mix/tasks/pleroma/database.ex +++ b/lib/mix/tasks/pleroma/database.ex @@ -113,36 +113,13 @@ defmodule Mix.Tasks.Pleroma.Database do Logger.info(log_message) if Keyword.get(options, :keep_threads) do - # We want to delete objects from threads where - # 1. the newest post is still old - # 2. none of the activities is local - # 3. none of the activities is bookmarked - # 4. optionally none of the posts is non-public + # Delete objects from threads that nobody local interacted with and that + # have been quiet for longer than the retention period, see Pleroma.Retention. deletable_context = - if Keyword.get(options, :keep_non_public) do - Pleroma.Activity - |> join(:left, [a], b in Pleroma.Bookmark, on: a.id == b.activity_id) - |> group_by([a], fragment("? ->> 'context'::text", a.data)) - |> having( - [a], - not fragment( - # Posts (checked on Create Activity) is non-public - "bool_or((not(?->'to' \\? ? OR ?->'cc' \\? ?)) and ? ->> 'type' = 'Create')", - a.data, - ^Pleroma.Constants.as_public(), - a.data, - ^Pleroma.Constants.as_public(), - a.data - ) - ) - else - Pleroma.Activity - |> join(:left, [a], b in Pleroma.Bookmark, on: a.id == b.activity_id) - |> group_by([a], fragment("? ->> 'context'::text", a.data)) - end - |> having([a], max(a.updated_at) < ^time_deadline) - |> having([a], not fragment("bool_or(?)", a.local)) - |> having([_, b], fragment("max(?::text) is null", b.id)) + time_deadline + |> Pleroma.Retention.evictable_contexts_query( + keep_non_public: Keyword.get(options, :keep_non_public) + ) |> select([a], fragment("? ->> 'context'::text", a.data)) Pleroma.Object @@ -222,18 +199,7 @@ defmodule Mix.Tasks.Pleroma.Database do |> Repo.query([], timeout: :infinity) end - """ - DELETE FROM hashtags AS ht - WHERE NOT EXISTS ( - SELECT 1 FROM hashtags_objects hto - WHERE ht.id = hto.hashtag_id - ) - AND NOT EXISTS ( - SELECT 1 FROM user_follows_hashtag ufh - WHERE ht.id = ufh.hashtag_id - ) - """ - |> Repo.query() + Pleroma.Retention.delete_unused_hashtags() if Keyword.get(options, :vacuum) do Maintenance.vacuum("full") diff --git a/test/mix/tasks/pleroma/database_test.exs b/test/mix/tasks/pleroma/database_test.exs index 0f38891b4..b3f25130c 100644 --- a/test/mix/tasks/pleroma/database_test.exs +++ b/test/mix/tasks/pleroma/database_test.exs @@ -200,6 +200,23 @@ defmodule Mix.Tasks.Pleroma.DatabaseTest do refute Object.get_by_ap_id(old_remote_post2_id) end + test "with the --keep-threads option it keeps old threads that mentioned a local user", %{ + old_insert_date: old_insert_date + } do + remote_user = insert(:user, local: false) + local_user = insert(:user) + + {:ok, activity} = CommonAPI.post(remote_user, %{status: "hey @#{local_user.nickname}"}) + + activity + |> Ecto.Changeset.change(%{local: false, updated_at: old_insert_date}) + |> Repo.update!() + + Mix.Tasks.Pleroma.Database.run(["prune_objects", "--keep-threads"]) + + assert Object.get_by_ap_id(activity.data["object"]) + end + test "with the --keep-threads option it still keeps non-old threads even with no local interactions" do remote_user = insert(:user, local: false) remote_user2 = insert(:user, local: false)