[#1335] User AP ID relations fetching performance optimizations.
authorIvan Tashkinov <ivantashkinov@gmail.com>
Wed, 20 Nov 2019 09:19:07 +0000 (12:19 +0300)
committerIvan Tashkinov <ivantashkinov@gmail.com>
Wed, 20 Nov 2019 09:19:07 +0000 (12:19 +0300)
lib/pleroma/notification.ex
lib/pleroma/user.ex
lib/pleroma/web/activity_pub/activity_pub.ex
lib/pleroma/web/streamer/worker.ex

index 15b3337f476c587d126adbccf4ad113592e16afb..d4b6eb3b8c2ba72fae9900058af353e6d36cc166 100644 (file)
@@ -21,6 +21,8 @@ defmodule Pleroma.Notification do
 
   @type t :: %__MODULE__{}
 
+  @include_muted_option :with_muted
+
   schema "notifications" do
     field(:seen, :boolean, default: false)
     belongs_to(:user, User, type: FlakeId.Ecto.CompatType)
@@ -34,7 +36,25 @@ defmodule Pleroma.Notification do
     |> cast(attrs, [:seen])
   end
 
-  def for_user_query(user, opts \\ []) do
+  defp for_user_query_ap_id_opts(user, opts) do
+    ap_id_relations =
+      [:block] ++
+        if opts[@include_muted_option], do: [], else: [:notification_mute]
+
+    preloaded_ap_ids = User.outgoing_relations_ap_ids(user, ap_id_relations)
+
+    exclude_blocked_opts = Map.merge(%{blocked_users_ap_ids: preloaded_ap_ids[:block]}, opts)
+
+    exclude_notification_muted_opts =
+      Map.merge(%{notification_muted_users_ap_ids: preloaded_ap_ids[:notification_mute]}, opts)
+
+    {exclude_blocked_opts, exclude_notification_muted_opts}
+  end
+
+  def for_user_query(user, opts \\ %{}) do
+    {exclude_blocked_opts, exclude_notification_muted_opts} =
+      for_user_query_ap_id_opts(user, opts)
+
     Notification
     |> where(user_id: ^user.id)
     |> where(
@@ -54,13 +74,13 @@ defmodule Pleroma.Notification do
         )
     )
     |> preload([n, a, o], activity: {a, object: o})
-    |> exclude_muted(user, opts)
-    |> exclude_blocked(user)
+    |> exclude_notification_muted(user, exclude_notification_muted_opts)
+    |> exclude_blocked(user, exclude_blocked_opts)
     |> exclude_visibility(opts)
   end
 
-  defp exclude_blocked(query, user) do
-    blocked_ap_ids = User.blocked_users_ap_ids(user)
+  defp exclude_blocked(query, user, opts) do
+    blocked_ap_ids = opts[:blocked_users_ap_ids] || User.blocked_users_ap_ids(user)
 
     query
     |> where([n, a], a.actor not in ^blocked_ap_ids)
@@ -70,12 +90,13 @@ defmodule Pleroma.Notification do
     )
   end
 
-  defp exclude_muted(query, _, %{with_muted: true}) do
+  defp exclude_notification_muted(query, _, %{@include_muted_option => true}) do
     query
   end
 
-  defp exclude_muted(query, user, _opts) do
-    notification_muted_ap_ids = User.notification_muted_users_ap_ids(user)
+  defp exclude_notification_muted(query, user, opts) do
+    notification_muted_ap_ids =
+      opts[:notification_muted_users_ap_ids] || User.notification_muted_users_ap_ids(user)
 
     query
     |> where([n, a], a.actor not in ^notification_muted_ap_ids)
index 615f1b72575e7b51996d7f3096b1333fe4aa7cd8..4b53dce13e88e16de430f0587733abd783565fba 100644 (file)
@@ -1158,11 +1158,14 @@ defmodule Pleroma.User do
   end
 
   @doc """
-  Returns map of related AP IDs list by relation type.
-  E.g. `related_ap_ids(user, [:block])` -> `%{block: ["https://some.site/users/userapid"]}`
+  Returns map of outgoing (blocked, muted etc.) relations' user AP IDs by relation type.
+  E.g. `outgoing_relations_ap_ids(user, [:block])` -> `%{block: ["https://some.site/users/userapid"]}`
   """
-  @spec related_ap_ids(User.t(), list(atom())) :: %{atom() => list(String.t())}
-  def related_ap_ids(%User{} = user, relationship_types) when is_list(relationship_types) do
+  @spec outgoing_relations_ap_ids(User.t(), list(atom())) :: %{atom() => list(String.t())}
+  def outgoing_relations_ap_ids(_, []), do: %{}
+
+  def outgoing_relations_ap_ids(%User{} = user, relationship_types)
+      when is_list(relationship_types) do
     db_result =
       user
       |> assoc(:outgoing_relationships)
