Spin off imports into n oban jobs
authorFloatingGhost <hannah@coffee-and-dreams.uk>
Sun, 27 Nov 2022 21:45:41 +0000 (21:45 +0000)
committerFloatingGhost <hannah@coffee-and-dreams.uk>
Sun, 27 Nov 2022 21:45:41 +0000 (21:45 +0000)
CHANGELOG.md
lib/pleroma/user/import.ex
lib/pleroma/workers/background_worker.ex
test/pleroma/emoji/formatter_test.exs
test/pleroma/user/import_test.exs
test/pleroma/web/pleroma_api/controllers/user_import_controller_test.exs

index 4b7b7e836b579257ccc494cf49434e242b23f0df..b6eb928c6a1d7bd90825315cc139729c5110e480 100644 (file)
@@ -14,6 +14,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - MastoAPI: Accept BooleanLike input on `/api/v1/accounts/:id/follow` (fixes follows with mastodon.py)
 - Relays from akkoma are now off by default
 - NormalizeMarkup MRF is now on by default
+- Follow/Block/Mute imports now spin off into *n* tasks to avoid the oban timeout
 
 ## 2022.11
 
index 60cd18041dc7e927c4ec514163c2e4bbcb6f37a1..95c4ef34ea200a6966b0600cf0fa592925cff4be 100644 (file)
@@ -12,47 +12,32 @@ defmodule Pleroma.User.Import do
   require Logger
 
   @spec perform(atom(), User.t(), list()) :: :ok | list() | {:error, any()}
-  def perform(:mutes_import, %User{} = user, [_ | _] = identifiers) do
-    Enum.map(
-      identifiers,
-      fn identifier ->
-        with {:ok, %User{} = muted_user} <- User.get_or_fetch(identifier),
-             {:ok, _} <- User.mute(user, muted_user) do
-          muted_user
-        else
-          error -> handle_error(:mutes_import, identifier, error)
-        end
-      end
-    )
+  def perform(:mutes_import, %User{} = user, identifier) do
+    with {:ok, %User{} = muted_user} <- User.get_or_fetch(identifier),
+         {:ok, _} <- User.mute(user, muted_user) do
+      muted_user
+    else
+      error -> handle_error(:mutes_import, identifier, error)
+    end
   end
 
-  def perform(:blocks_import, %User{} = blocker, [_ | _] = identifiers) do
-    Enum.map(
-      identifiers,
-      fn identifier ->
-        with {:ok, %User{} = blocked} <- User.get_or_fetch(identifier),
-             {:ok, _block} <- CommonAPI.block(blocker, blocked) do
-          blocked
-        else
-          error -> handle_error(:blocks_import, identifier, error)
-        end
-      end
-    )
+  def perform(:blocks_import, %User{} = blocker, identifier) do
+    with {:ok, %User{} = blocked} <- User.get_or_fetch(identifier),
+         {:ok, _block} <- CommonAPI.block(blocker, blocked) do
+      blocked
+    else
+      error -> handle_error(:blocks_import, identifier, error)
+    end
   end
 
-  def perform(:follow_import, %User{} = follower, [_ | _] = identifiers) do
-    Enum.map(
-      identifiers,
-      fn identifier ->
-        with {:ok, %User{} = followed} <- User.get_or_fetch(identifier),
-             {:ok, follower, followed} <- User.maybe_direct_follow(follower, followed),
-             {:ok, _, _, _} <- CommonAPI.follow(follower, followed) do
-          followed
-        else
-          error -> handle_error(:follow_import, identifier, error)
-        end
-      end
-    )
+  def perform(:follow_import, %User{} = follower, identifier) do
+    with {:ok, %User{} = followed} <- User.get_or_fetch(identifier),
+         {:ok, follower, followed} <- User.maybe_direct_follow(follower, followed),
+         {:ok, _, _, _} <- CommonAPI.follow(follower, followed) do
+      followed
+    else
+      error -> handle_error(:follow_import, identifier, error)
+    end
   end
 
   def perform(_, _, _), do: :ok
@@ -62,24 +47,24 @@ defmodule Pleroma.User.Import do
     error
   end
 
