perf(retention): only clean up hashtags of evicted objects
Each run scanned the whole hashtags table. Collect the hashtag ids of the objects about to be deleted and check just those.
This commit is contained in:
parent
5067fd6d96
commit
75b158c1d0
2 changed files with 57 additions and 20 deletions
|
|
@ -125,7 +125,6 @@ defmodule Pleroma.Retention do
|
|||
|
||||
# Fewer rows than asked for: everything up to the boundary is done.
|
||||
if length(rows) < budget and after?(boundary, from), do: Cursor.put(cursor, boundary)
|
||||
if stats.contexts > 0, do: delete_unused_hashtags()
|
||||
|
||||
stats
|
||||
end
|
||||
|
|
@ -335,6 +334,17 @@ defmodule Pleroma.Retention do
|
|||
{:ok, stats} =
|
||||
Repo.transaction(
|
||||
fn ->
|
||||
# hashtags_objects rows go with the objects, so collect them first
|
||||
hashtag_ids =
|
||||
from(ho in "hashtags_objects",
|
||||
join: o in Object,
|
||||
on: o.id == ho.object_id,
|
||||
where: fragment("? ->> 'id'", o.data) in ^object_ids,
|
||||
distinct: true,
|
||||
select: ho.hashtag_id
|
||||
)
|
||||
|> Repo.all(timeout: :infinity)
|
||||
|
||||
{objects, deleted_ap_ids} =
|
||||
Object
|
||||
|> where([o], fragment("? ->> 'id'", o.data) in ^object_ids)
|
||||
|
|
@ -367,6 +377,8 @@ defmodule Pleroma.Retention do
|
|||
|> where([a], fragment("? ->> 'type' != 'Flag'", a.data))
|
||||
|> Repo.delete_all(timeout: :infinity)
|
||||
|
||||
delete_unused_hashtags(hashtag_ids)
|
||||
|
||||
%{
|
||||
contexts: length(threads),
|
||||
objects: objects,
|
||||
|
|
@ -398,27 +410,34 @@ defmodule Pleroma.Retention do
|
|||
if estimate > 0, do: estimate, else: Repo.aggregate(Object, :count, timeout: :infinity)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Removes hashtags no longer attached to any object and not followed by anyone.
|
||||
@unused_hashtags """
|
||||
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
|
||||
)
|
||||
"""
|
||||
@spec delete_unused_hashtags() :: :ok
|
||||
def delete_unused_hashtags do
|
||||
Repo.query!(
|
||||
"""
|
||||
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
|
||||
)
|
||||
""",
|
||||
[],
|
||||
timeout: :infinity
|
||||
)
|
||||
|
||||
@doc """
|
||||
Removes hashtags no longer attached to any object and not followed by anyone,
|
||||
either all of them or only those among the given ids.
|
||||
"""
|
||||
@spec delete_unused_hashtags([integer()] | nil) :: :ok
|
||||
def delete_unused_hashtags(ids \\ nil)
|
||||
|
||||
def delete_unused_hashtags([]), do: :ok
|
||||
|
||||
def delete_unused_hashtags(nil) do
|
||||
Repo.query!(@unused_hashtags, [], timeout: :infinity)
|
||||
:ok
|
||||
end
|
||||
|
||||
def delete_unused_hashtags(ids) do
|
||||
Repo.query!(@unused_hashtags <> "AND ht.id = ANY($1)", [ids], timeout: :infinity)
|
||||
:ok
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -488,5 +488,23 @@ defmodule Pleroma.RetentionTest do
|
|||
|
||||
refute Pleroma.Hashtag.get_by_name("lonelytag")
|
||||
end
|
||||
|
||||
test "only cleans up hashtags of the evicted objects", %{old_date: old_date} do
|
||||
remote_user = insert(:user, local: false)
|
||||
local_user = insert(:user)
|
||||
|
||||
old_remote_post(remote_user, old_date, %{status: "#gone #shared #followed"})
|
||||
{:ok, _} = CommonAPI.post(local_user, %{status: "#shared"})
|
||||
{:ok, followed} = Pleroma.Hashtag.get_or_create_by_name("followed")
|
||||
{:ok, _} = Pleroma.User.follow_hashtag(local_user, followed)
|
||||
{:ok, _} = Pleroma.Hashtag.get_or_create_by_name("unrelated")
|
||||
|
||||
assert %{contexts: 1} = Retention.run()
|
||||
|
||||
refute Pleroma.Hashtag.get_by_name("gone")
|
||||
assert Pleroma.Hashtag.get_by_name("shared")
|
||||
assert Pleroma.Hashtag.get_by_name("followed")
|
||||
assert Pleroma.Hashtag.get_by_name("unrelated")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue