WIP: preloading of user relations for timeline/statuses rendering (performance improvement).

This commit is contained in:
Ivan Tashkinov 2020-03-22 21:51:44 +03:00
commit c2e415143b
4 changed files with 160 additions and 19 deletions

View file

@ -10,6 +10,19 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
alias Pleroma.Web.MastodonAPI.AccountView
alias Pleroma.Web.MediaProxy
def test_rel(user_relationships, rel_type, source, target, func) do
cond do
is_nil(source) or is_nil(target) ->
false
user_relationships ->
[rel_type, source.id, target.id] in user_relationships
true ->
func.(source, target)
end
end
def render("index.json", %{users: users} = opts) do
users
|> render_many(AccountView, "show.json", opts)
@ -35,21 +48,50 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
%{}
end
def render("relationship.json", %{user: %User{} = user, target: %User{} = target}) do
follow_state = User.get_follow_state(user, target)
def render(
"relationship.json",
%{user: %User{} = reading_user, target: %User{} = target} = opts
) do
user_relationships = Map.get(opts, :user_relationships)
follow_state = User.get_follow_state(reading_user, target)
# TODO: add a note on adjusting StatusView.user_relationships_opt/1 re: preloading of user relations
%{
id: to_string(target.id),
following: follow_state == "accept",
followed_by: User.following?(target, user),
blocking: User.blocks_user?(user, target),
blocked_by: User.blocks_user?(target, user),
muting: User.mutes?(user, target),
muting_notifications: User.muted_notifications?(user, target),
subscribing: User.subscribed_to?(user, target),
followed_by: User.following?(target, reading_user),
blocking:
test_rel(user_relationships, :block, reading_user, target, &User.blocks_user?(&1, &2)),
blocked_by:
test_rel(user_relationships, :block, target, reading_user, &User.blocks_user?(&1, &2)),
muting: test_rel(user_relationships, :mute, reading_user, target, &User.mutes?(&1, &2)),
muting_notifications:
test_rel(
user_relationships,
:notification_mute,
reading_user,
target,
&User.muted_notifications?(&1, &2)
),
subscribing:
test_rel(
user_relationships,
:inverse_subscription,
target,
reading_user,
&User.subscribed_to?(&2, &1)
),
requested: follow_state == "pending",
domain_blocking: User.blocks_domain?(user, target),
showing_reblogs: User.showing_reblogs?(user, target),
domain_blocking: User.blocks_domain?(reading_user, target),
showing_reblogs:
not test_rel(
user_relationships,
:reblog_mute,
reading_user,
target,
&User.muting_reblogs?(&1, &2)
),
endorsed: false
}
end
@ -93,7 +135,12 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
}
end)
relationship = render("relationship.json", %{user: opts[:for], target: user})
relationship =
render("relationship.json", %{
user: opts[:for],
target: user,
user_relationships: opts[:user_relationships]
})
%{
id: to_string(user.id),

View file

@ -13,6 +13,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
alias Pleroma.Object
alias Pleroma.Repo
alias Pleroma.User
alias Pleroma.UserRelationship
alias Pleroma.Web.CommonAPI
alias Pleroma.Web.CommonAPI.Utils
alias Pleroma.Web.MastodonAPI.AccountView
@ -70,11 +71,34 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
present?(user && user.ap_id in (object.data["announcements"] || []))
end
def render("index.json", opts) do
replied_to_activities = get_replied_to_activities(opts.activities)
opts = Map.put(opts, :replied_to_activities, replied_to_activities)
defp user_relationships_opt(opts) do
reading_user = opts[:for]
safe_render_many(opts.activities, StatusView, "show.json", opts)
if reading_user do
activities = opts[:activities]
actors = Enum.map(activities, fn a -> get_user(a.data["actor"]) end)
UserRelationship.dictionary(
[reading_user],
actors,
[:block, :mute, :notification_mute, :reblog_mute],
[:block, :inverse_subscription]
)
else
[]
end
end
def render("index.json", opts) do
activities = opts.activities
replied_to_activities = get_replied_to_activities(activities)
opts =
opts
|> Map.put(:replied_to_activities, replied_to_activities)
|> Map.put(:user_relationships, user_relationships_opt(opts))
safe_render_many(activities, StatusView, "show.json", opts)
end
def render(
@ -107,7 +131,12 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
id: to_string(activity.id),
uri: activity_object.data["id"],
url: activity_object.data["id"],
account: AccountView.render("show.json", %{user: user, for: opts[:for]}),
account:
AccountView.render("show.json", %{
user: user,
for: opts[:for],
user_relationships: opts[:user_relationships]
}),
in_reply_to_id: nil,
in_reply_to_account_id: nil,
reblog: reblogged,
@ -253,11 +282,28 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
_ -> []
end
user_relationships_opt = opts[:user_relationships]
muted =
thread_muted? ||
Pleroma.Web.MastodonAPI.AccountView.test_rel(
user_relationships_opt,
:mute,
opts[:for],
user,
fn for_user, user -> User.mutes?(for_user, user) end
)
%{
id: to_string(activity.id),
uri: object.data["id"],
url: url,
account: AccountView.render("show.json", %{user: user, for: opts[:for]}),
account:
AccountView.render("show.json", %{
user: user,
for: opts[:for],
user_relationships: user_relationships_opt
}),
in_reply_to_id: reply_to && to_string(reply_to.id),
in_reply_to_account_id: reply_to_user && to_string(reply_to_user.id),
reblog: nil,
@ -270,7 +316,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
reblogged: reblogged?(activity, opts[:for]),
favourited: present?(favorited),
bookmarked: present?(bookmarked),
muted: thread_muted? || User.mutes?(opts[:for], user),
muted: muted,
pinned: pinned?(activity, user),
sensitive: sensitive,
spoiler_text: summary,