-  def blocks_import(%User{} = blocker, [_ | _] = identifiers) do
-    BackgroundWorker.enqueue(
-      "blocks_import",
-      %{"user_id" => blocker.id, "identifiers" => identifiers}
+  defp enqueue_many(op, user, identifiers) do
+    Enum.map(
+      identifiers,
+      fn identifier ->
+        BackgroundWorker.enqueue(op, %{"user_id" => user.id, "identifier" => identifier})
+      end
     )
   end
 
+  def blocks_import(%User{} = blocker, [_ | _] = identifiers) do
+    enqueue_many("blocks_import", blocker, identifiers)
+  end
+
   def follow_import(%User{} = follower, [_ | _] = identifiers) do
-    BackgroundWorker.enqueue(
-      "follow_import",
-      %{"user_id" => follower.id, "identifiers" => identifiers}
-    )
+    enqueue_many("follow_import", follower, identifiers)
   end
 
   def mutes_import(%User{} = user, [_ | _] = identifiers) do
-    BackgroundWorker.enqueue(
-      "mutes_import",
-      %{"user_id" => user.id, "identifiers" => identifiers}
-    )
+    enqueue_many("mutes_import", user, identifiers)
   end
 end
index 4db077232a850eac077dd98793496f217e2c8f36..9bd9899db59e4a741c1808c211fba5e06c370c7f 100644 (file)
@@ -25,10 +25,10 @@ defmodule Pleroma.Workers.BackgroundWorker do
     User.perform(:force_password_reset, user)
   end
 
-  def perform(%Job{args: %{"op" => op, "user_id" => user_id, "identifiers" => identifiers}})
+  def perform(%Job{args: %{"op" => op, "user_id" => user_id, "identifier" => identifier}})
       when op in ["blocks_import", "follow_import", "mutes_import"] do
     user = User.get_cached_by_id(user_id)
-    {:ok, User.Import.perform(String.to_atom(op), user, identifiers)}
+    {:ok, User.Import.perform(String.to_atom(op), user, identifier)}
   end
 
   def perform(%Job{
index 3942f609fd0e85d65cc8d0fef1061aabeae82287..eafdd5a435eabdea744b5c4983dd0d552048043b 100644 (file)
@@ -11,7 +11,7 @@ defmodule Pleroma.Emoji.FormatterTest do
       text = "I love :firefox:"
 
       expected_result =
-        "I love <img class=\"emoji\" alt=\"firefox\" title=\"firefox\" src=\"/emoji/Firefox.gif\"/>"
+        "I love <img alt=\"firefox\" title=\"firefox\" src=\"/emoji/Firefox.gif\"/>"
 
       assert Formatter.emojify(text) == expected_result
     end
index 2be2ee75b1edf3ddc07a1f90ffc8619b71ca4a44..19d022529412525f2288771c07ffd22b91eedbfe 100644 (file)
@@ -25,11 +25,14 @@ defmodule Pleroma.User.ImportTest do
         user3.nickname
       ]
 
-      {:ok, job} = User.Import.follow_import(user1, identifiers)
+      [{:ok, job1}, {:ok, job2}] = User.Import.follow_import(user1, identifiers)
+
+      assert {:ok, result} = ObanHelpers.perform(job1)
+      assert result == refresh_record(user2)
+
+      assert {:ok, result} = ObanHelpers.perform(job2)
+      assert result == refresh_record(user3)
 
-      assert {:ok, result} = ObanHelpers.perform(job)
-      assert is_list(result)
-      assert result == [refresh_record(user2), refresh_record(user3)]
       assert User.following?(user1, user2)
       assert User.following?(user1, user3)
     end
@@ -44,11 +47,14 @@ defmodule Pleroma.User.ImportTest do
         user3.nickname
       ]
 
-      {:ok, job} = User.Import.blocks_import(user1, identifiers)
+      [{:ok, job1}, {:ok, job2}] = User.Import.blocks_import(user1, identifiers)
+
+      assert {:ok, result} = ObanHelpers.perform(job1)
+      assert result == user2
+
+      assert {:ok, result} = ObanHelpers.perform(job2)
+      assert result == user3
 
-      assert {:ok, result} = ObanHelpers.perform(job)
-      assert is_list(result)
-      assert result == [user2, user3]
       assert User.blocks?(user1, user2)
       assert User.blocks?(user1, user3)
     end
@@ -63,11 +69,14 @@ defmodule Pleroma.User.ImportTest do
         user3.nickname
       ]
 
-      {:ok, job} = User.Import.mutes_import(user1, identifiers)
+      [{:ok, job1}, {:ok, job2}] = User.Import.mutes_import(user1, identifiers)
+
+      assert {:ok, result} = ObanHelpers.perform(job1)
+      assert result == user2
+
+      assert {:ok, result} = ObanHelpers.perform(job2)
+      assert result == user3
 
