ObjectView: do not fetch an object for its ID

Non-Create/Listen activities had their associated object field
normalized and fetched, but only to use their `id` field, which is both
slow and redundant. This also failed on Undo activities, which delete
the associated object/activity in database.

Undo activities will now render properly and database loads should
improve ever so slightly.
This commit is contained in:
Hélène 2022-09-11 04:54:04 +02:00 committed by FloatingGhost
parent dfba26a09c
commit e88f36f72b
3 changed files with 26 additions and 7 deletions

View file

@ -145,7 +145,7 @@ defp warn_on_no_object_preloaded(ap_id) do
Logger.debug("Backtrace: #{inspect(Process.info(:erlang.self(), :current_stacktrace))}") Logger.debug("Backtrace: #{inspect(Process.info(:erlang.self(), :current_stacktrace))}")
end end
def normalize(_, options \\ [fetch: false]) def normalize(_, options \\ [fetch: false, id_only: false])
# If we pass an Activity to Object.normalize(), we can try to use the preloaded object. # If we pass an Activity to Object.normalize(), we can try to use the preloaded object.
# Use this whenever possible, especially when walking graphs in an O(N) loop! # Use this whenever possible, especially when walking graphs in an O(N) loop!
@ -173,10 +173,15 @@ def normalize(%Activity{data: %{"object" => ap_id}}, options) do
def normalize(%{"id" => ap_id}, options), do: normalize(ap_id, options) def normalize(%{"id" => ap_id}, options), do: normalize(ap_id, options)
def normalize(ap_id, options) when is_binary(ap_id) do def normalize(ap_id, options) when is_binary(ap_id) do
if Keyword.get(options, :fetch) do cond do
Fetcher.fetch_object_from_id!(ap_id, options) Keyword.get(options, :id_only) ->
else ap_id
get_cached_by_ap_id(ap_id)
Keyword.get(options, :fetch) ->
Fetcher.fetch_object_from_id!(ap_id, options)
true ->
get_cached_by_ap_id(ap_id)
end end
end end

View file

@ -29,11 +29,11 @@ def render("object.json", %{object: %Activity{data: %{"type" => activity_type}}
def render("object.json", %{object: %Activity{} = activity}) do def render("object.json", %{object: %Activity{} = activity}) do
base = Pleroma.Web.ActivityPub.Utils.make_json_ld_header() base = Pleroma.Web.ActivityPub.Utils.make_json_ld_header()
object = Object.normalize(activity, fetch: false) object_id = Object.normalize(activity, id_only: true)
additional = additional =
Transmogrifier.prepare_object(activity.data) Transmogrifier.prepare_object(activity.data)
|> Map.put("object", object.data["id"]) |> Map.put("object", object_id)
Map.merge(base, additional) Map.merge(base, additional)
end end

View file

@ -81,4 +81,18 @@ test "renders an announce activity" do
assert result["object"] == object.data["id"] assert result["object"] == object.data["id"]
assert result["type"] == "Announce" assert result["type"] == "Announce"
end end
test "renders an undo announce activity" do
note = insert(:note_activity)
user = insert(:user)
{:ok, announce} = CommonAPI.repeat(note.id, user)
{:ok, undo} = CommonAPI.unrepeat(note.id, user)
result = ObjectView.render("object.json", %{object: undo})
assert result["id"] == undo.data["id"]
assert result["object"] == announce.data["id"]
assert result["type"] == "Undo"
end
end end