FollowingRelationship storage & performance optimizations (state turned ecto_enum-driven integer, reorganized indices etc.).

This commit is contained in:
Ivan Tashkinov 2020-03-28 18:49:03 +03:00
commit be9d18461a
17 changed files with 128 additions and 45 deletions

View file

@ -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