-      assert {:ok, result} = ObanHelpers.perform(job)
-      assert is_list(result)
-      assert result == [user2, user3]
       assert User.mutes?(user1, user2)
       assert User.mutes?(user1, user3)
     end
index d977bc3a22903a4104b75cb15a40770f6bed9bc6..f9175058d01c28f70add7b0bc688f18a45d8d1ec 100644 (file)
@@ -47,8 +47,8 @@ defmodule Pleroma.Web.PleromaAPI.UserImportControllerTest do
                  |> json_response_and_validate_schema(200)
 
         assert [{:ok, job_result}] = ObanHelpers.perform_all()
-        assert job_result == [refresh_record(user2)]
-        assert [%Pleroma.User{follower_count: 1}] = job_result
+        assert job_result == refresh_record(user2)
+        assert %Pleroma.User{follower_count: 1} = job_result
       end
     end
 
@@ -108,8 +108,8 @@ defmodule Pleroma.Web.PleromaAPI.UserImportControllerTest do
                |> post("/api/pleroma/follow_import", %{"list" => identifiers})
                |> json_response_and_validate_schema(200)
 
-      assert [{:ok, job_result}] = ObanHelpers.perform_all()
-      assert job_result == Enum.map(users, &refresh_record/1)
+      job_results = Enum.map(ObanHelpers.perform_all(), fn {:ok, result} -> result end)
+      assert job_results == Enum.map(users, &refresh_record/1)
     end
   end
 
@@ -141,8 +141,8 @@ defmodule Pleroma.Web.PleromaAPI.UserImportControllerTest do
                  })
                  |> json_response_and_validate_schema(200)
 
-        assert [{:ok, job_result}] = ObanHelpers.perform_all()
-        assert job_result == users
+        job_results = Enum.map(ObanHelpers.perform_all(), fn {:ok, result} -> result end)
+        assert job_results == users
       end
     end
 
@@ -165,8 +165,8 @@ defmodule Pleroma.Web.PleromaAPI.UserImportControllerTest do
                |> post("/api/pleroma/blocks_import", %{"list" => identifiers})
                |> json_response_and_validate_schema(200)
 
-      assert [{:ok, job_result}] = ObanHelpers.perform_all()
-      assert job_result == users
+      job_results = Enum.map(ObanHelpers.perform_all(), fn {:ok, result} -> result end)
+      assert job_results == users
     end
   end
 
@@ -183,12 +183,12 @@ defmodule Pleroma.Web.PleromaAPI.UserImportControllerTest do
                |> post("/api/pleroma/mutes_import", %{"list" => "#{user2.ap_id}"})
                |> json_response_and_validate_schema(200)
 
-      assert [{:ok, job_result}] = ObanHelpers.perform_all()
-      assert job_result == [user2]
+      job_results = Enum.map(ObanHelpers.perform_all(), fn {:ok, result} -> result end)
+      assert job_results == [user2]
       assert Pleroma.User.mutes?(user, user2)
     end
 
-    test "it imports mutes users from file", %{user: user, conn: conn} do
+    test "it imports muted users from file", %{user: user, conn: conn} do
       users = [user2, user3] = insert_list(2, :user)
 
       with_mocks([
@@ -202,8 +202,8 @@ defmodule Pleroma.Web.PleromaAPI.UserImportControllerTest do
                  })
                  |> json_response_and_validate_schema(200)
 
-        assert [{:ok, job_result}] = ObanHelpers.perform_all()
-        assert job_result == users
+        job_results = Enum.map(ObanHelpers.perform_all(), fn {:ok, result} -> result end)
+        assert job_results == users
         assert Enum.all?(users, &Pleroma.User.mutes?(user, &1))
       end
     end
@@ -227,8 +227,8 @@ defmodule Pleroma.Web.PleromaAPI.UserImportControllerTest do
                |> post("/api/pleroma/mutes_import", %{"list" => identifiers})
                |> json_response_and_validate_schema(200)
 
-      assert [{:ok, job_result}] = ObanHelpers.perform_all()
-      assert job_result == users
+      job_results = Enum.map(ObanHelpers.perform_all(), fn {:ok, result} -> result end)
+      assert job_results == users
       assert Enum.all?(users, &Pleroma.User.mutes?(user, &1))
     end
   end