Put rich media processing in a Task
[akkoma] / lib / pleroma / web / rich_media / parser.ex
index d6b54943b40ee2ee0289ef648a1f2cdf4a79a3ba..1d4cad0100e2ebcb8092b96555f5b5dfa938fa70 100644 (file)
@@ -15,7 +15,7 @@ defmodule Pleroma.Web.RichMedia.Parser do
 
   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 @@ defmodule Pleroma.Web.RichMedia.Parser 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 @@ defmodule Pleroma.Web.RichMedia.Parser 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