From 0b19625bfba0ef4a9a4c97bada981dfb5c1edbf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9l=C3=A8ne?= Date: Sun, 11 Sep 2022 04:54:04 +0200 Subject: [PATCH] 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. --- lib/pleroma/object.ex | 15 ++++++++++----- lib/pleroma/web/activity_pub/views/object_view.ex | 4 ++-- .../web/activity_pub/views/object_view_test.exs | 14 ++++++++++++++ 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/lib/pleroma/object.ex b/lib/pleroma/object.ex index fee3f1842..38accae5d 100644 --- a/lib/pleroma/object.ex +++ b/lib/pleroma/object.ex @@ -144,7 +144,7 @@ defp warn_on_no_object_preloaded(ap_id) do Logger.debug("Backtrace: #{inspect(Process.info(:erlang.self(), :current_stacktrace))}") 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. # Use this whenever possible, especially when walking graphs in an O(N) loop! @@ -172,10 +172,15 @@ def normalize(%Activity{data: %{"object" => ap_id}}, options) do def normalize(%{"id" => ap_id}, options), do: normalize(ap_id, options) def normalize(ap_id, options) when is_binary(ap_id) do - if Keyword.get(options, :fetch) do - Fetcher.fetch_object_from_id!(ap_id, options) - else - get_cached_by_ap_id(ap_id) + cond do + Keyword.get(options, :id_only) -> + ap_id + + Keyword.get(options, :fetch) -> + Fetcher.fetch_object_from_id!(ap_id, options) + + true -> + get_cached_by_ap_id(ap_id) end end diff --git a/lib/pleroma/web/activity_pub/views/object_view.ex b/lib/pleroma/web/activity_pub/views/object_view.ex index f848aba3a..63caa915c 100644 --- a/lib/pleroma/web/activity_pub/views/object_view.ex +++ b/lib/pleroma/web/activity_pub/views/object_view.ex @@ -29,11 +29,11 @@ def render("object.json", %{object: %Activity{data: %{"type" => activity_type}} def render("object.json", %{object: %Activity{} = activity}) do base = Pleroma.Web.ActivityPub.Utils.make_json_ld_header() - object = Object.normalize(activity, fetch: false) + object_id = Object.normalize(activity, id_only: true) additional = Transmogrifier.prepare_object(activity.data) - |> Map.put("object", object.data["id"]) + |> Map.put("object", object_id) Map.merge(base, additional) end diff --git a/test/pleroma/web/activity_pub/views/object_view_test.exs b/test/pleroma/web/activity_pub/views/object_view_test.exs index 48a4b47c4..d94878e31 100644 --- a/test/pleroma/web/activity_pub/views/object_view_test.exs +++ b/test/pleroma/web/activity_pub/views/object_view_test.exs @@ -81,4 +81,18 @@ test "renders an announce activity" do assert result["object"] == object.data["id"] assert result["type"] == "Announce" 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