From bf7ff6a337a6a329524d3607b5ac2b4caa2df93a Mon Sep 17 00:00:00 2001 From: FloatingGhost Date: Fri, 30 Dec 2022 20:11:53 +0000 Subject: [PATCH] Put rich media processing in a Task --- .../web/mastodon_api/views/status_view.ex | 2 +- lib/pleroma/web/rich_media/parser.ex | 19 +++++++++++++++++-- .../controllers/status_controller_test.exs | 2 +- test/pleroma/web/rich_media/helpers_test.exs | 2 +- test/pleroma/web/rich_media/parser_test.exs | 2 +- 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex index cc58f803e..8fbf9b6d9 100644 --- a/lib/pleroma/web/mastodon_api/views/status_view.ex +++ b/lib/pleroma/web/mastodon_api/views/status_view.ex @@ -28,7 +28,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do # to fetch the preview. However it should be fine considering # pagination is restricted to 40 activities at a time defp fetch_rich_media_for_activities(activities) do - Enum.each(activities, fn activity -> + Enum.map(activities, fn activity -> spawn(fn -> Pleroma.Web.RichMedia.Helpers.fetch_data_for_activity(activity) end) diff --git a/lib/pleroma/web/rich_media/parser.ex b/lib/pleroma/web/rich_media/parser.ex index d6b54943b..1d4cad010 100644 --- a/lib/pleroma/web/rich_media/parser.ex +++ b/lib/pleroma/web/rich_media/parser.ex @@ -15,7 +15,7 @@ def parse(nil), do: {:error, "No URL provided"} if Pleroma.Config.get(:env) == :test do @spec parse(String.t()) :: {:ok, map()} | {:error, any()} - def parse(url), do: parse_url(url) + def parse(url), do: parse_with_timeout(url) else @spec parse(String.t()) :: {:ok, map()} | {:error, any()} def parse(url) do @@ -27,7 +27,7 @@ def parse(url) do defp get_cached_or_parse(url) do case @cachex.fetch(:rich_media_cache, url, fn -> - case parse_url(url) do + case parse_with_timeout(url) do {:ok, _} = res -> {:commit, res} @@ -141,6 +141,21 @@ def parse_url(url) do end end + def parse_with_timeout(url) do + try do + task = + Task.Supervisor.async_nolink(Pleroma.TaskSupervisor, fn -> + parse_url(url) + end) + + Task.await(task, 5000) + catch + :exit, {:timeout, _} -> + Logger.warn("Timeout while fetching rich media for #{url}") + {:error, :timeout} + end + end + defp maybe_parse(html) do Enum.reduce_while(parsers(), %{}, fn parser, acc -> case parser.parse(html, acc) do diff --git a/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs index d76db0c0d..7931d1d69 100644 --- a/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs +++ b/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs @@ -326,7 +326,7 @@ test "posting a fake status", %{conn: conn} do test "fake statuses' preview card is not cached", %{conn: conn} do clear_config([:rich_media, :enabled], true) - Tesla.Mock.mock(fn + Tesla.Mock.mock_global(fn %{ method: :get, url: "https://example.com/twitter-card" diff --git a/test/pleroma/web/rich_media/helpers_test.exs b/test/pleroma/web/rich_media/helpers_test.exs index 689854fb6..c6c3ffd6c 100644 --- a/test/pleroma/web/rich_media/helpers_test.exs +++ b/test/pleroma/web/rich_media/helpers_test.exs @@ -12,7 +12,7 @@ defmodule Pleroma.Web.RichMedia.HelpersTest do import Tesla.Mock setup do - mock(fn env -> apply(HttpRequestMock, :request, [env]) end) + mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) :ok end diff --git a/test/pleroma/web/rich_media/parser_test.exs b/test/pleroma/web/rich_media/parser_test.exs index 2fe7f1b0b..b6444ac82 100644 --- a/test/pleroma/web/rich_media/parser_test.exs +++ b/test/pleroma/web/rich_media/parser_test.exs @@ -8,7 +8,7 @@ defmodule Pleroma.Web.RichMedia.ParserTest do alias Pleroma.Web.RichMedia.Parser setup do - Tesla.Mock.mock(fn + Tesla.Mock.mock_global(fn %{ method: :get, url: "http://example.com/ogp"