From 555edd01abf62b74c14c30caf82d77a80a93e72c Mon Sep 17 00:00:00 2001 From: Ivan Tashkinov Date: Wed, 20 Nov 2019 12:19:07 +0300 Subject: [PATCH] [#1335] User AP ID relations fetching performance optimizations. --- lib/pleroma/notification.ex | 37 ++++++++++++++---- lib/pleroma/user.ex | 11 ++++-- lib/pleroma/web/activity_pub/activity_pub.ex | 40 ++++++++++++++++---- lib/pleroma/web/streamer/worker.ex | 2 +- 4 files changed, 70 insertions(+), 20 deletions(-) diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex index 15b3337f4..d4b6eb3b8 100644 --- a/lib/pleroma/notification.ex +++ b/lib/pleroma/notification.ex @@ -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 @@ def changeset(%Notification{} = notification, attrs) 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 @@ def for_user_query(user, opts \\ []) 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 @@ defp exclude_blocked(query, user) 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) diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 615f1b725..4b53dce13 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -1158,11 +1158,14 @@ def subscribed_to?(user, %{ap_id: ap_id}) 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) diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 61b7f9280..b24139117 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -884,7 +884,7 @@ defp restrict_reblogs(query, _), do: query 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 @@ defp restrict_muted(query, %{"muting_user" => %User{} = user} = opts) 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 @@ defp restrict_pinned(query, %{"pinned" => "true", "pinned_activity_ids" => ids}) 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 @@ defp maybe_order(query, %{order: :asc}) 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 @@ def fetch_activities_query(recipients, opts \\ %{}) 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) diff --git a/lib/pleroma/web/streamer/worker.ex b/lib/pleroma/web/streamer/worker.ex index 07e677d29..a1b445f2f 100644 --- a/lib/pleroma/web/streamer/worker.ex +++ b/lib/pleroma/web/streamer/worker.ex @@ -130,7 +130,7 @@ defp do_stream(%{topic: topic, item: item}) 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)