Put rich media processing in a Task

This commit is contained in:
FloatingGhost 2022-12-30 20:11:53 +00:00
parent 5d4c291d52
commit bf7ff6a337
5 changed files with 21 additions and 6 deletions

View file

@ -28,7 +28,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
# to fetch the preview. However it should be fine considering # to fetch the preview. However it should be fine considering
# pagination is restricted to 40 activities at a time # pagination is restricted to 40 activities at a time
defp fetch_rich_media_for_activities(activities) do defp fetch_rich_media_for_activities(activities) do
Enum.each(activities, fn activity -> Enum.map(activities, fn activity ->
spawn(fn -> spawn(fn ->
Pleroma.Web.RichMedia.Helpers.fetch_data_for_activity(activity) Pleroma.Web.RichMedia.Helpers.fetch_data_for_activity(activity)
end) end)

View file

@ -15,7 +15,7 @@ def parse(nil), do: {:error, "No URL provided"}
if Pleroma.Config.get(:env) == :test do if Pleroma.Config.get(:env) == :test do
@spec parse(String.t()) :: {:ok, map()} | {:error, any()} @spec parse(String.t()) :: {:ok, map()} | {:error, any()}
def parse(url), do: parse_url(url) def parse(url), do: parse_with_timeout(url)
else else
@spec parse(String.t()) :: {:ok, map()} | {:error, any()} @spec parse(String.t()) :: {:ok, map()} | {:error, any()}
def parse(url) do def parse(url) do
@ -27,7 +27,7 @@ def parse(url) do
defp get_cached_or_parse(url) do defp get_cached_or_parse(url) do
case @cachex.fetch(:rich_media_cache, url, fn -> case @cachex.fetch(:rich_media_cache, url, fn ->
case parse_url(url) do case parse_with_timeout(url) do
{:ok, _} = res -> {:ok, _} = res ->
{:commit, res} {:commit, res}
@ -141,6 +141,21 @@ def parse_url(url) do
end end
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 defp maybe_parse(html) do
Enum.reduce_while(parsers(), %{}, fn parser, acc -> Enum.reduce_while(parsers(), %{}, fn parser, acc ->
case parser.parse(html, acc) do case parser.parse(html, acc) do

View file

@ -326,7 +326,7 @@ test "posting a fake status", %{conn: conn} do
test "fake statuses' preview card is not cached", %{conn: conn} do test "fake statuses' preview card is not cached", %{conn: conn} do
clear_config([:rich_media, :enabled], true) clear_config([:rich_media, :enabled], true)
Tesla.Mock.mock(fn Tesla.Mock.mock_global(fn
%{ %{
method: :get, method: :get,
url: "https://example.com/twitter-card" url: "https://example.com/twitter-card"

View file

@ -12,7 +12,7 @@ defmodule Pleroma.Web.RichMedia.HelpersTest do
import Tesla.Mock import Tesla.Mock
setup do setup do
mock(fn env -> apply(HttpRequestMock, :request, [env]) end) mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
:ok :ok
end end

View file

@ -8,7 +8,7 @@ defmodule Pleroma.Web.RichMedia.ParserTest do
alias Pleroma.Web.RichMedia.Parser alias Pleroma.Web.RichMedia.Parser
setup do setup do
Tesla.Mock.mock(fn Tesla.Mock.mock_global(fn
%{ %{
method: :get, method: :get,
url: "http://example.com/ogp" url: "http://example.com/ogp"