diff options
| author | Ivan Tashkinov <ivantashkinov@gmail.com> | 2020-03-28 18:49:03 +0300 | 
|---|---|---|
| committer | Ivan Tashkinov <ivantashkinov@gmail.com> | 2020-03-28 18:49:03 +0300 | 
| commit | be9d18461a5ed6bd835e2eba8d3b54ba61fc51fb (patch) | |
| tree | 0b5b199feab5cef526d365030213170c99fb9f0f /lib | |
| parent | 4e81b4b190161ebb0c496c682fa8e1e0c38a3903 (diff) | |
| download | pleroma-be9d18461a5ed6bd835e2eba8d3b54ba61fc51fb.tar.gz pleroma-be9d18461a5ed6bd835e2eba8d3b54ba61fc51fb.zip | |
FollowingRelationship storage & performance optimizations (state turned `ecto_enum`-driven integer, reorganized indices etc.).
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/pleroma/ecto_enums.ex | 6 | ||||
| -rw-r--r-- | lib/pleroma/following_relationship.ex | 43 | ||||
| -rw-r--r-- | lib/pleroma/user.ex | 18 | ||||
| -rw-r--r-- | lib/pleroma/user/query.ex | 6 | ||||
| -rw-r--r-- | lib/pleroma/web/activity_pub/mrf.ex | 2 | ||||
| -rw-r--r-- | lib/pleroma/web/activity_pub/transmogrifier.ex | 13 | ||||
| -rw-r--r-- | lib/pleroma/web/common_api/common_api.ex | 4 | ||||
| -rw-r--r-- | lib/pleroma/web/mastodon_api/views/account_view.ex | 6 | 
8 files changed, 70 insertions, 28 deletions
| diff --git a/lib/pleroma/ecto_enums.ex b/lib/pleroma/ecto_enums.ex index d9b601223..b98ac4ba1 100644 --- a/lib/pleroma/ecto_enums.ex +++ b/lib/pleroma/ecto_enums.ex @@ -11,3 +11,9 @@ defenum(UserRelationshipTypeEnum,    notification_mute: 4,    inverse_subscription: 5  ) + +defenum(FollowingRelationshipStateEnum, +  follow_pending: 1, +  follow_accept: 2, +  follow_reject: 3 +) diff --git a/lib/pleroma/following_relationship.ex b/lib/pleroma/following_relationship.ex index a9538ea4e..a28da8bec 100644 --- a/lib/pleroma/following_relationship.ex +++ b/lib/pleroma/following_relationship.ex @@ -13,7 +13,7 @@ defmodule Pleroma.FollowingRelationship do    alias Pleroma.User    schema "following_relationships" do -    field(:state, :string, default: "accept") +    field(:state, FollowingRelationshipStateEnum, default: :follow_pending)      belongs_to(:follower, User, type: CompatType)      belongs_to(:following, User, type: CompatType) @@ -27,6 +27,19 @@ defmodule Pleroma.FollowingRelationship do      |> put_assoc(:follower, attrs.follower)      |> put_assoc(:following, attrs.following)      |> validate_required([:state, :follower, :following]) +    |> unique_constraint(:follower_id, +      name: :following_relationships_follower_id_following_id_index +    ) +    |> validate_not_self_relationship() +  end + +  def state_to_enum(state) when is_binary(state) do +    case state do +      "pending" -> :follow_pending +      "accept" -> :follow_accept +      "reject" -> :follow_reject +      _ -> raise "State is not convertible to FollowingRelationshipStateEnum: #{state}" +    end    end    def get(%User{} = follower, %User{} = following) do @@ -35,7 +48,7 @@ defmodule Pleroma.FollowingRelationship do      |> Repo.one()    end -  def update(follower, following, "reject"), do: unfollow(follower, following) +  def update(follower, following, :follow_reject), do: unfollow(follower, following)    def update(%User{} = follower, %User{} = following, state) do      case get(follower, following) do @@ -50,7 +63,7 @@ defmodule Pleroma.FollowingRelationship do      end    end -  def follow(%User{} = follower, %User{} = following, state \\ "accept") do +  def follow(%User{} = follower, %User{} = following, state \\ :follow_accept) do      %__MODULE__{}      |> changeset(%{follower: follower, following: following, state: state})      |> Repo.insert(on_conflict: :nothing) @@ -80,7 +93,7 @@ defmodule Pleroma.FollowingRelationship do    def get_follow_requests(%User{id: id}) do      __MODULE__      |> join(:inner, [r], f in assoc(r, :follower)) -    |> where([r], r.state == "pending") +    |> where([r], r.state == ^:follow_pending)      |> where([r], r.following_id == ^id)      |> select([r, f], f)      |> Repo.all() @@ -88,7 +101,7 @@ defmodule Pleroma.FollowingRelationship do    def following?(%User{id: follower_id}, %User{id: followed_id}) do      __MODULE__ -    |> where(follower_id: ^follower_id, following_id: ^followed_id, state: "accept") +    |> where(follower_id: ^follower_id, following_id: ^followed_id, state: ^:follow_accept)      |> Repo.exists?()    end @@ -97,7 +110,7 @@ defmodule Pleroma.FollowingRelationship do        __MODULE__        |> join(:inner, [r], u in User, on: r.following_id == u.id)        |> where([r], r.follower_id == ^user.id) -      |> where([r], r.state == "accept") +      |> where([r], r.state == ^:follow_accept)        |> select([r, u], u.follower_address)        |> Repo.all() @@ -157,4 +170,22 @@ defmodule Pleroma.FollowingRelationship do        fr -> fr.follower_id == follower.id and fr.following_id == following.id      end)    end + +  defp validate_not_self_relationship(%Ecto.Changeset{} = changeset) do +    changeset +    |> validate_change(:following_id, fn _, following_id -> +      if following_id == get_field(changeset, :follower_id) do +        [target_id: "can't be equal to follower_id"] +      else +        [] +      end +    end) +    |> validate_change(:follower_id, fn _, follower_id -> +      if follower_id == get_field(changeset, :following_id) do +        [source_id: "can't be equal to following_id"] +      else +        [] +      end +    end) +  end  end diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index d9aa54057..6ffb82045 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -697,7 +697,7 @@ defmodule Pleroma.User do    @spec maybe_direct_follow(User.t(), User.t()) :: {:ok, User.t()} | {:error, String.t()}    def maybe_direct_follow(%User{} = follower, %User{local: true, locked: true} = followed) do -    follow(follower, followed, "pending") +    follow(follower, followed, :follow_pending)    end    def maybe_direct_follow(%User{} = follower, %User{local: true} = followed) do @@ -717,14 +717,14 @@ defmodule Pleroma.User do    def follow_all(follower, followeds) do      followeds      |> Enum.reject(fn followed -> blocks?(follower, followed) || blocks?(followed, follower) end) -    |> Enum.each(&follow(follower, &1, "accept")) +    |> Enum.each(&follow(follower, &1, :follow_accept))      set_cache(follower)    end    defdelegate following(user), to: FollowingRelationship -  def follow(%User{} = follower, %User{} = followed, state \\ "accept") do +  def follow(%User{} = follower, %User{} = followed, state \\ :follow_accept) do      deny_follow_blocked = Pleroma.Config.get([:user, :deny_follow_blocked])      cond do @@ -751,7 +751,7 @@ defmodule Pleroma.User do    def unfollow(%User{} = follower, %User{} = followed) do      case get_follow_state(follower, followed) do -      state when state in ["accept", "pending"] -> +      state when state in [:follow_pending, :follow_accept] ->          FollowingRelationship.unfollow(follower, followed)          {:ok, followed} = update_follower_count(followed) @@ -769,6 +769,7 @@ defmodule Pleroma.User do    defdelegate following?(follower, followed), to: FollowingRelationship +  @doc "Returns follow state as FollowingRelationshipStateEnum value"    def get_follow_state(%User{} = follower, %User{} = following) do      following_relationship = FollowingRelationship.get(follower, following)      get_follow_state(follower, following, following_relationship) @@ -782,8 +783,11 @@ defmodule Pleroma.User do      case {following_relationship, following.local} do        {nil, false} ->          case Utils.fetch_latest_follow(follower, following) do -          %{data: %{"state" => state}} when state in ["pending", "accept"] -> state -          _ -> nil +          %Activity{data: %{"state" => state}} when state in ["pending", "accept"] -> +            FollowingRelationship.state_to_enum(state) + +          _ -> +            nil          end        {%{state: state}, _} -> @@ -1282,7 +1286,7 @@ defmodule Pleroma.User do    def blocks?(%User{} = user, %User{} = target) do      blocks_user?(user, target) || -      (!User.following?(user, target) && blocks_domain?(user, target)) +      (blocks_domain?(user, target) and not User.following?(user, target))    end    def blocks_user?(%User{} = user, %User{} = target) do diff --git a/lib/pleroma/user/query.ex b/lib/pleroma/user/query.ex index 884e33039..ec88088cf 100644 --- a/lib/pleroma/user/query.ex +++ b/lib/pleroma/user/query.ex @@ -148,7 +148,7 @@ defmodule Pleroma.User.Query do        as: :relationships,        on: r.following_id == ^id and r.follower_id == u.id      ) -    |> where([relationships: r], r.state == "accept") +    |> where([relationships: r], r.state == ^:follow_accept)    end    defp compose_query({:friends, %User{id: id}}, query) do @@ -158,7 +158,7 @@ defmodule Pleroma.User.Query do        as: :relationships,        on: r.following_id == u.id and r.follower_id == ^id      ) -    |> where([relationships: r], r.state == "accept") +    |> where([relationships: r], r.state == ^:follow_accept)    end    defp compose_query({:recipients_from_activity, to}, query) do @@ -173,7 +173,7 @@ defmodule Pleroma.User.Query do      )      |> where(        [u, following: f, relationships: r], -      u.ap_id in ^to or (f.follower_address in ^to and r.state == "accept") +      u.ap_id in ^to or (f.follower_address in ^to and r.state == ^:follow_accept)      )      |> distinct(true)    end diff --git a/lib/pleroma/web/activity_pub/mrf.ex b/lib/pleroma/web/activity_pub/mrf.ex index a0b3af432..f54647945 100644 --- a/lib/pleroma/web/activity_pub/mrf.ex +++ b/lib/pleroma/web/activity_pub/mrf.ex @@ -33,7 +33,7 @@ defmodule Pleroma.Web.ActivityPub.MRF do    @spec subdomain_match?([Regex.t()], String.t()) :: boolean()    def subdomain_match?(domains, host) do -    Enum.any?(domains, fn domain -> Regex.match?(domain, host) end) +    !!Enum.find(domains, fn domain -> Regex.match?(domain, host) end)    end    @callback describe() :: {:ok | :error, Map.t()} diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index d6549a932..37e485741 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -490,7 +490,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do             {_, {:ok, follower}} <- {:follow, User.follow(follower, followed)},             {_, {:ok, _}} <-               {:follow_state_update, Utils.update_follow_state_for_all(activity, "accept")}, -           {:ok, _relationship} <- FollowingRelationship.update(follower, followed, "accept") do +           {:ok, _relationship} <- +             FollowingRelationship.update(follower, followed, :follow_accept) do          ActivityPub.accept(%{            to: [follower.ap_id],            actor: followed, @@ -500,7 +501,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do        else          {:user_blocked, true} ->            {:ok, _} = Utils.update_follow_state_for_all(activity, "reject") -          {:ok, _relationship} = FollowingRelationship.update(follower, followed, "reject") +          {:ok, _relationship} = FollowingRelationship.update(follower, followed, :follow_reject)            ActivityPub.reject(%{              to: [follower.ap_id], @@ -511,7 +512,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do          {:follow, {:error, _}} ->            {:ok, _} = Utils.update_follow_state_for_all(activity, "reject") -          {:ok, _relationship} = FollowingRelationship.update(follower, followed, "reject") +          {:ok, _relationship} = FollowingRelationship.update(follower, followed, :follow_reject)            ActivityPub.reject(%{              to: [follower.ap_id], @@ -521,7 +522,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do            })          {:user_locked, true} -> -          {:ok, _relationship} = FollowingRelationship.update(follower, followed, "pending") +          {:ok, _relationship} = FollowingRelationship.update(follower, followed, :follow_pending)            :noop        end @@ -541,7 +542,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do           {:ok, follow_activity} <- get_follow_activity(follow_object, followed),           {:ok, follow_activity} <- Utils.update_follow_state_for_all(follow_activity, "accept"),           %User{local: true} = follower <- User.get_cached_by_ap_id(follow_activity.data["actor"]), -         {:ok, _relationship} <- FollowingRelationship.update(follower, followed, "accept") do +         {:ok, _relationship} <- FollowingRelationship.update(follower, followed, :follow_accept) do        ActivityPub.accept(%{          to: follow_activity.data["to"],          type: "Accept", @@ -564,7 +565,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do           {:ok, follow_activity} <- get_follow_activity(follow_object, followed),           {:ok, follow_activity} <- Utils.update_follow_state_for_all(follow_activity, "reject"),           %User{local: true} = follower <- User.get_cached_by_ap_id(follow_activity.data["actor"]), -         {:ok, _relationship} <- FollowingRelationship.update(follower, followed, "reject"), +         {:ok, _relationship} <- FollowingRelationship.update(follower, followed, :follow_reject),           {:ok, activity} <-             ActivityPub.reject(%{               to: follow_activity.data["to"], diff --git a/lib/pleroma/web/common_api/common_api.ex b/lib/pleroma/web/common_api/common_api.ex index 2646b9f7b..d530da42c 100644 --- a/lib/pleroma/web/common_api/common_api.ex +++ b/lib/pleroma/web/common_api/common_api.ex @@ -42,7 +42,7 @@ defmodule Pleroma.Web.CommonAPI do      with {:ok, follower} <- User.follow(follower, followed),           %Activity{} = follow_activity <- Utils.fetch_latest_follow(follower, followed),           {:ok, follow_activity} <- Utils.update_follow_state_for_all(follow_activity, "accept"), -         {:ok, _relationship} <- FollowingRelationship.update(follower, followed, "accept"), +         {:ok, _relationship} <- FollowingRelationship.update(follower, followed, :follow_accept),           {:ok, _activity} <-             ActivityPub.accept(%{               to: [follower.ap_id], @@ -57,7 +57,7 @@ defmodule Pleroma.Web.CommonAPI do    def reject_follow_request(follower, followed) do      with %Activity{} = follow_activity <- Utils.fetch_latest_follow(follower, followed),           {:ok, follow_activity} <- Utils.update_follow_state_for_all(follow_activity, "reject"), -         {:ok, _relationship} <- FollowingRelationship.update(follower, followed, "reject"), +         {:ok, _relationship} <- FollowingRelationship.update(follower, followed, :follow_reject),           {:ok, _activity} <-             ActivityPub.reject(%{               to: [follower.ap_id], diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex index 0efcabc01..f2dc2a9bd 100644 --- a/lib/pleroma/web/mastodon_api/views/account_view.ex +++ b/lib/pleroma/web/mastodon_api/views/account_view.ex @@ -71,7 +71,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do      followed_by =        if following_relationships do          case FollowingRelationship.find(following_relationships, target, reading_user) do -          %{state: "accept"} -> true +          %{state: :follow_accept} -> true            _ -> false          end        else @@ -81,7 +81,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do      # NOTE: adjust UserRelationship.view_relationships_option/2 on new relation-related flags      %{        id: to_string(target.id), -      following: follow_state == "accept", +      following: follow_state == :follow_accept,        followed_by: followed_by,        blocking:          UserRelationship.exists?( @@ -123,7 +123,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do            reading_user,            &User.subscribed_to?(&2, &1)          ), -      requested: follow_state == "pending", +      requested: follow_state == :follow_pending,        domain_blocking: User.blocks_domain?(reading_user, target),        showing_reblogs:          not UserRelationship.exists?( | 
