fix(retention): see local reactions of the legacy EmojiReaction type

Older data stores emoji reactions as EmojiReaction. The per-thread check
only looked at EmojiReact, so a thread whose only local interaction was
such a reaction was evicted.
This commit is contained in:
Lain Soykaf 2026-09-23 15:43:02 +04:00
commit 5e425ce9f5
No known key found for this signature in database
2 changed files with 33 additions and 5 deletions

View file

@ -81,11 +81,12 @@ defmodule Pleroma.Retention do
# Invariant: every type that *adopts* another activity's context must be
# listed, or its thread's local pins become invisible to the walk and the
# thread gets evicted. Today only Create, Announce, Like and EmojiReact do
# (see Pleroma.Web.ActivityPub.Builder). The others carry a context of
# their own (or did in older data) and are listed so they get evicted
# rather than left behind. The regression test "keeps threads pinned by
# each local interaction type" guards this.
@context_types ~w(Create Announce Like EmojiReact Update Delete Undo Flag Listen Move)
# (see Pleroma.Web.ActivityPub.Builder), and EmojiReaction, the name
# EmojiReact had in older data. The others carry a context of their own (or
# did in older data) and are listed so they get evicted rather than left
# behind. The regression test "keeps threads pinned by each local
# interaction type" guards this.
@context_types ~w(Create Announce Like EmojiReact EmojiReaction Update Delete Undo Flag Listen Move)
@doc """
Runs one eviction batch using the `:retention` config and returns what was removed.

View file

@ -217,6 +217,33 @@ defmodule Pleroma.RetentionTest do
assert Activity.get_by_id(post.id)
end
test "keeps threads pinned by a local reaction of the legacy EmojiReaction type", %{
old_date: old_date
} do
remote_user = insert(:user, local: false)
local_user = insert(:user)
post = old_remote_post(remote_user, old_date)
Repo.insert!(%Activity{
data: %{
"id" => "#{Pleroma.Web.Endpoint.url()}/activities/#{Ecto.UUID.generate()}",
"type" => "EmojiReaction",
"actor" => local_user.ap_id,
"object" => post.data["object"],
"content" => "👍",
"context" => post.data["context"]
},
local: true,
actor: local_user.ap_id,
recipients: [remote_user.ap_id]
})
|> make_old(old_date)
assert %{contexts: 0} = Retention.run()
assert Object.get_by_ap_id(post.data["object"])
end
test "keeps an old remote post that was reported", %{old_date: old_date} do
remote_user = insert(:user, local: false)
local_user = insert(:user)