index 61b7f9280193d2b198df501181d48bc5ba0c2324..b24139117eccd61510bd5e2b28671d2ab8ad113e 100644 (file)
@@ -884,7 +884,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
   defp restrict_muted(query, %{"with_muted" => val}) when val in [true, "true", "1"], do: query
 
   defp restrict_muted(query, %{"muting_user" => %User{} = user} = opts) do
-    mutes = opts["muted_ap_ids"] || User.muted_users_ap_ids(user)
+    mutes = opts["muted_users_ap_ids"] || User.muted_users_ap_ids(user)
 
     query =
       from([activity] in query,
@@ -902,7 +902,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
   defp restrict_muted(query, _), do: query
 
   defp restrict_blocked(query, %{"blocking_user" => %User{} = user} = opts) do
-    blocked_ap_ids = opts["blocked_ap_ids"] || User.blocked_users_ap_ids(user)
+    blocked_ap_ids = opts["blocked_users_ap_ids"] || User.blocked_users_ap_ids(user)
     domain_blocks = user.domain_blocks || []
 
     query =
@@ -944,8 +944,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
 
   defp restrict_pinned(query, _), do: query
 
-  defp restrict_muted_reblogs(query, %{"muting_user" => %User{} = user}) do
-    muted_reblogs = User.reblog_muted_users_ap_ids(user)
+  defp restrict_muted_reblogs(query, %{"muting_user" => %User{} = user} = opts) do
+    muted_reblogs = opts["reblog_muted_users_ap_ids"] || User.reblog_muted_users_ap_ids(user)
 
     from(
       activity in query,
@@ -1012,7 +1012,33 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
 
   defp maybe_order(query, _), do: query
 
+  defp fetch_activities_query_ap_ids_ops(opts) do
+    source_user = opts["muting_user"]
+    ap_id_relations = if source_user, do: [:mute, :reblog_mute], else: []
+
+    ap_id_relations =
+      ap_id_relations ++
+        if opts["blocking_user"] && opts["blocking_user"] == source_user do
+          [:block]
+        else
+          []
+        end
+
+    preloaded_ap_ids = User.outgoing_relations_ap_ids(source_user, ap_id_relations)
+
+    restrict_blocked_opts = Map.merge(%{"blocked_users_ap_ids" => preloaded_ap_ids[:block]}, opts)
+    restrict_muted_opts = Map.merge(%{"muted_users_ap_ids" => preloaded_ap_ids[:mute]}, opts)
+
+    restrict_muted_reblogs_opts =
+      Map.merge(%{"reblog_muted_users_ap_ids" => preloaded_ap_ids[:reblog_mute]}, opts)
+
+    {restrict_blocked_opts, restrict_muted_opts, restrict_muted_reblogs_opts}
+  end
+
   def fetch_activities_query(recipients, opts \\ %{}) do
+    {restrict_blocked_opts, restrict_muted_opts, restrict_muted_reblogs_opts} =
+      fetch_activities_query_ap_ids_ops(opts)
+
     config = %{
       skip_thread_containment: Config.get([:instance, :skip_thread_containment])
     }
@@ -1032,15 +1058,15 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
     |> restrict_type(opts)
     |> restrict_state(opts)
     |> restrict_favorited_by(opts)
-    |> restrict_blocked(opts)
-    |> restrict_muted(opts)
+    |> restrict_blocked(restrict_blocked_opts)
+    |> restrict_muted(restrict_muted_opts)
     |> restrict_media(opts)
     |> restrict_visibility(opts)
     |> restrict_thread_visibility(opts, config)
     |> restrict_replies(opts)
     |> restrict_reblogs(opts)
     |> restrict_pinned(opts)
-    |> restrict_muted_reblogs(opts)
+    |> restrict_muted_reblogs(restrict_muted_reblogs_opts)
     |> Activity.restrict_deactivated_users()
     |> exclude_poll_votes(opts)
     |> exclude_visibility(opts)
index 07e677d29e866a275c42cfa270388016300353c0..a1b445f2f131dfad9f9973aadfb40d9c6d15307e 100644 (file)
@@ -130,7 +130,7 @@ defmodule Pleroma.Web.Streamer.Worker do
 
   defp should_send?(%User{} = user, %Activity{} = item) do
     %{block: blocked_ap_ids, mute: muted_ap_ids, reblog_mute: reblog_muted_ap_ids} =
-      User.related_ap_ids(user, [:block, :mute, :reblog_mute])
+      User.outgoing_relations_ap_ids(user, [:block, :mute, :reblog_mute])
 
     recipient_blocks = MapSet.new(blocked_ap_ids ++ muted_ap_ids)
     recipients = MapSet.new(item.recipients)